一看就懂系列之 如何实现与控制php常驻进程
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
目錄(?)[+]
前言
關于如何實現與控制php常駐進程,不管是google還是baidu上進行搜索,都沒有感覺看起來賞心悅目的解答,于是決定自己動手總結下。
有同學會問了,整這個干甚?簡單的說就是,可以讓一個php腳本一直處于運行的狀態。從而實現將項目中某些耗時操作異步化,進隊列后由php腳本取出再執行。
有同學又會問了,直接在服務器直接命令“php test.php &”,不就可以實現了?那么這樣做的話有三點還需要考慮:1.如何保證此進程的穩定性(掛了怎么辦)2.如果想開10個進程,手動去執行10回好像不怎么友好。3.關閉的話需要手動殺死進程?
有同學又會問了,這個不是在crontab加一個定時任務從而一直去執行不就好了,而且保證了穩定性。準確地說這也是可以的,但是有三點需要考慮:1.每回新增隊列都要加一回crontab真的好嗎。2.還是開10的進程問題(同上)。3.那要是關閉的話還要去備注crontab任務?
所以本文所設計的方案主要解決以下幾個問題:
1.如果實現php的常駐?(不依賴第三方php擴展)
2.如何保證進程的穩定性(誰來守護的問題)?
3.如何方便的管理php進程的關閉與重啟?
4.如何方便的管理php進程的并發數?
5.如何進行對php進程的監控?
正文
demo文件描述
cron_demo
1.cron_watchdog.sh:用于添加以及調起php進程
2.cron_watchdogd.sh:用于監控cron_watchdog.sh,保證其一直在運行
3.cron_zombie_alert.sh:用于進程文件的掃描監控,與錯誤通知。
privdata/cron_demo
cron_count.ini:用于控制php進程的并發數
cron_switch.ini:用于控制php進程的開關
cron_status/ :用于存在標記php進程的pid,以供cron_zombie_alert.sh掃描
cron_kill.log:用于記錄cron_zombie_alert.sh掃描到并且kill的僵尸進程。
由于是一看就懂系列,故具體文件解析會附帶上詳細的解讀。
cron_watchdog.sh的實現與解讀
代碼實現
#!/bin/bash #該腳本需在bash版本>=4中執行 #輸出當前地址 CRON_DIR=$(cd $(dirname "$0"); pwd) #執行進程監控腳本的命令 zombie_alert_cmd="/bin/sh $CRON_DIR/cron_zombie_alert.sh& > /dev/null" #獲取php進程并發數配置 CRON_COUNT_INI=/www/privdata/cron_demo/config/cron_count.ini echo $CRON_COUNT_INI#此類寫法需要bash版本>4的支持。(如果mac默認3.x,所以不支持) declare -A deamon_map#key 為cron_count里的key value為命令腳本地址 deamon_map["test"]="$CRON_DIR/test.php"while true; do#循環執行deamon_map里的命令for deamon_count_key in "${!deamon_map[@]}" ; doecho $deamon_count_key#計算出配置文件里面php進程的并發數SUM=`grep "^$deamon_count_key *=" "$CRON_COUNT_INI" | awk '{print $3}'`#若在cron_count.ini中不存在,則默認賦值隊列并發數1if ! (echo $SUM | egrep -q '^[0-9]+$'); thenSUM=1 fiphp_script="${deamon_map["$deamon_count_key"]}"#計算當前運行中的php進程數目proc=`/bin/ps xaww | grep -v " grep" | grep "$php_script" |wc -l`current_count=$proc#若小于進程的配置數,則進行調起if [ $current_count -lt "$SUM" ];thenneed_to_open_count=`expr $SUM - $current_count`while [ $need_to_open_count -gt 0 ]dophp "$php_script" &(( need_to_open_count-- ))donefidone#php進程的監控與消息通知eval "$zombie_alert_cmd"sleep 1 done- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
shell關鍵點解讀
1.ps xaww:
a 顯示終端上地所有進程,包括其他用戶地進程 x 顯示沒有控制終端地進程 ww 避免詳細參數被截斷;2.${!arr[@]} 用于返回數組array的所有下標
3.deamon_map[“test”]=”$CRON_DIR/test.php”
用于添加cron任務,test為腳本在cron_count.ini里面的標號(這里設置為php腳本文件名),test.php為所需要執行的php腳本。解決問題
1.進程添加問題,只需在此處添加一行配置即可。
2.進程并發管理問題,只需在cron_count.ini配置即可。
cron_watchdogd.sh的實現與解讀
代碼實現
#!/bin/sh CRON_DIR=$(cd $(dirname "$0"); pwd) cmd="/bin/sh $CRON_DIR/cron_watchdog.sh& > /dev/null" #檢測cron_watchdog.sh是否在執行 proc=`/bin/ps xaww | grep -v " grep" | grep -- "cron_watchdog.sh"` #根據返回結果進行判斷腳本是否執行 if test -z "$proc" then#若不執行,那么就調起命令執行eval "$cmd" fi- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
此外需要在/etc/crontab中添加以下命令,以保證此腳本定時都會去檢測一回。
*/1 * * * * root sh /www/cron_demo/cron_watchdogd.sh > /dev/null 2>&1- 1
- 2
shell關鍵點解讀
1.grep -v:逆向輸出. 打印不匹配模式的行
2.test –z 字符串:測試字符串的長度是否為零
3.eval
此命令會執行兩回后續的語句,在這里,第一回先翻譯"$cmd"成"/bin/sh $CRON_DIR/cron_watchdog.sh& > /dev/null",第二回在進行執行這個命令解決問題
1.cron_watchdog.sh腳本的監控,保證其不死掉
cron_zombie_alert.sh的實現與解讀
代碼實現
#!/bin/sh PID_LOG=/www/privdata/cron_demo/cron_status/ KILL_LOG=/www/privdata/cron_demo/log/cron_kill.log #用于檢測30分鐘未進行更新的進程文件。 Minute=30#PID_LOG cd "$PID_LOG" if [ "$?" == 0 ];then#若進程文件30分鐘沒進行更新則認為已經僵死,需要kill并報警for pid in `find ./ -mmin +"$Minute"| grep -v /$ | awk -F '/' '{print $2}'`doif [ "$pid" != '' ];thenNOW=`date +%Y-%m-%d_%H:%M`HOSTNAME=`hostname`nl=''PROCESS=`ps p$pid fuh`if [ "$PROCESS" != '' ];thenPSTACK=`pstack $pid`#將pid進程信息輸出到tmp.out文件,若2秒之后還在運行再kill此進程TMP=`timeout 2 strace -p $pid -o tmp.out`STRACE=`cat tmp.out`rm tmp.outfi#組織報警消息message="$NOW $HOSTNAME zombie process id $pid $nl$PROCESS$nl$PSTACK$nl$STRACE--"echo "$message">>"$KILL_LOG"#kill "$pid"cd "$PID_LOG"#同時刪除進程文件rm -r "$pid"#進行郵件或者其他的形式將message的內容同步出去fidone fi- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
shell關鍵點解讀
1.timeout:
timeout [選項] 數字[后綴] 命令 [參數]... 或:timeout [選項] 運行指定命令,如果在指定時間后仍在運行則殺死該進程。 后綴"s"代表秒(默認值),"m"代表分,"h"代表小時,"d"代表天。2.strace:
-f :除了跟蹤當前進程外,還跟蹤其子進程。 -o file :將輸出信息寫到文件file中,而不是顯示到標準錯誤輸出(stderr)。 -p pid :綁定到一個由pid對應的正在運行的進程。此參數常用來調試后臺進程。解決問題
1.cron_status底下進程文件的管理。
2.處理php進程僵死的情況。發出相應報警信息。
簡單的例子
用于測試的php腳本片段。主要實現功能:每隔10秒輸出數字到tset_cron.log日志。
<?php define('ROOT_PATH', dirname(__FILE__)); //一些初始化操作,常量定義以及公共函數的引入 include(ROOT_PATH . '/cron_init.php'); $log_file = LOG_DIR . '/test_cron.log';//獲取進程pid $pid_status_log = CRON_STATUS_DIR . '/' . getmypid(); $i = 0; while (true) {// 將其放入cron_status中以供檢測file_put_contents($pid_status_log, 1);//從cron_switch.ini中來判斷此進程是否開啟,這個函數后面會單獨解析$cron_flag = cron_switch(TEST_CRON_KEY);//若關閉則刪掉進程文件if (!$cron_flag) {unlink($pid_status_log);exit();}// 可從隊列中取出數據進行處理// 這里作為例子,以記錄一個日志好了$msg = $i ."\n";file_put_contents($log_file, $msg, FILE_APPEND);sleep(10);$i++; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
cron_switch函數
function cron_switch($task = 'all') {//解析cron_switch.ini文件$cron_switch = parse_ini_file(CRON_SWITCH_FILE);if ($task == 'all') {return $cron_switch;} else {$task = str_replace(KEY_PREFIX, '', $task);$current_cron_switch = $cron_switch [$task];//第二個判斷用于重啟進程之用。只要將cron_switch的數字設置大一點則認為重啟,設置為0代表關閉,1代表開啟。if($GLOBALS['current_cron_switch'] && $GLOBALS['current_cron_switch']<$current_cron_switch){//若小于當前配置文件$current_cron_switch = 0;}if($current_cron_switch){//全局標記當前的cron_switch值,用于當作重啟的標志$GLOBALS['current_cron_switch'] = $current_cron_switch;}return $current_cron_switch;}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
開始運行啦
加好定時任務后發現:
日志每隔10s輸出一個數字了。此時將此php進程kill掉,馬上發現,有重現開始跑了。
此時:
現在試試進程數設置為2(cron_count.ini設置“test = 2”),會發現以上命令后,進程數會變為2個。(這里不截圖了,因為很晚了)
代碼demo
cron_demo
demo地址:https://github.com/supcbs/cron_demo來源:http://blog.csdn.net/u011957758/article/details/52519748
總結
以上是生活随笔為你收集整理的一看就懂系列之 如何实现与控制php常驻进程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 山区做什么生意赚钱 值得每一个农民创业者
- 下一篇: 制造业税负率一般控制在多少?