2

ここにいくつかの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 が exec の前に fork するケースが 1 つだけあるということです。コードをファイルに入れて strace -fF で実行すると、64 ビットの Hardy ではclone()(like のようにfork()) beforeを呼び出しているように見えますが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 ビット システムでのこれらのコマンドの違いさえ何かを教えてくれる人がいるかもしれません。

4

2 に答える 2

2

%x が単一の引数で使用されている場合、Rubyはシェル展開を実行します(あなたがやっているように)。

何が起こっているのかについての私の推測は次のとおりです。

Ruby はコマンドをスキャンして、シェル展開を実行する必要がある特殊文字があるかどうかを判断し、必要な場合はシェルを呼び出して実行します。2 番目の例では、Ruby がシェルを呼び出して展開を実行するようにするには、一重引用符で十分です。したがって、フォークします。最初の例では、Ruby は、コマンドに (変数展開後に) 特殊文字が含まれていないため、シェル展開が不要であると判断できます。したがって、フォークもありません。2 つのバージョンの違いは、シェルの拡張が必要かどうかを ruby​​ が判断しようとする方法の内部的な変更におそらく関係しています。32 ビット マシンの ruby​​ 1.8.5 で 2 番目の例のフォークを取得します。

[編集]

さて、Ruby 1.8.4 と 1.8.6 のソース コードを調べてみましたが、どちらのバージョンも同じ基準を使用して、コマンドに次の文字のいずれかが存在する場合、シェルを呼び出してシェル展開を実行するかどうかを決定します。 %x に 1 つの引数が指定されたときにシェルが呼び出される行:

*?{}[]<>()~&|\\$;'`"\n

Ruby は両方のケースで実際にシェルを呼び出しています (例では引用符が含まれています)。異なる出力が表示される理由は、異なるマシンでのコマンドの違いによるものです。1 つは を呼び出しpstree、もう 1 つは呼び出しません。これを自分で確認するには、両方のマシンで次のコマンドを実行します。shfork

/bin/sh -c "pstree $$"

pstreeこれは、Ruby が両方のマシンで引用符付きの例で実行するために使用しているコマンドです。bash---pstree32 ビット マシンともう一方のマシンで表示されるはずbash---sh---pstreeです。

では、なぜこの違いを発見したのか、それが問題を引き起こしているのでしょうか?

于 2008-10-18T00:27:13.293 に答える
1

一連のサブプロセス (フォーク) を持つ非同期プロセッサの作業を開発することでこの状況を経験しましたが、マスターがフォアグラウンドにあり、SIGINT を受け取ったときに発生しました。

私は実行します: puts "結果は %(monster-delayed-job)" です

出力は次のとおりでした: "結果は"

  • はい、マスターでSIGINTを「トラップ」します

アンドレ

于 2011-09-24T18:47:09.837 に答える