tmux ♡ ssh な生活

ターミナルマルチプレクサ Advent Calendar 2011の17日目です。
16日目はglidenoteさんのtmuxの外観をカスタムして、運用と開発を加速させるでした。

さてみなさん、screenとtmuxどっちを使っていますか?
screenとtmuxどっちが好きですか?

僕はtmuxを使っていますが、screenが好きになりそうです。
11日目のyoshikawさんのlayoutに関しる記事をみて、tmuxのwindow-paneよりもlayoutの方が便利そうだなぁと思ってしまいました><
でもtmuxの見た目(?)の方が好きなのでやっぱりtmuxを使うことにします><

さて、前置きはこれぐらいにして本題へ。
ここからの話はtmux前提ですが、tmuxでできることは大概screenでもできるはずなので適宜おきかえていただけると。
(最近screen使ってないのでどうか分かりませんが…)

sshコマンドをキーバインドで呼びだす

みなさんは開発環境やら、本番環境やらにsshで入ってほげほげするあれげな人ばっかりだと思うのですが、大体sshするときって別window使ったり、paneを切ってやったりしますよね?
でもわざわざnew-windowやったり、split-paneしてからsshとかってダサくてキモいですよね。
なので、.tmux.confに以下のような設定をしてその辺一発でできちゃうようにしましょう。

# ssh
unbind s
bind-key s command-prompt "new-window -n ssh 'ssh -t %1'"
bind-key ^s command-prompt "split-window -h 'ssh -t %1'"
bind-key S command-prompt "split-window 'ssh -t %1'"

キーバインドは自分の好みに合わせてもらえればいいです。
tmuxだとwindowとpaneがあるのでどれがどのキーバインドだったか自分でも忘れてしまうというのが玉に瑕です…

っていうか、本番環境とかセキュリティ的にgateway経由じゃないと入れねーよJKという方は、

# gateway
unbind g
bind-key ^g command-prompt "split-window -h 'ssh -t gateway \"ssh -t %1\"'"
bind-key G command-prompt "split-window 'ssh -t gateway \"ssh -t %1\"'"
bind-key g command-prompt "new-window -n actual 'ssh -t gateway \"ssh -t %1\"'"

とかしておけばいいと思います。
クォートをエスケープしないといけないところがキモです。
僕の場合は本番はsshしてからtmux使うようにしているので使わないですけど><

起動sessionの設定を.tmux.confに書いて最初からssh

上で書いた設定のように、tmuxではtmuxコマンド実行時に任意のshellコマンド(クォートで括っているところ)を実行可能です。
それでそのプロセスが死んだらwindowやらpaneやらも閉じてくれます。

.tmux.confにはsessionの設定も書けるので以下のように書いておけば、
kill-serverした後でも同じようにsshしたり、pane作ったりしたものでも最初から使えちゃうというわけです。
tmux起動時のデフォルトの設定みたいな感じでしょうか。

# custom session
new-session -s mobcov 'ssh -t develop'
split-window -h 'ssh -t develop'
split-window 'ssh -t develop'
select-pane -t 0
rename-window develop
new-window -n ssh 'ssh -t develop "ssh -t stage"'
split-window -h 'ssh -t develop "ssh -t stage"'
split-window 'ssh -t develop "ssh -t stage"'
select-pane -t 0
new-window -n local
split-window
select-pane -t 0

これでtmux attatchすればいつでもいい感じにtmuxできますね!

まとめ

以上、超簡単で申し分けない感じですが、.tmux.confに書いているssh関連の設定を紹介してみました。
でも自分は上記の設定のおかげでかなり便利にtmuxを使えています。
(これと同じことがscreenでもできるかどうかはよく分からないので、今後のscreenハードコアな方に期待です><)
みなさんの日常業務に少しでもお役にたてたなら幸いです。

おまけ

dodaさんの15日目のリモートの tmux でコピーした内容のローカルのクリップボードへの反映ってMacのTerminalやiTerm2でもできるんですかね?
いまはマウスでselectとしてコピーやってるんですが、split-paneしてるとマウスselectが隣りのpaneにいっちゃってうまくできない><
なのでそのためにkill-paneしたりしている今日この頃です。
そういう意味でもscreenのlayoutの方がいいかもと思ったり…

Capistranoで個人開発環境用のVMをセットアップ

最近ははがないラジオを聞きながら生活しています。
どうも。

職場ではmacminiとMacBookAirで開発してるんですが、忙しいときに限ってマシントラブルになったりしますよね。
この間なんか2台がほぼ同時に入院しちゃって泣きそうになりました…

