PHP高級編程之守護進程
PHP高級編程之守護進程http://netkiller.github.io/journal/php.daemon.htmlMr.Neo Chen(陳景峰),netkiller, BG7NYT
版權聲明
轉載請與作者聯繫,轉載時請務必標明文章原始出處和作者信息及本聲明。
2014-09-01
摘要
2014-09-01 發表
2015-08-31 更新
2015-10-20 更新,增加優雅重啟
目錄
1. 什麼是守護進程
2. 為什麼開發守護進程
3. 何時採用守護進程開發應用程序
4. 守護進程的安全問題
5. 怎樣開發守護進程
5.1. 程序啟動
5.2. 程序停止
5.3. 單例模式
5.4. 實現優雅重啟
6. 進程意外退出解決方案
1. 什麼是守護進程
守護進程是脫離於終端並且在後台運行的進程。守護進程脫離於終端是為了避免進程在執行過程中的信息在任何終端上顯示並且進程也不會被任何終端所產生的終端信息所打斷。
例如 apache, nginx, mysql 都是守護進程
2. 為什麼開發守護進程
很多程序以服務形式存在,他沒有終端或UI交互,它可能採用其他方式與其他程序交互,如TCP/UDP Socket, UNIX Socket, fifo。程序一旦啟動便進入後台,直到滿足條件他便開始處理任務。
3. 何時採用守護進程開發應用程序
以我當前的需求為例,我需要運行一個程序,然後監聽某埠,持續接受服務端發起的數據,然後對數據分析處理,再將結果寫入到資料庫中; 我採用ZeroMQ實現數據收發。
如果我不採用守護進程方式開發該程序,程序一旦運行就會佔用當前終端窗框,還有受到當前終端鍵盤輸入影響,有可能程序誤退出。
4. 守護進程的安全問題
我們希望程序在非超級用戶運行,這樣一旦由於程序出現漏洞被駭客控制,攻擊者只能繼承運行許可權,而無法獲得超級用戶許可權。
我們希望程序只能運行一個實例,不運行同事開啟兩個以上的程序,因為會出現埠衝突等等問題。
5. 怎樣開發守護進程
例 1. 多線程守護進程例示
例 2. 消息隊列與守護進程
5.1. 程序啟動
下面是程序啟動後進入後台的代碼
通過進程ID文件來判斷,當前進程狀態,如果進程ID文件存在表示程序在運行中,通過代碼file_exists($this->pidfile)實現,但而後進程被kill需要手工刪除該文件才能運行
private function daemon(){if (file_exists($this->pidfile)) {echo "The file $this->pidfile exists.
";exit();}$pid = pcntl_fork();if ($pid == -1) { die( could not fork );} else if ($pid) {// we are the parent//pcntl_wait($status); //Protect against Zombie childrenexit($pid);} else {// we are the childfile_put_contents($this->pidfile, getmypid());posix_setuid(self::uid);posix_setgid(self::gid);return(getmypid());}}
程序啟動後,父進程會推出,子進程會在後台運行,子進程許可權從root切換到指定用戶,同時將pid寫入進程ID文件。
5.2. 程序停止
程序停止,只需讀取pid文件,然後調用posix_kill($pid, 9); 最後將該文件刪除。
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. 實現優雅重啟
所謂優雅重啟是指進程不退出的情況加實現重新載入包含重置變數,刷新配置文件,重置日誌等等
stop/start 或者 restart都會退出進程,重新啟動,導致進程ID改變,同時瞬間退出導致業務閃斷。所以很多守護進程都會提供一個reload功能,者就是所謂的優雅重啟。
reload 實現原理是給進程發送SIGHUP信號,可以通過kill命令發送 kill -s SIGHUP 64881,也可以通過庫函數實現 posix_kill(posix_getpid(), SIGUSR1);
創建配置文件
[root@netkiller pcntl]# cat test.ini [db]host=192.168.0.1port=3306
測試方法,首先運行該守護進程
現在修改配置文件,增加user=test配置項
[root@netkiller pcntl]# cat test.ini [db]host=192.168.0.1port=3306user=test
發送信號,在另一個終端窗口,通過ps命令找到該進程的PID,然後使用kill命令發送SIGHUP信號,然後再通過ps查看進程,你會發現進程PID沒有改變
[root@netkiller pcntl]# ps ax grep reload64881 pts/0 S 0:00 php -c /srv/php/etc/php-cli.ini signal.reload.php65073 pts/1 S+ 0:00 grep --color=auto reload[root@netkiller pcntl]# kill -s SIGHUP 64881[root@netkiller pcntl]# ps ax grep reload64881 pts/0 S 0:00 php -c /srv/php/etc/php-cli.ini signal.reload.php65093 pts/1 S+ 0:00 grep --color=auto reload
配置文件被重新載入
This signal is called. [1] This program is reload.Array( [host] => 192.168.0.1 [port] => 3306 [user] => test)
優雅重啟完成。
6. 進程意外退出解決方案
如果是非常重要的進程,必須要保證程序正常運行,一旦出現任何異常退出,都需要做即時做處理。下面的程序可能檢查進程是否異常退出,如果退出便立即啟動。
#!/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 $) #echo $ if [ -z "$" ]; then$ >> $LOGFILE echo "[$] $ $" >> $LOGFILE #else #echo "[$] $ $" >> $LOGFILE fisleep 5done &
Donations (打賞)
We accept PayPal through:
https://www.paypal.me/netkiller
http://www.netkiller.cn/home/donations.html


TAG:Netkiller |
※Python學習之進程和線程
※PHP 的非同步進程助手
※快速過濾出進程PID進程
※系統變慢?WMI進程導致的CPU高佔用解決
※Python 並發編程之線程池/進程池
※Python多進程編程
※Python網路編程——進程
※深入Python多進程編程基礎
※IPO估價過高 投資者擔憂美團急速擴張影響IPO進程
※聯想長江汽車戰略合作 AI+IoV加速車聯進程
※入門Python多線程/多進程編程
※深蘭科技斬獲IEEE ISI冠軍,其Auto ML 技術加速企業AI升級新進程
※用C#編寫Linux守護進程
※Perl 進程管理
※5G商用進程持續推進 VR/AR行業或迎新契機
※GDPR 出台!AWS 如何幫助客戶及 APN 合作夥伴推進合規進程?
※進程與線程的區別
※行業整合進程:美國3D列印廠商TAM破產
※Android跨進程IPC通信AIDL
※Android 進程和線程