PHP Advanced Programming Daemon
http://netkiller.github.io/journal/php.daemon.html
Neo Chen (陈京峰) 氏、netkiller、 7NYT
中国広東省深セン市龍華新区民志街西山美地
518131
+86 13113668890
+86 755 29812080
6e61359cee4f36410cc69c8751705c8cpidfile) によってプログラムは実行されていますが、その後プロセスが強制終了されるため、実行する前にファイルを手動で削除する必要があります
private function daemon(){ if (file_exists($this->pidfile)) { echo "The file $this->pidfile exists.\n"; exit(); } $pid = pcntl_fork(); if ($pid == -1) { die('could not fork'); } else if ($pid) { // we are the parent //pcntl_wait($status); //Protect against Zombie children exit($pid); } else { // we are the child file_put_contents($this->pidfile, getmypid()); posix_setuid(self::uid); posix_setgid(self::gid); return(getmypid()); } }
プログラムの開始後、親プロセスが起動されますを実行すると、子プロセスがバックグラウンドで実行され、子プロセスの権限が root から指定されたユーザーに切り替えられ、同時にプロセス ID ファイルの書き込みが行われます。
5.2. プログラムが停止します
private function stop(){ if (file_exists($this->pidfile)) { $pid = file_get_contents($this->pidfile); posix_kill($pid, 9); unlink($this->pidfile); } }
5.3. シングルトン モード
protected function getInstance(){ return self::$dbh;}
5.4. グレースフル リスタートを実現する
<?phppcntl_signal(SIGTERM, function($signo) { echo "\n This signal is called. [$signo] \n"; Status::$state = -1;});pcntl_signal(SIGHUP, function($signo) { echo "\n This signal is called. [$signo] \n"; Status::$state = 1; Status::$ini = parse_ini_file('test.ini');});class Status{ public static $state = 0; public static $ini = null;}$pid = pcntl_fork();if ($pid == -1) { die('could not fork');}if($pid) { // parent} else { $loop = true; Status::$ini = parse_ini_file('test.ini'); while($loop) { print_r(Status::$ini); while(true) { // Dispatching... pcntl_signal_dispatch(); if(Status::$state == -1) { // Do something and end loop. $loop = false; break; } if(Status::$state == 1) { printf("This program is reload.\r\n"); Status::$state = 0; break; } echo '.'; sleep(1); } echo "\n"; } echo "Finish \n"; exit();}
テスト方法、まずデーモンを実行します
[root@netkiller pcntl]# cat test.ini [db]host=192.168.0.1port=3306
次に、設定ファイルを変更して user=test 設定項目を追加します
# php signal.reload.php Array( [host] => 192.168.0.1 [port] => 3306)
別のターミナル ウィンドウで、ps コマンドを使用して PID を見つけます。プロセスを削除し、kill コマンドを使用して SIGHUP シグナルを送信し、ps でプロセスを確認すると、プロセスの PID が変更されていないことがわかります
うわー設定ファイルがリロードされました
This signal is called. [1] This program is reload.Array( [host] => 192.168.0.1 [port] => 3306 [user] => test)
优雅重启完成。
如果是非常重要的进程,必须要保证程序正常运行,一旦出现任何异常退出,都需要做即时做处理。下面的程序可能检查进程是否异常退出,如果退出便立即启动。
#!/bin/shLOGFILE=/var/log/$(basename $0 .sh).logPATTERN="my.php"RECOVERY="/path/to/my.php start"while truedo TIMEPOINT=$(date -d "today" +"%Y-%m-%d_%H:%M:%S") PROC=$(pgrep -o -f ${PATTERN}) #echo ${PROC} if [ -z "${PROC}" ]; then ${RECOVERY} >> $LOGFILE echo "[${TIMEPOINT}] ${PATTERN} ${RECOVERY}" >> $LOGFILE #else #echo "[${TIMEPOINT}] ${PATTERN} ${PROC}" >> $LOGFILE fisleep 5done &