Ruby%xは64ビットLinuxでフォークしますが、32ではなく、特定の構文でのみフォークします
質問
Rubyコードを次に示します。
puts %x{ pstree #{$} } # never forks
puts %x{ pstree '#{$}' } # forks on amd64 only
32ビットUbuntu Dapperでは、次の出力が表示されます。
t.rb---pstree
t.rb---pstree
これは私にとって理にかなっています。しかし、64ビットUbuntu Hardyでは、次のようになります:
t.rb---sh---pstree
t.rb---pstree
ここで示されているのは、いずれかのケースで実行する前にRubyが分岐することです。コードをファイルに入れてstrace -fFで実行すると、64ビットのHardyでは clone()
( fork()
など)を呼び出すように見えます execve()
、32ビットDapperではそのようなことはしません。
私のRubyバージョンは次のとおりです。
ruby 1.8.4 (2005-12-24) [i486-linux]
ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]
&を混合してみてくださいマッチング通訳& OSの&ワードサイズは増えますが、現時点ではこれらのマシンを管理していないので簡単ではありません。おそらく、32ビットシステムでこれらのコマンドが同じように機能する理由は言うまでもなく、64ビットシステムでのこれらのコマンドの違いでさえ、誰かが教えてくれるかもしれません。
解決
Rubyは、%xが単一の引数で使用されている場合、シェル拡張を実行します(実行しているように)。
何が起こっているのかについての私の推測です:
Rubyはコマンドをスキャンして、シェル拡張を実行する必要がある特殊文字があるかどうかを判断します。特殊文字がある場合は、シェルを呼び出して実行します。 2番目の例では、単一引用符で十分なので、Rubyがシェルを呼び出して展開するので、フォークが必要になります。最初の例では、コマンドに特殊文字(変数展開後)が含まれていないため、フォークがないため、Rubyはシェル展開が不要であると判断できます。この2つのバージョンの違いは、おそらくシェルの拡張が必要であるとrubyが判断しようとする方法の内部的な変更に関係しています。 32ビットマシンのruby 1.8.5で2番目の例のフォークを取得します。
[編集]
さて、ルビー1.8.4と1.8.6のソースコードを見て、両方のバージョンが同じ基準を使用して、シェル拡張を実行するためにシェルを呼び出すかどうかを決定します。コマンドラインで、%xへの引数が1つ指定されると、シェルが呼び出されます。
*?{}[]<>()~&|\\$;'`"\n
Rubyは実際には両方のケースでシェルを呼び出しています(引用符を含む例)。 pstree
から異なる出力が表示される理由は、 sh 異なるマシンでcode>コマンドを実行します。1つは
fork
を呼び出し、もう1つは呼び出しません。これを自分で確認するには、両方のマシンで次のコマンドを実行します。
/bin/sh -c "pstree $"
これは、両方のマシンで引用符付きの例で pstree
を実行するためにRubyが使用しているコマンドです。 32ビットマシンでは bash --- pstree
が、もう1台では bash --- sh --- pstree
が表示されます。
今、私は興味がありますが、この違いを発見したきっかけは何ですか?それが問題を引き起こしていますか?
他のヒント
一連のサブプロセス(フォーク)を持つ非同期プロセッサ作業を開発することでこの状況を経験しましたが、マスターがフォアグラウンドにいてSIGINTを受信したときに発生しました。
実行:puts&quot;結果は%(monster-delayed-job)&quot;
そして出力は次のとおりでした:&quot;結果は&quot;
- はい、Im&quot; trap&quot;マスターのSIGINT
アンドレ