開発はMacFusionにいれたVMでやっているんですが、マシンのサルベージができなくなったりする、雛形のVMからいろいろインストールしたりしないといけません。

面倒ですね。

そこでCapistranoでその辺のtask作ってあとコマンド一発セットアップできないかと考えています。
実際まだcapfile途中なんですが。

基本はCPAN Moduleいれるのと、rpmforgeいれてgitやtmuxいれたり、zshvimはsourceからbuildしたり、hostsやsshの公開鍵入れたりとか。
あとは開発repositoryからceckoutしたり、必要なcronの設定もCapistranoでやろうと思ってます。

これできたらいつマシントラブル起こっても平気だぞっと。

でもローカルのMacのセットアップがまた色々大変なのは変わらんですが…
そこもコマンドでいけるやつはcapfile作るかなぁ、homebrewとかperlbrewとか。
さすがに.appをダウンロード、インストールは…
wgetすればいいかもしれないけど。

あとVMWareToolsのinstallスクリプトが対話型なんですが、あれ全部enterでいいんでCapistranoから操作できなかなーと悩んでいます。

git-nowをhomebrew本家にpull-requestした、それFormulaについてあれ

たまゆらにでてくるスイーツが毎回おいそうで固唾を飲んでいる今日このごろです。

id:sinsokuさんに許可をいただいて、サブコマンドほげほげしたgit-nowをhomebrewに追加すべくpull-requestを送りました。

https://github.com/mxcl/homebrew/pull/8169

それで当然Formulaを書いたんですが、色々try and errorがあったのでここに書きます。

続きを読む

git-nowをサブコマンド化してみた

最近プロジェクトのVCSSubversionからGitに移行して、ホクホク顔でgit stashしまくっている今日この頃ですが、みなさんいかがおすごしでしょうか?

さてそんなお寒い時候(?)の挨拶はおいといて、hotfixとかfeatureのbranch上でgit-now使いまくっているわけなんです。
git-nowには--rebaseってオプションがあって、あとからcommitをいじっちゃうわけなんですが、それにさらにオプションはやしたり云々やってたらサブコマンド化したくなってやってしまいました><
homebrew化とかもしっちゃった関係(謎)でGitHub上にあげてるんですが、元々のscriptがgistでGitHubとしてforkできなくてid:sinsokuさん、すいません><

git-nowって?

temporaryのcommitを簡単にできるコマンドラインツールです。
詳しくはid:sinsokuさんの元ネタをみてください。

サブコマンドについて

いまのところrebaseとgrepというサブコマンドがあります。

rebase

rebaseは元々の--rebaseにいくつかオプションを加えたのと、引数でbranch名を指定できるようにしてます。
--rebaseつけるとrepository上の全てのコミットメッセージからgit-nowなコミットをgrepしてきちゃうわけなんですが、自分的にはいまのbranch上にあるgit-nowコミットだけrebaseしたいことがほとんどなので、branch名を与えると、いま自分がいるbranchと指定したbranchとの共通の先祖からgit-nowコミットをgrepしてくれます。

$ git now rebase master

git-nowコミットはtemporaryなんで普通は後から修正するんですが、間違ってそのメッセージがそのままpushされちゃってる場合なんかは、--rebaseする度に古〜いコミットもgrepに引っかかってきちゃうんで、これはかなり重宝してます><b

あとは--push|-pってオプションがあってrebaseのあとにgit pushをしてくれます。
手元でtest通ったらgit nowして、一通り機能ができたらgit now rebaseしてコメント修正後にremoteにpushって流れるになると思うんで、その辺を簡単にやるあれです。
remoteに一回もpushしていない場合、git pushできないんで、そういうときは--remote|-rオプションでpush先に指定できます。中では--set-upstreamやる感じですよ〜

$ git now rebase -p master
$ git now rebase -p -r origin master
grep

git-nowコミットをgrepして表示するサブコマンドです。
こいつもrebaseと同じように引数でbranch名を指定すると共通先祖からのgrepになります。
pushする前にgrepしてtemporaryコミットあったかな?って思ったときにサクっと確認できちゃうんです><

$ git now grep
$ git now grep master

インストール方法

GitHubのREADMEみてもらえば分かるんですが、Macでhomebrewな人は:

$ brew install https://github.com/iwata/git-now/raw/master/git-now.rb

それ以外の人は普通にgitでもってきてmake installでいけます。

shell scriptについて

今回はgit-flowのscriptを参考にしました。
ベースとなる部分はコピペです><

getoptのlong-optionとFormula

