Perl でプロセスを起動して忘れる方法を誰か教えてくれませんか? 私はすでにルビーを見てきました:サブプロセスを起動して忘れるには? Rubyで同じことをするため。
4 に答える
perlfaq8の回答からバックグラウンドでプロセスを開始するにはどうすればよいですか?
いくつかのモジュールは、Perlプログラムをブロックしない他のプロセスを開始できます。IPC :: Open3、Parallel :: Jobs、IPC :: Run、および一部のPOEモジュールを使用できます。詳細については、CPANを参照してください。
あなたも使うことができます
system("cmd &")
または、perlfuncの「fork」に記載されているようにforkを使用し、perlipcでさらに例を示すこともできます。Unixライクなシステムを使用している場合は、次の点に注意してください。
STDIN、STDOUT、およびSTDERRは共有されます
メインプロセスとバックグラウンドプロセス(「子」プロセス)の両方が、同じSTDIN、STDOUT、およびSTDERRファイルハンドルを共有します。両方が同時にそれらにアクセスしようとすると、奇妙なことが起こる可能性があります。あなたは子供のためにこれらを閉じるか再開したいかもしれません。パイプを「開く」ことでこれを回避できますが(perlfuncの「開く」を参照)、一部のシステムでは、これは子プロセスが親よりも長生きできないことを意味します。
信号
SIGCHLDシグナルをキャッチする必要があり、場合によってはSIGPIPEもキャッチする必要があります。バックグラウンドプロセスが終了すると、SIGCHLDが送信されます。子プロセスが閉じているファイルハンドルに書き込むと、SIGPIPEが送信されます(トラップされていないSIGPIPEを使用すると、プログラムがサイレントに停止する可能性があります)。これは「system( "cmd&")」の問題ではありません。
ゾンビ
子プロセスが終了したら、子プロセスを「刈り取る」準備をする必要があります。
$SIG{CHLD} = sub { wait };
$SIG{CHLD} = 'IGNORE';
ダブルフォークを使用することもできます。すぐに最初の子をwait()し、initデーモンは孫が終了するとすぐにwait()します。
unless ($pid = fork) {
unless (fork) {
exec "what you really wanna do";
die "exec failed!";
}
exit 0;
}
waitpid($pid, 0);
これを行う他のコード例については、perlipcの「Signals」を参照してください。ゾンビは「system( "prog&")」の問題ではありません。
「親」プロセスが終了したときにウォッチドッグの「子」プロセスをなくしたい場合は、親プロセスが子プロセスを「起動して忘れる」ことを本当に望んでいません。fork (brian d foy で説明されているように) するか、親の PID を子に渡す必要があります (後者がプロセス テーブルをポーリングできるようにするため、お勧めしません)。
system()
この呼び出しは、実行を続行する前に関数の戻りを待機することを理解しているため、使用しないでください。私は単純にLinuxにシェルアウトしてプロセスを開始しますが、この方法ではシェルの新しいコピーが呼び出されることに注意してください。パフォーマンスを探している場合は、たとえばループでこれを行いません。
process_name > /dev/null 2>&1 &
;
これにより、プロセスのリダイレクトが開始され、STDOUT
/ dev/nullにリダイレクトされます。STDERR