私が行った場合
Process.fork do
x
end
x が何を返したか (true/fase/string など) を知るにはどうすればよいですか?
(ファイル/データベースへの書き込みはオプションではありません...)
実際には、Rails分離テストでこの問題を処理する必要がありました。私はそれについて私のブログにいくつか投稿しました。
基本的には、親子でパイプを開き、子にパイプに書き込んでもらいます。子プロセスでブロックのコンテンツを実行し、結果を返す簡単な方法は次のとおりです。
def do_in_child
read, write = IO.pipe
pid = fork do
read.close
result = yield
Marshal.dump(result, write)
exit!(0) # skips exit handlers.
end
write.close
result = read.read
Process.wait(pid)
raise "child failed" if result.empty?
Marshal.load(result)
end
次に、実行できます。
do_in_child do
require "some_polluting_library"
SomePollutingLibrary.some_operation
end
子でrequireを実行すると、親でそのライブラリにアクセスできないため、このメソッドを使用してそのタイプのオブジェクトを返すことはできないことに注意してください。ただし、両方で使用可能な任意のタイプを返すことができます。
また、ここでの詳細の多く(read.close
、Process.wait2(pid)
)は主にハウスキーピングの詳細であるため、これを頻繁に使用する場合は、再利用できるユーティリティライブラリに移動する必要があります。
最後に、これはWindowsまたはJRubyでは機能しないことに注意してください。これらは、フォークをサポートしていないためです。
すべての回答をありがとう、私は自分のソリューションを稼働させましたが、非フォーク環境を処理する方法を確認する必要がありますが、今のところ動作します:)
read, write = IO.pipe
Process.fork do
write.puts "test"
end
Process.fork do
write.puts 'test 2'
end
Process.wait
Process.wait
write.close
puts read.read
read.close
@ parallel_specs Railsプラグインで実際に見ることができます
はい、内部でブロックを実行するサブプロセスを作成できます。
私はaw
宝石をお勧めします:
Aw.fork! { 6 * 7 } # => 42
もちろん、それは副作用を防ぎます:
arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]
2つのUnixプロセス間のフォーク通信は、主にリターンコードであり、それ以上のものではありません。ただし、2つのプロセス間でファイル記述子を開き、このファイル記述子を介してプロセス間でデータを渡すことができます。これは通常のUnixパイプ方式です。
Marshal.dump()とMarshal.load()の値を渡す場合は、これらのRubyプロセス間でRubyオブジェクトを簡単に渡すことができます。
子がルビーコードの小さなチャンクである必要がある場合は、共有メモリを使用してこれを行うことができます。次のようなものが機能します。
str = 'from parent'
Thread.new do
str = 'from child'
end
sleep(1)
puts str # outputs "from child"
ただし、同時実行性にはかなり注意が必要です。この方法で共有メモリにアクセスすることが理由の大きな部分です。変数があり、別のプロセスによって変数が変更される可能性がある場合は、十分に注意する必要があります。または、パイプを使用することもできます。パイプは、より面倒ですが、最も些細なコード以外ではおそらく安全であり、任意のコマンドを実行するためにも使用できます。これは、IO.popenのrdocから直接出た例です。
f = IO.popen("uname")
p f.readlines # outputs "Darwin", at least on my box :-)
ドキュメントによると:
ブロックが指定されている場合、そのブロックはサブプロセスで実行され、サブプロセスはステータス 0 で終了します。
したがって、ブロックで呼び出すと 0 が返されます。それ以外の場合は、基本的fork()
に Unix のシステム コールと同じように機能します (親は新しいプロセスの PID を受け取り、子は を受け取りますnil
)。