git-flowのパクりなので、shellのコマンドライン引数のパースにはshflagsっていうのを使っています。
helpとか書くのにかなり便利なんですが、Macだと--pushとかのlong-optionのパースがうまくいきませんでした。
-pはいけるんですが。
-pでいいっちゃいいんですが勝手にpushが走っちゃうんでできれば--pushとタイプ数が多くなる方が誤動作少なくできるんじゃないかと思ってlong-option動かねーのダメだなぁ…とか思ってました。
それでGoogle先生で色々調べてみるとshflagsのBTSFailed to parse long option on Mac OSX Snow Leopard with standard getoptっていうのを発見!しました。
それで一番下のやつをみると、

Final comment, for anyone having the same issue on Mac OS X, you can get the enhanced GNU getopt version via MacPorts (http://www.macports.org/).

$ sudo port install getopt
(after you installed MacPorts, see http://www.macports.org/install.php)

getoptのenhancedバージョンが必要だからMacPortsインスコすればいいお><bって書いてあります。
ってMacPortsかよ Σヾ(゜Д゜汗) …なのでhomebrewで同じのはないかな?って調べるとありました。gnu-getoptっていうのがそれらしいです。
(なのでFormulaのdepends_onにはgnu-getoptをいれてます、一応。)

ちなみに自分のgetoptがenhancedじゃないかどうかは以下を実行してみればわかります。

$ getopt --version

これで" --"って表示されたら--versionがパースできていないってことで普通のgetoptでバージョン情報が表示されたらenhancedってことになります。

そして早速インストール。

$ brew install gnu-getopt
$ getopt --version
 --

ってなんでやねん Σヾ(゜Д゜汗)
enhancedにならない><、whereしてみると、

$ where getopt
/usr/bin/getopt

あれ? homebrewでいれたやつじゃない、、、
gnu-getoptのFormulaをみてみると"keg_only"が指定されている!
なので以下のようにlinkを貼る。

$ brew link gnu-getopt
$ getopt --version
getopt (enhanced) 1.1.4

ktkr!!
これで--pushオプションが使えるようになりました。この辺の色々をやらないといけないので上のコマンドでは-pを使っています。でも間違い易いと思うので、使える環境なら--pushを打つようにしといた方が安全だと思います。

Formulaでは

  # for longopt
  depends_on 'gnu-getopt'

  def install
    system "make", "prefix=#{prefix}", "install"
    system "brew ln gnu-getopt"
  end

ってやっていてinstallの中で無理矢理linkさせてるんですが、これだとupdateのときいちいちbrew unlinkしないとinstallにコケるのでなんかイマイチです。
もしこの辺うまくできる方法を知っている人がいらっしゃったら教えてください><

追記

rebaseの後にpushとかしようとしてもrebase -iやっちゃうとshell抜けちゃって返ってこないですね><

…ということで--pushとかのオプション再考しまふ。。

追記2

とりあえず、--pushとか--removeオプションは廃止。

あと--author|-aオプションで自分のコミットだけから、grepしたり、rebaseすることができるようにした。

jQueryのFlexgrid pluginをカスタマイズ

table表示のためにjQueryのFlexgridというpluginを使っています。
Flexigrid - Web 2.0 Javscript Grid for jQuery
http://www.flexigrid.info/

その名の通り、Flexでのグリッド表示をJSで実現するという便利なpluginです。
見た目も当り触りのないUIで機能的もイカすので使っています。

UIは基本英語で、オプションでその辺りはある程度いじれるのですが、
QuickSearchのUIだけオプションがなくいじることができません。

この辺りを日本語化するために仕方なくコアをいじることにしました。
オプションを追加してform作成の箇所を変数で文字列をとるようにしました。

例によってJSが圧縮されたソースでも提供されているので、
変更したJSを再び圧縮しなければなりません。
当初はTMのYUI Compressor Bundleで圧縮しようとしたのですが、
うまく動作しなかったので以下のツールを使いました。
/packer/
http://dean.edwards.name/packer/

どうやら元々のFlexgridもこれを使って圧縮しているようなので、
これでいいかなと思います。

P.S.
Flexgridの更新が結構止まっているのが心配です。

Dbfinder Plugin

symfonyのPluginにDbfinderっていうものがあって、
jQueryのflexgrid Pluginでtable表示するときに鯖側で使ってます。
whereというメソッドでSQLのfilterを定義できるんですが、
comparisonとしてINが用意されていないようですorz
READMEを読んでもINの記述がなかったので、
いまはJOINで代替しています。
INは使えないのかな〜