Ruby、exec、system、%x()またはBackticksの違い


370

次のRubyメソッドの違いは何ですか?

execsystemおよび%x()またはバッククォート

Rubyを介してプログラムで端末コマンドを実行するために使用されることは知っていますが、これを行うには3つの異なる方法がある理由を知りたいのです。


1
これらのコマンドや他の多くのコマンドは、ドキュメントで非常によく説明されています:exec system backticks
zetetic

1
そのトピックに関する優れたRubyクイックヒント記事があります:シェルコマンドを実行します
Simon Perepelitsa

6
:誰かがちょうどこの古いスレッドを掘っているので、話題に興味を持っRubyistsための優れた著書である「ワーキングではUnixのはプロセス」workingwithunixprocesses.com
マイケル・コールズ

1
答えに言及していないことに驚いていshます。
デニス

@Dennis私がこの質問を提起したとき、Ruby 1.9.3 *はリリースされていません。
ブラック氏

回答:


411

システム

このsystemメソッドはシステムプログラムを呼び出します。このメソッドの文字列引数としてコマンドを提供する必要があります。例えば:

>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true

呼び出されたプログラムは、現在使用されますSTDINSTDOUTそしてSTDERR、あなたのRubyプログラムのオブジェクトを。実際、実際の戻り値はtruefalseまたはのいずれかnilです。この例では、日付はのIOオブジェクトを通じて出力されましたSTDINtrueプロセスがゼロのステータスで終了した場合、プロセスがゼロ以外のステータスでfalse終了したnil場合、および実行が失敗した場合、メソッドは戻ります。

別の副作用は、グローバル変数$?Process::Statusオブジェクトに設定されることです。このオブジェクトには、呼び出されたプロセスのプロセス識別子(PID)や終了ステータスなど、呼び出し自体に関する情報が含まれます。

>> system("date")
Wed Sep 4 22:11:02 CEST 2013
=> true
>> $?
=> #<Process::Status: pid 15470 exit 0>

バックティック

バックティック( ``)はシステムプログラムを呼び出し、その出力を返します。最初のアプローチとは異なり、コマンドは文字列ではなく、バッククォートペア内に配置することで提供されます。

>> `date`
=> Wed Sep 4 22:22:51 CEST 2013   

グローバル変数$?もバッククォートを介して設定されます。バックティックを使用すると、文字列補間を使用することもできます。

%バツ()

を使用%xすると、バックティックスタイルの代わりになります。出力も返します。親戚%w%q(他の)と同様に、ブラケット形式の区切り文字が一致する限り、どの区切り文字でも十分です。これは手段%x(date)%x{date}および%x-date-すべての同義語です。同様に、バックティック%xは文字列補間を利用できます。

エグゼクティブ

Kernel#exec現在のプロセス(Rubyスクリプト)を使用すると、から呼び出されたプロセスに置き換えられますexec。このメソッドは文字列を引数として取ることができます。この場合、文字列はシェル展開の対象になります。複数の引数を使用する場合、最初の引数を使用してプログラムを実行し、呼び出されるプログラムの引数として以下を指定します。

Open3.popen3

必要な情報が標準入力または標準エラーに書き込まれることがあり、それらも制御する必要がある場合があります。ここOpen3.popen3で便利です:

require 'open3'

Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread|
   pid = thread.pid
   puts stdout.read.chomp
end

3
そして、どのように呼び出しハンドルのよりきめ細かい制御のためにSTDINSTDOUTSTDERR、検討するOpen3.popen3代わりに、例:stackoverflow.com/a/10922097/258662を
cboettig

1
バッククォートが文字列補間をサポートしていて、私の問題を解決してくれたことに言及していただきありがとうございます。
adg 2019

244

この回答に基づくフローチャートを次に示します端末のエミュレート使用scriptするもご覧ください。

ここに画像の説明を入力してください


3
これはそれほど単純ではありません。私の場合、popen3を使用してSTDOUT / STDERR出力をチェックするために、「プロセスが完了するまでブロックすることはOK(そして必要)でした」。
Nakilon、2016

whileループでラップすることにより、(実質的に)ブロックする非ブロッキング呼び出しを常に引き起こすことができます。ブロッキングコールをノンブロッキングコールにするのは簡単ではありません。
Ian

106

彼らは異なることをします。 exec現在のプロセスを新しいプロセスで置き換え、決して戻りませんsystem別のプロセスを呼び出し、その終了値を現在のプロセスに返します。バックティックを使用すると、別のプロセスが呼び出され、そのプロセスの出力が現在のプロセスに返されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.