• 締切済み

バックグラウンド処理をforkする意味

初歩的な質問かもしれませんが… デーモンなどではなく、あくまでも通常のCGIスクリプトにおいて、何か重い処理をさせる場合は、STDOUTをcloseして処理はforkで生成した子プロセスにさせる、するとユーザーを待たせることなく(ブラウザをビジーから開放し)処理はバックグラウンドで実行される、という方法がよく見られるのですが、素朴な疑問があります。 ブラウザを開放させるにはSTDOUTをcloseすれば良い、 では、なぜ処理を子プロセスにさせなければならない? という点です。 一応、以下のような簡単なコードで試してみました。 ----------------- use Date::Format; my $log_file = 'hogehoge/test.log'; my $start = time2str('%m-%d %T', time); print "Content-Type: text/plain\n\n"; print "start:$start"; close(STDOUT); &heavy_exe($start); exit; sub heavy_exe { my $start = $_[0]; sleep(15); my $now = time2str('%m-%d %T', time); open(LOG, ">>$log_file") or &error('cant_open'); print LOG "$start\t$now\n"; close(LOG); } ----------------- 実行してみると、ブラウザはすぐさま開放される(読み込み完了になる)のと、15秒後にロギングも問題なく行われ、また本当に開放されていることを確認するために表示から15秒以内にリロードさせても、問題なく2プロセスとも動いていました。 以上を見る限りでは、forkなんてしなくても単にブラウザを開放するだけでいい、STDOUTをcloseするだけでバックグラウンド処理されると思うのですが、どうなのでしょう。 あるいは何か環境に依存した、子プロセスにさせなければならない理由などがあるのでしょうか。 よろしくお願いいたします。

みんなの回答

回答No.2

ログ出力された=実行できた というのは間違いではありませんが、 ログ出力されたのをどうやって判定したかということです。 別にコンソールかなにかで、探ってみたということですよね? 同プログラム内で、処理が返ってきてその結果を受けた訳ではないですよね? と、いうことが言いたかっただけです。 ただ、標準出力を開放してしまいますと、 後に実行しているプログラムが無限ループに陥っても分らなくなるので、少々危険だと思われますし、 上記のプログラムでは、ブラウザを数回リロードされると その分実行されるので、サーバ内部では結局重い処理の連続になると思われます。くれぐれもご注意を。

taseki
質問者

補足

たびたびありがとうございます。 > ログ出力されたのをどうやって判定したか もちろんログそのものを見て判定しました。 ご覧のとおりプログラム自体は処理結果を返しませんから、ログ出力されたのを確認するにはログを見るしかありません。なので、heavy_exe が実行されたかどうかの判定は問題ないと思います。 どうも私の質問の仕方が悪かったようですね。すみません。 標準出力の開放、という部分が解らないのですが(逆にcloseしています)、いずれにしても、お聞きしたかったのは、このプログラムのロジックうんぬんではないんです…(単なる実験用コードです)。 「perl fork バックグラウンド」などで検索してもらうといくらでも見つかりますが、よくあるパターン「STDOUTをcloseしてforkで生成した子プロセスにバックグラウンド処理させる」という広く知られた方法がありますよね。これについて、「STDOUTをclose」は解りますが「子プロセスにバックグラウンド処理させる」理由が知りたかったのです。 標準出力をcloseするとhttpdがスクリプトのプロセスをkillしようとするから、という記事も見つけましたが、試してみたところ10分たってもプロセスは生きていました。もしかしたらバージョンによる違いかもしれませんが(apache2系)。 どなたか、御存じないでしょうか。

回答No.1

念のため、バックグランウンド処理 == fork ではありません。 ブラウザに開放だけですと、 close(STDOUT); でいいように思います。 上記プログラムですと、 なお、heavy_exe が本当に実行できているかは判断がつかないように思います。 # 違う重い処理を書いた場合、ひょっとしたら、ゾンビってるかもしれませんし。 forkはそもそも、子プロセスの挙動を制御(返り値が取れる)するためで、daemon系のプログラムに有用でしょう(今日、threadの方がいいでしょうけど) # forkを使ってもゾンビるときはゾンビますけど。 私自身は、forkは嫌いなので、重い処理があるときは、 予約データとして値を何かしらに格納し、別プログラムをcronで走らせてます。

taseki
質問者

補足

早速のご回答ありがとうございます。 誠にすみません、ちょっと意味が解らなかったのですが… 結論としては、私の推測は正しかった、という理解でいいのでしょうか? また、 > heavy_exe が本当に実行できているかは判断がつかない 上記について、よろしければもう少し詳しく御教授いただけないでしょうか。 ログ出力された=実行できた、と考えたのですが、これは間違いと言うことですよね?

関連するQ&A