サーチ…


前書き

オペレーティングシステムとのやり取りにはさまざまな方法があります。 Rubyの中から、シェル/システムコマンドやサブプロセスを実行できます。

備考

Exec:
Execは機能が非常に限られており、実行するとRubyプログラムを終了してコマンドを実行します。

システムコマンド:
システムコマンドは、現在のプロセスを置き換えるのではなく、サブシェルで実行され、trueまたはnillを返します。システムコマンドは、バックティックと同様に、メインアプリケーションがシステム操作の結果が完了するまで待機するブロッキング操作です。ここでの主な操作では、子プロセスから発生した例外のキャプチャについて心配する必要はありません。

スクリプトがエラーなしで実行されたかどうかによって、システム関数の出力は常にtrueまたはnilになります。したがって、スクリプトの実行中に発生するすべてのエラーは、アプリケーションに渡されません。メインの操作では、子プロセスから発生した例外をキャプチャすることを心配する必要はありません。この場合、子プロセスが例外を発生させたため、出力はnilになります。
これはブロッキング操作で、Rubyプログラムはコマンドの処理が完了するまで待ってから実行します。
システム操作はforkを使用して現在のプロセスをforkし、execを使用して所定の操作を実行します。

バックティック( `):
バックティック文字は通常、キーボードのエスケープキーの下にあります。 Backticksは、現在のプロセスを置き換える代わりにサブシェルで実行され、コマンドの結果を返します。
ここではコマンドの出力を得ることができますが、例外が生成されるとプログラムはクラッシュします。
サブプロセスに例外がある場合、その例外はメインプロセスに与えられ、例外が処理されないとメインプロセスが終了することがあります。これはブロッキング操作で、Rubyプログラムはコマンドの処理が完了するまで待ってから実行します。
システム操作はforkを使用して現在のプロセスをforkし、execを使用して所定の操作を実行します。

IO.popen:
IO.popenはサブプロセスで実行されます。ここでは、サブプロセス標準入力と標準出力がIOオブジェクトに接続されています。

Popen3:
Popen3では、標準入力、標準出力、および標準エラーにアクセスできます。
サブプロセスの標準入力と出力はIOオブジェクトに返されます。

$? ($ CHILD_STATUSと同じ)
backticks、system()または%x {}操作で使用することができ、最後に実行されたシステムのコマンドのステータスを表示します。
これは、 exitstatusおよびpidプロパティにアクセスするのにexitstatusです。

$?.exitstatus

Rubyでシェルコードを実行するための推奨される方法:

Open3.popen3またはOpen3.capture3:
Open3は実際にはRubyのspawnコマンドを使用しますが、はるかに優れたAPIを提供します。

Open3.popen3

Popen3はサブプロセスで実行され、stdin、stdout、stderr、およびwait_thrを返します。

require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3("sleep 5s && ls")
puts "#{stdout.read} #{stderr.read} #{wait_thr.value.exitstatus}"

または

require 'open3'
cmd = 'git push heroku master'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  puts "stdout is:" + stdout.read
  puts "stderr is:" + stderr.read
end

stdout is:stderr is:fatal:gitリポジトリ(または親ディレクトリのいずれでもない):.git

または

require 'open3'
cmd = 'ping www.google.com'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  while line = stdout.gets
    puts line
  end
end

出力されます:

www.google.com [216.58.223.36]に32バイトのデータをpingする:
216.58.223.36からの返信:バイト= 32時間= 16ms TTL = 54
216.58.223.36からの返信:バイト= 32時間= 10ms TTL = 54
216.58.223.36からの返信:バイト= 32時間= 21ms TTL = 54
216.58.223.36からの返信:バイト= 32時間= 29ms TTL = 54
216.58.223.36のPing統計情報:
パケット:送信= 4、受信= 4、損失= 0(損失率0%)、
およその往復時間(ミリ秒):
最小値= 10ms、最大値= 29ms、平均値= 19ms


Open3.capture3:

require 'open3'

stdout, stderr, status = Open3.capture3('my_funky_command', 'and', 'some', 'argumants')
if status.success?
  # command completed successfully, do some more stuff
else
  raise "An error occured"
end

または

Open3.capture3('/some/binary with some args')  

ただし、追加のオーバーヘッドとシェル注入の可能性があるため、お勧めできません。

コマンドがstdinから読み込み、それにいくつかのデータを送りたい場合:

Open3.capture3('my_funky_command', stdin_data: 'read from stdin')  

chdirを使用して、別の作業ディレクトリでコマンドを実行します。

Open3.capture3('my_funky_command', chdir: '/some/directory')  

Rubyでシェルコードを実行するための明確な方法:

Exec:

exec 'echo "hello world"'

または

exec ('echo "hello world"')

システムコマンド:

system 'echo "hello world"'

コマンドウィンドウで "hello world"を出力します。

または

system ('echo "hello world"')

コマンドが成功した場合はtrue、失敗した場合はnillを返します。

result = system 'echo "hello world"'
puts result  # will return a true in the command window

バックティック( `):

echo "hello world"コマンドウィンドウで "hello world"を出力します。

結果をキャッチすることもできます。

result = `echo "hello world"`  
puts "We always code a " + result  

IO.popen:

# Will get and return the current date from the system
IO.popen("date") { |f| puts f.gets }


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow