質問
長時間実行しているプロセスがあり、別のプロセスを起動するために必要です(しばらく実行されます)。開始するだけで、その後は完全に忘れる必要があります。
プログラミングRubyの本からいくつかのコードをすくって必要なことをやることができましたが、最善/正しい方法を見つけて、何が起こっているのかを理解したいと思います。私が最初に得たものは次のとおりです。
exec("whatever --take-very-long") if fork.nil?
Process.detach($)
それで、これが方法ですか、それとも他にどのようにすればよいですか?
以下の回答を確認した後、このコードになりました。これはより理にかなっているようです:
(pid = fork) ? Process.detach(pid) : exec("foo")
fork
の仕組みについての説明をいただければ幸いです。 [すでに知っています]
$$
をデタッチしましたか?これがなぜ機能するのかわかりません。状況をよりよく把握したいのです。
解決
fork
関数は、プロセスを2つに分けます。
両方のプロセスが関数の結果を受け取ります。子はゼロ/ nil
の値を受け取り(したがって、それが子であることを知っています)、親は子のPIDを受け取ります。
したがって:
exec("something") if fork.nil?
子プロセスは「何か」を開始し、親プロセスはそれがどこにあったかを続行します。
exec()
現在のプロセスを" something"に置き換えるので、子プロセスは以降のRubyコードを実行しないことに注意してください。
Process.detach()
の呼び出しは、正しくない可能性があります。子のPIDが含まれていると予想していましたが、コードを正しく読み取った場合、実際には親プロセスが切り離されています。
他のヒント
Alnitakは正しい。以下に、$$を使用せずに明示的に記述する方法を示します
pid = Process.fork
if pid.nil? then
# In child
exec "whatever --take-very-long"
else
# In parent
Process.detach(pid)
end
デタッチの目的は、「子がいつ終了するかは気にしません」と言うことです。 ゾンビプロセスを避けるため。
デタッチ $$
は正しくありませんでした。 pから。 348本のつるはし(2nd Ed):
$$
Fixnum実行中のプログラムのプロセス番号。 [r / o]
このセクション、"変数と定数" " Ruby言語"章は、さまざまなルビーの短い $
定数をデコードするのに非常に便利ですが、オンライン版(最初の
あなたが実際にやっていたのは、その子からではなく、それ自体からプログラムを切り離すことでした。
他の人が言ったように、子から切り離す適切な方法は、 fork()
から返された子のpidを使用することです。
他の答えは、子プロセスをデタッチしたいことが確実な場合に適しています。ただし、気にしない場合、または子プロセスをアタッチしたままにする場合(たとえば、Webアプリのサブサーバー/サービスを起動している場合)、次の短縮形を利用できます
fork do
exec('whatever --option-flag')
end
ブロックを提供すると、forkは子プロセスでそのブロック(およびそのブロックのみ)を実行し、親で続行します。
iは、上記の答えが私の端末を破壊し、出力を台無しにしたことを発見しました。これは私が見つけた解決策です。
system("nohup ./test.sh &")
同じ問題が発生した場合に備えて、私の目標はsshサーバーにログインし、そのプロセスを無期限に実行し続けることでした。 test.shはこれです
#!/usr/bin/expect -f
spawn ssh host -l admin -i cloudkey
expect "pass"
send "superpass\r"
sleep 1000000