多くのプログラミング言語には、外部コマンドを実行するための機能が備わっています。
プログラムからOSのコマンドを実行することによって、プログラムでは複雑になってしまう処理を簡単に行うことが出来ることもあります。
本記事では、Rubyのコマンド実行について解説します。
記事内に記載しているプログラムは、Ruby2.7.1を使って動作確認をしています。
Rubyの外部コマンド実行方法7選
Rubyの外部コマンド実行方法について、以下の内容を解説します。
- Kernel.#systemを使う方法
- バッククォートを使う方法
- %記法を使う方法
- Kernel.#execを使う方法
- IO.popenを使う方法
- Open3.capture3を使う方法
- Open3.popen3を使う方法
Kernel.#systemを使う方法
結果の取得が不要で手軽にコマンドを実行するのに、systemを使うことができます。
result = system('date') # -> 2021年 1月 14日 木曜日 10:49:33 JST p result # -> true
- 実行結果:成功時はtrue、失敗時はfalse、コマンドを実行できない場合はnilを返す。
- 例外の発生:引数オプションの :exceptionにtrueを指定することで発生させることが可能。
- 終了ステータス:$?で取得できる。
- 標準出力:取得できない。
- 標準エラー出力:取得できない。
- 標準入力:渡せない。
バッククォートを使う方法
標準出力を結果として取得したい場合に手軽に使うことができます。
result = `date` p result # -> "2021年 1月 14日 木曜日 10:49:33 JST\n"
- 実行結果:標準出力を返す。
- 例外の発生:コマンドを実行できない場合や失敗した場合に発生。
- 終了ステータス:$?で取得できる。
- 標準出力:戻り値として取得できる。
- 標準エラー出力:取得できない。
- 標準入力:渡せない。
%記法を使う方法
バッククォートを使う方法は、%記法でも記述できます。
result = %x(date) p result # -> "2021年 1月 14日 木曜日 10:49:33 JST\n"
実行結果や入出力などの情報は、バッククォートを使う方法と同じです。
Kernel.#execを使う方法
execでの実行は起動に成功するとこのメソッドから戻らなくなるので注意が必要です。
exec('date') # -> 2021年 1月 14日 木曜日 10:49:33 JST
- 実行結果:返さない。
- 例外の発生:コマンドを実行できない場合や失敗した場合に発生。
- 終了ステータス:取得できない。
- 標準出力:取得できない。
- 標準エラー出力:取得できない。
- 標準入力:渡せない。
IO.popenを使う方法
標準入力を渡したい場合は、IO.popenを使うことができます。
result = IO.popen("cat", "r+") {|io| io.puts "Hello" io.close_write io.gets } p result # -> "Hello\n"
- 実行結果:標準出力を返す。
- 例外の発生:コマンドを実行できない場合や失敗した場合に発生。
- 終了ステータス:$?で取得できる。
- 標準出力:戻り値として取得できる。
- 標準エラー出力:オプションで指定することで可能。
- 標準入力:渡せる。
Open3.capture3を使う方法
requireが必要となりますが、様々な機能を提供している実行方法です。
require "open3" result, err, status = Open3.capture3("date") p result # -> "2021年 1月 14日 木曜日 10:49:33 JST\n" p err # -> "" p status # -> #<Process::Status: pid 21841 exit 0>
- 実行結果:標準出力、標準エラー出力、終了ステータスを返す。
- 例外の発生:コマンドを実行できない場合や失敗した場合に発生。
- 終了ステータス:戻り値として取得できる。
- 標準出力:戻り値として取得できる。
- 標準エラー出力:戻り値として取得できる。
- 標準入力:オプションの:stdin_dataから渡せる。
Open3.popen3を使う方法
コマンドの実行中に標準出力から結果を随時取得したい場合には、Open3.popen3を使います。
require "open3" Open3.popen3("cat") do |input, output, err, status| input.write "Hello" input.close output.each do |line| p line end # -> "Hello" err.each do |line| p line end # -> (なし) p status.value # -> #<Process::Status: pid 21845 exit 0> end
- 実行結果:標準入力へのパイプ、標準出力へのパイプ、標準エラー出力へのパイプ、プロセスを待つためのスレッドを返す。
- 例外の発生:コマンドを実行できない場合や失敗した場合に発生。
- 終了ステータス:プロセスを待つためのスレッドから取得できる。
- 標準出力:戻り値のパイプから取得できる。
- 標準エラー出力:戻り値のパイプから取得できる。
- 標準入力:戻り値のパイプから渡せる。
まとめ
Rubyの外部コマンド実行方法についてまとめると、以下となります。
- Rubyの外部コマンド実行方法は、たくさんの方法が提供されている。
- 手軽に実行して、結果を取得したい場合はバッククォートを使う方法がおすすめ。
- 標準入力を扱う場合やリアルタイムに結果を取得したい場合は、open3モジュールのcapture3またはpopen3を使う。
マルチOSで使用するアプリケーションの場合は、コマンドの違いを考慮する必要があります。
また、コマンドインジェクション等の脆弱性にも注意が必要です。
ですが、OSコマンドを利用することで、プログラムで実現できる範囲が広がるので、必要な場合には使ってみてはいかがでしょうか。
今回は、Rubyの外部コマンド実行方法7選を解説しました。
以上、参考になれば幸いです。
コメント