Capistrano: execute / captureの使い方(ハマったよ)
Capistraのexecuteとcaptureについて 仕様が明確になったので綴ります。
結論
executeやcaptureを使う時はコマンド部分と、その他を分けましょう。
まぁわかりづらいので、(<シンボル> , "args")で書くのがお作法的に良さそう。
例)
◯ execute(:echo, "test")
◯ execute("echo", "test")
✕ execute("echo test")
カッコの有無は、Rubyによると引数が無い時はわざわざつけない。引数がある時はつけよう。(だったかな) 位なのでつけておいた方がくくりがわかりやすいかも?
背景
実行コマンドによって動き方が違うかった事を不審に思った。
例えば
- withinで括ると、本来指定したフォルダがカレントフォルダで動くはずなのに動かないことがあった。
- default_envを設定しているのに、効いていない。
原因
第一引数と、第二引数でコマンド部分をわけないと、色々なオプションが効かない。 それは、capistranoの実装がそうなってる。
例題
デフォルトのRuby(2.2.3)を自分で上書きして、違うバージョンのRuby(2.3.0)を使う。
# :default_envをセットすると実行時にkey=valueを環境変数に入れてくれる。 # $PATHには元々別のRuby(2.2.3)が通っている。今回はそれを上書き(2.3.0に)したかった。 set :default_env, { path: "/opt/user-ruby/bin:$PATH" }
をセットした状態で、
namespace : setup do task :test do run_locally do puts "Ruby -v :" + capture("ruby -v") puts "Ruby -v :" + capture(:ruby, "-v") end end end
を実行するとなんと、
** Execute setup:test Ruby -v :ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux] Ruby -v :ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
結果が違う。
どうやら、コマンド部分と引数部分にわけない場合にはdefault_envを使って暗黙的にバックグラウンドで
export key=value
をコマンドに足してくれるんだけど、そうじゃない場合は、to_sで返しちゃう。
この感じだと、withinとかwithとか効かなかった全部こいつのせい…。 シンボルで書くべきか、コマンドで書くべきか迷って、コマンドに寄せた時に、引数部分とわけずに書いてたのでハマってた様子。
# こんな感じでコマンドの変換をしている。 # 第一引数をコマンドだけにしないと、mapに含まれずに処理される def to_command return command.to_s unless should_map? within do umask do with do user do in_background do group do to_s end end end end end end end
ココで事前にロード済のコマンドmapに存在するかしないかを見ている。