この前に投稿した記事で今年変えてみたことを書きましたが、今度は今年に限らず自分で使っていて地味に便利だと思うことをまとめておこうと思います。
SSH接続先サーバーでtmuxを使いわける
SSH接続した先の環境でtmuxを使っているのですが、以下のようなことができるようにしています。
- tmuxは基本的に1つのセッションのみを使うので、もし既存のセッションがあればそれをアタッチする
- sshしてからtmux起動と2ステップかかるのが面倒なのでssh接続したら即座にtmuxの環境になるようにする
- ただし、たまにtmuxなしで接続することもあるので使い分けられるようにする
- tmux.confを間違ってtmuxが起動しなくなることもあるので...
実現方法は以下のとおりです。
まず、要件1を満たすためssh接続先の環境で、以下のようなコマンド(function)を用意します。
このtm
コマンドはtmuxを起動するためのコマンドです。既にtmuxのセッションがあればそれにattachし、なければ新規作成します。
function tm {
tmux has -t main #2> /dev/null
if [ "$?" -eq 0 ]; then
exec tmux attach -t main
else
exec tmux new -s main
fi
}
その上で、要件2,3はsshコマンドの実行方法で使い分けています。
# tmuxなしで通常のssh接続する場合
$ ssh serv
# 必ず新規セッションのtmuxを起動
$ ssh -t serv tmux
# 既存のセッションにアタッチしつつ起動
$ ssh -t serv tm
単にssh
でtmux
コマンドを実行してしまうとttyがないのでtmuxが起動できませんが、-t
オプションをつけてttyがある状態にすることでtmuxを起動できます。
Vimで選択範囲の変換処理をコマンド化する
Vimで決まった整形をするときに、複数の置換操作を一連で実行したいことがあります。
そういうときは以下のような感じでコマンド化できます。
" タブ区切りやCSVをMarkdown table形式に変換する
function! MdTable(...) range
let delim="\t"
if a:0 >= 1
let delim = a:1
end
let rng = a:firstline . "," . a:lastline
exec rng . 's/^\|$\|' . delim . '/|/g'
exec rng . 's/"//g'
exec rng . 'EasyAlign *|'
endf
command! -range -nargs=? MdTable silent <line1>,<line2>call MdTable(<f-args>)
" SQLのin句に指定するような形式にする
function! SqlList() range
let rng = a:firstline . "," . a:lastline
exec rng . 's/"//g'
exec rng . 's/^\|$/''/g'
exec rng . 's/$/,/'
endf
command! -range SqlList silent <line1>,<line2>call SqlList()
functionを範囲に対してcallしたら1行ずつに個別にfunctionが実行されます。
functionの末尾にrange
と記述することで、この動作を範囲全体に対して1回のみ実行されるにできます。
その上で、a:firstline
とa:lastline
で範囲に対して操作を行うコマンド文字列を作成し、exec
コマンドで実行しています。
functionをExコマンドで実行する方法は、command! -range
の行の通りです。
Rakeタスクを並列で実行する
私はログ分析をRakeで実装しているのですが、分析処理を手軽に並列実行するのにpwrake
というコマンドを使わせていただいています。
これは何かの研究用途で作成されたツールのようですが、汎用的に使うことができます。
内容については上記の公式説明を見ていただくのでも十分だとは思いますが、ざっと紹介します。
ログの分析をRakeで行うときに以下のような感じでRakefile
を作成します。
# 出力先フォルダ
directory "out"
# "in"フォルダ内の入力となるログファイルをループ
out_files = Dir.glob('in/*.log').map { |filepath|
out_file = File.join("out", filepath)
# 出力ファイル生成タスクを動的に定義
file out_file => ["out", filepath] do |t|
# filepath のファイルから、out_file を生成する処理を実装する
`cat #{filepath} | grep "GET" > #{out_file}` # 例
end
}
file "result.log" => out_files do |t|
# 複数の出力ファイルを一つにまとめる処理を実装する
`cat #{out_files.join(' ')} > #{t.name}` # 例
end
desc "parse logs"
task :log => "result.log"
これは、入力となるログの1ファイルごとを加工するためのfile
タスクを定義し、それらを最後に1つにまとめてresult.log
というファイルを生成するような処理になっています。
これを普通のrake
で実行するとout_files
に入っているタスクを順番に実行することになります。
ここで、rake
と同じ要領でpwrake
でタスクを実行するとout_files
部分を並列に実行することができます。
# 順番に1ファイルずつ処理
$ rake log
# out_filesのタスクを並列実行
$ pwrake log
# 並列数の上限を決めて実行
$ pwrake -j 3 log # 3並列で実行
pwrake
は普通のrake
コマンドの代わりに使えて、Rakefileに特殊な記述をすることもなく、決まった並列数で並列処理を実行してくれます。
ただ、今回記事を書くにあたってあらためてrake(v11.2.2)コマンドを調べると、multitask
というタスク生成機能とrake
の-j
オブションでそこまで遜色なく同じことができそうです。
私がpwrake
を使い始めたころは、rake
では並列数の上限を指定できなかったんですが、今は変わっているようです。
MacのJISキーボードを仮想的にUSキーボード配列にする
私はUSキーボード配列をメインで使っているのですが、いま会社で支給されているMacBookがJISキーボードです。
JISキーボードでは操作に色々と困るので KarabinerとSeilというツールでJISキーボードの配列をUSキーボードに近づけて対応しています。
Karabiner の設定において、以下にチェックをつけます。
- [For Japanese]-[Change Keyboard Layout]-[Use Japanese Keyboard as US Keyboard]
- [For Japanese]-[Change EISUU Key]-[EISUU to Command_L (+ When you type EISUU only, send EISUU)]
- [For Japanese]-[Change KANA Key]-[KANA to Command_R (+ When you type KANA only, send KANA)]
次に、以下の手順でキーボードの左下の「caps」キーを「fn」キーに変えます。
- OSXの[システム環境設定]->[キーボード]画面で、[修飾キー...]ボタンをクリックし、出てきたダイアログで[Caps Lockキー]欄を「アクションなし」に設定する
- Seilを起動し、[Setting]画面で[Change the caps lock key]-[Change the caps lock key]にチェックをいれ、[keycode]欄に「63」(Fnキーのキーコード)を入力する
物理的な配置の問題で変えられないキーもありますが、実用的な状態にはできます。
- 参考: MacでCapsキーをFnキーに変更する方法 - ttaka/tmp
追記: 2017/02/13
Mac OSX Sierra 10.12 では、2017/02/13 現在では karabinerが動きませんので、上記の方法は実現できません。
次期版として https://github.com/tekezo/Karabiner-Elements を作成中のようです。
Karabiner-Elements でも設定ファイルを上手く作ると実現できるっぽいのですが、その設定ファイルの内容がよくわからず...
https://github.com/tekezo/Karabiner-Elements/issues/55