Rubyから外部コマンドを実行したい場合…
…例えばHTMLファイルをPDFに変換するwkhtmltopdfなど。
使用できるRubyメソッドは幾つかあります。
これらのメソッドを一緒に探ってみましょう!
Rubyシステムメソッド
Rubyシステムメソッドは、外部コマンドを実行する最も簡単な方法です。
次のようになります。
また、コマンドの実行が完了するまで Ruby プログラムを待たせます。
-
trueコマンドが動作した場合 -
falseコマンドがエラーコードを返した場合 -
nilコマンド実行に失敗(コマンドが見つからない)場合
グローバル変数 $? で最後に実行した外部コマンドの終了ステータスコードを取得することが可能です。 このステータスコードから、なぜコマンドが失敗したのか、より詳しい情報を得ることができます。
シェル拡張とは
外部コマンドをsystemで実行すると、「シェル拡張」効果が得られます。
シェル拡張とはシェル (sh/bash/zsh) がいくつかの特殊文字(*, ?, ")# "best"
This will not change the current environment of your Ruby application.
%x / Kernel#`
If you want to get the output from the command you're running, instead of displaying it then you can use %xまたは Kernel#`メソッドを取ることです。
これらは同じことをします。
`ls`
以下に例を示します。%xを使った別の例:
%x|ls|
これら二つの例は ls コマンドの出力を文字列で返します。
注意すべきは、スレッドの中で実行しなければ、コマンドが終了するまでまだ待たされることです。
How to Use Fork + Exec To Run External Commands on a Separate Process
フォークは現在のプロセス (Ruby アプリ) のコピーを作成し、そのコピーを exec を使用して別のプロセスに置き換えることができます。
これは Unix の世界でよく使われるパターンです。
これがどのように動作するか説明します。
fork { exec("ls") }
これは別のプロセスで ls を実行し & その出力を表示します。
重要:
forkなしでexecを使用すると、現在のプロセスを置き換えることになります。
これは、Rubyプログラムが終了することを意味します。
How to Use the Popen Method For Two Way Communication With An External Program
もし必要なら:
- More control over the process
- Two two-way communication
そして IO.popen method is what you looking at the following to.
次の例では、popen メソッドを使って irb プロセスを起動し、& 入力を送り、出力を読みます。
r = IO.popen("irb", "r+")r.write "puts 123 + 1\n"3.times { puts r.gets }r.write "exit\n"
この r 変数は IO オブジェクトで、これは通常のファイルのように & 書いたり読んだりできることを意味しています。
また、popenを使用すると、外部コマンドは独自のプロセスで実行されるので、スレッドで実行する必要はありません。
また、標準ライブラリにpopen3メソッドがあります。
通常の popen との違いは、通常の出力 & エラー メッセージを別の IO オブジェクトに分割する点です。
まとめ
Rubyで外部コマンドと対話できるさまざまな方法について学びました。
これらには注意してください!
Rubyアプリにセキュリティ問題を起こしたくなければ、これらのコマンドに何らかのユーザー入力を渡さないようにしてください。