初心者のエクソシストへのメモ。始める前に:phpDaemonとSystem_Daemonが何であるかを知っています。 私はこのテーマに関する記事を読んでいます。
それで、あなたはすでにあなたが悪魔を必要とすると決めたと仮定します。 彼は何ができるはずですか?
- コンソールから実行し、それを取り除く
- ログにすべての情報を書き込みます。コンソールには何も出力しません
- 子プロセスを生成および制御できる
- タスクを完了する
- 正しくシャットダウンする
コンソールから取り外します
pcntl_fork()関数は子プロセスを作成し、その識別子を返します。 ただし、変数
$ child_pidは子プロセスに入りません(より正確には、0になります)。したがって、親プロセスのみがテストに合格します。 それは終了し、子プロセスはコードの実行を継続します。
通常、デーモンはすでに作成されていますが、コンソールにはすべての情報(エラーを含む)が表示されます。 はい。実行後すぐに終了します。
出力を再定義する
$baseDir = dirname(__FILE__); ini_set('error_log',$baseDir.'/error.log'); fclose(STDIN); fclose(STDOUT); fclose(STDERR); $STDIN = fopen('/dev/null', 'r'); $STDOUT = fopen($baseDir.'/application.log', 'ab'); $STDERR = fopen($baseDir.'/daemon.log', 'ab');
ここで、標準出力ストリームを閉じて、それらをファイルに送信します。 念のため、STDINは/ dev / nullからの読み取り用に開かれています。 私たちの悪魔はコンソールから読み込まれません-それは解かれています。 これで、デーモンのすべての出力がファイルに記録されます。
行こう!
include 'DaemonClass.php'; $daemon = new DaemonClass(); $daemon->run();
結論を再定義した後、デーモンに割り当てられたタスクを実行できます。
DaemonClass.phpを作成し、デーモンの基本的な作業を行うクラスの作成を開始します。
Daemonclass.php
シグナルSIGTERM(シャットダウン)およびSIGCHLD(子プロセスから)が必要です。 デーモンが終了しないように、無限ループを開始します。 別の子プロセスを作成できるかどうかを確認し、できない場合は待機します。
protected function launchJob() {
エラーが発生した場合、
pcntl_fork()は-1を返します。$ pidは親プロセスで使用可能になり、この変数は子にはありません(より正確には、0になります)。
public function childSignalHandler($signo, $pid = null, $status = null) { switch($signo) { case SIGTERM:
SIGTERM-正しいシャットダウンのシグナル。 SIGCHLD-子プロセスの完了のシグナル。 子プロセスの最後に、実行中のプロセスのリストから子プロセスを削除します。 SIGTERMを受信したら、フラグを設定します。現在のタスクが完了すると、「無限ループ」が終了します。
デーモンの複数のコピーの起動を禁止することは残っています。
これについては、
この記事で詳しく説明しています。
ご清聴ありがとうございました。
UPD: Dlussky habrayuzerの
コメントでは、PHP> = 5.3.0では、
declare(ticks = 1)ではなく
pcntl_signal_dispatch()を使用する必要があることが
示唆されました。