require 'rake'
するとshというメソッドが定義される。内部ではKernel.systemが使われており、Kernel.systemとよく似た振る舞いをするが、いくつかの機能が追加されている。ここではそれらの機能について解説する。
require 'rake'
sh "ruby -e 'puts :stdout; warn :stderr;'"
ruby -e 'puts :stdout; warn :stderr;'
stdout
stderr
実行に失敗するとデフォルトでRuntimeErrorが発生する
require 'rake'
sh 'ruby -e "exit 1"'
ruby -e "exit 1"
/home/vzvu3k6k/.anyenv/envs/rbenv/versions/2.2.0/lib/ruby/2.2.0/rake/file_utils.rb:66:in `block in create_shell_runner': Command failed with status (1): [ruby -e "fail"...] (RuntimeError)
(後略)
Kernel.systemや`と違い、コマンドが失敗した場合はRuntimeErrorが発生する。つまり、失敗時には勝手にタスクの実行が止まる。これによって、途中のステップが失敗したまま次の処理が実行されて意図しない結果になったり、処理が失敗したことにさえ気づかないといったトラブルを防ぐことができる。
ブロックで実行結果を受け取る
require 'rake'
sh "ruby -e 'exit 1'" do |ok, status|
p({ok: ok, status: status})
end
puts "例外は発生しない"
ruby -e 'exit 1'
{:ok=>false, :status=>#<Process::Status: pid 27598 exit 1>}
例外は発生しない
ブロックを渡すと、コマンドの実行結果(true/false)、コマンドの実行ステータス($?)を引数にして呼び出される。ブロックが渡された場合には、コマンドが失敗してもRuntimeErrorが発生しない。
オプション
引数の末尾にHashを付けることで、verbose, noopオプションを設定できる。
参考: Ruby リファレンスマニュアル - module FileUtils - オプションの説明
verbose
verboseが偽値だと実行するコマンドが表示されなくなる。
require 'rake'
puts "# default"
sh "echo foobar"
puts
puts "# verbose: false"
sh "echo foobar", verbose: false
# default
echo foobar
foobar
# verbose: false
foobar
noop
noopが偽値だとコマンドが実行されなくなる。
require 'rake'
sh "touch dummy", noop: true # コマンドが実行されない
puts File.exist? "dummy" # ファイルが作られていないのでfalseになる
verboseとnoopを同時に設定することもできる。
verboseとnoopのデフォルト値を設定する
verboseのデフォルト値はverboseメソッドで、noopのデフォルト値はnowriteメソッドで設定できる。
この設定値はshだけではなく、FileUtilsの他のメソッドにも適用される。
require 'rake'
verbose(false)
sh "表示されない" rescue nil
verbose(true) do
sh "verboseは#{verbose}になり、表示される" rescue nil
end
sh "ブロックを抜けるとverboseは元の状態に戻るので表示されない" rescue nil
sh "オプションを直接指定すると上書き可能", verbose: true rescue nil
Kernel.systemにオプションを渡す
Kernel.systemにオプションを渡すこともできる。引数の末尾のHashはverbose, noopのオプションと解釈されることに注意。
require 'rake'
begin
sh "pwd", {chdir: "/"}
rescue
# 末尾のHashはsystemへのオプションではなく
# verbose, noopのオプションと解釈されるので、
# <ArgumentError: no such option: chdir>が発生する。
p $!
end
# systemにオプションを渡すためには
# 常に末尾にverbose, noopオプションのためのHashを付けないといけない。
sh "pwd", {chdir: "/"}, {}
そのほか
RakeはRubyを起動するrubyというメソッドも提供している。動作はshに準ずる。
Rubyで外部コマンドを実行する方法については下記を参照。