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アプリにセキュリティ問題を起こしたくなければ、これらのコマンドに何らかのユーザー入力を渡さないようにしてください。