日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

一看就懂系列之 如何实现与控制php常驻进程

發(fā)布時間:2024/9/20 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一看就懂系列之 如何实现与控制php常驻进程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄(?)[+]

前言

關(guān)于如何實現(xiàn)與控制php常駐進(jìn)程,不管是google還是baidu上進(jìn)行搜索,都沒有感覺看起來賞心悅目的解答,于是決定自己動手總結(jié)下。

有同學(xué)會問了,整這個干甚?簡單的說就是,可以讓一個php腳本一直處于運行的狀態(tài)。從而實現(xiàn)將項目中某些耗時操作異步化,進(jìn)隊列后由php腳本取出再執(zhí)行。

有同學(xué)又會問了,直接在服務(wù)器直接命令“php test.php &”,不就可以實現(xiàn)了?那么這樣做的話有三點還需要考慮:1.如何保證此進(jìn)程的穩(wěn)定性(掛了怎么辦)2.如果想開10個進(jìn)程,手動去執(zhí)行10回好像不怎么友好。3.關(guān)閉的話需要手動殺死進(jìn)程?

有同學(xué)又會問了,這個不是在crontab加一個定時任務(wù)從而一直去執(zhí)行不就好了,而且保證了穩(wěn)定性。準(zhǔn)確地說這也是可以的,但是有三點需要考慮:1.每回新增隊列都要加一回crontab真的好嗎。2.還是開10的進(jìn)程問題(同上)。3.那要是關(guān)閉的話還要去備注crontab任務(wù)?

所以本文所設(shè)計的方案主要解決以下幾個問題:
1.如果實現(xiàn)php的常駐?(不依賴第三方php擴展)
2.如何保證進(jìn)程的穩(wěn)定性(誰來守護(hù)的問題)?
3.如何方便的管理php進(jìn)程的關(guān)閉與重啟?
4.如何方便的管理php進(jìn)程的并發(fā)數(shù)?
5.如何進(jìn)行對php進(jìn)程的監(jiān)控?

正文

demo文件描述

cron_demo
1.cron_watchdog.sh:用于添加以及調(diào)起php進(jìn)程
2.cron_watchdogd.sh:用于監(jiān)控cron_watchdog.sh,保證其一直在運行
3.cron_zombie_alert.sh:用于進(jìn)程文件的掃描監(jiān)控,與錯誤通知。


privdata/cron_demo
cron_count.ini:用于控制php進(jìn)程的并發(fā)數(shù)
cron_switch.ini:用于控制php進(jìn)程的開關(guān)
cron_status/ :用于存在標(biāo)記php進(jìn)程的pid,以供cron_zombie_alert.sh掃描
cron_kill.log:用于記錄cron_zombie_alert.sh掃描到并且kill的僵尸進(jìn)程。


由于是一看就懂系列,故具體文件解析會附帶上詳細(xì)的解讀。

cron_watchdog.sh的實現(xiàn)與解讀

代碼實現(xiàn)

#!/bin/bash #該腳本需在bash版本>=4中執(zhí)行 #輸出當(dāng)前地址 CRON_DIR=$(cd $(dirname "$0"); pwd) #執(zhí)行進(jìn)程監(jiān)控腳本的命令 zombie_alert_cmd="/bin/sh $CRON_DIR/cron_zombie_alert.sh& > /dev/null" #獲取php進(jìn)程并發(fā)數(shù)配置 CRON_COUNT_INI=/www/privdata/cron_demo/config/cron_count.ini echo $CRON_COUNT_INI#此類寫法需要bash版本>4的支持。(如果mac默認(rèn)3.x,所以不支持) declare -A deamon_map#key 為cron_count里的key value為命令腳本地址 deamon_map["test"]="$CRON_DIR/test.php"while true; do#循環(huán)執(zhí)行deamon_map里的命令for deamon_count_key in "${!deamon_map[@]}" ; doecho $deamon_count_key#計算出配置文件里面php進(jìn)程的并發(fā)數(shù)SUM=`grep "^$deamon_count_key *=" "$CRON_COUNT_INI" | awk '{print $3}'`#若在cron_count.ini中不存在,則默認(rèn)賦值隊列并發(fā)數(shù)1if ! (echo $SUM | egrep -q '^[0-9]+$'); thenSUM=1 fiphp_script="${deamon_map["$deamon_count_key"]}"#計算當(dāng)前運行中的php進(jìn)程數(shù)目proc=`/bin/ps xaww | grep -v " grep" | grep "$php_script" |wc -l`current_count=$proc#若小于進(jìn)程的配置數(shù),則進(jìn)行調(diào)起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進(jìn)程的監(jiān)控與消息通知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關(guān)鍵點解讀

1.ps xaww:

a 顯示終端上地所有進(jìn)程,包括其他用戶地進(jìn)程 x 顯示沒有控制終端地進(jìn)程 ww 避免詳細(xì)參數(shù)被截斷;

2.${!arr[@]} 用于返回數(shù)組array的所有下標(biāo)

3.deamon_map[“test”]=”$CRON_DIR/test.php”

用于添加cron任務(wù),test為腳本在cron_count.ini里面的標(biāo)號(這里設(shè)置為php腳本文件名),test.php為所需要執(zhí)行的php腳本。

解決問題

1.進(jìn)程添加問題,只需在此處添加一行配置即可。
2.進(jìn)程并發(fā)管理問題,只需在cron_count.ini配置即可。

cron_watchdogd.sh的實現(xiàn)與解讀

代碼實現(xiàn)

#!/bin/sh CRON_DIR=$(cd $(dirname "$0"); pwd) cmd="/bin/sh $CRON_DIR/cron_watchdog.sh& > /dev/null" #檢測cron_watchdog.sh是否在執(zhí)行 proc=`/bin/ps xaww | grep -v " grep" | grep -- "cron_watchdog.sh"` #根據(jù)返回結(jié)果進(jìn)行判斷腳本是否執(zhí)行 if test -z "$proc" then#若不執(zhí)行,那么就調(diào)起命令執(zhí)行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關(guān)鍵點解讀

1.grep -v:逆向輸出. 打印不匹配模式的行

2.test –z 字符串:測試字符串的長度是否為零

3.eval

此命令會執(zhí)行兩回后續(xù)的語句,在這里,第一回先翻譯"$cmd"成"/bin/sh $CRON_DIR/cron_watchdog.sh& > /dev/null",第二回在進(jìn)行執(zhí)行這個命令

解決問題

1.cron_watchdog.sh腳本的監(jiān)控,保證其不死掉

cron_zombie_alert.sh的實現(xiàn)與解讀

代碼實現(xiàn)

#!/bin/sh PID_LOG=/www/privdata/cron_demo/cron_status/ KILL_LOG=/www/privdata/cron_demo/log/cron_kill.log #用于檢測30分鐘未進(jìn)行更新的進(jìn)程文件。 Minute=30#PID_LOG cd "$PID_LOG" if [ "$?" == 0 ];then#若進(jìn)程文件30分鐘沒進(jìn)行更新則認(rèn)為已經(jīng)僵死,需要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進(jìn)程信息輸出到tmp.out文件,若2秒之后還在運行再kill此進(jìn)程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"#同時刪除進(jìn)程文件rm -r "$pid"#進(jìn)行郵件或者其他的形式將message的內(nèi)容同步出去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關(guān)鍵點解讀

1.timeout:

timeout [選項] 數(shù)字[后綴] 命令 [參數(shù)]... 或:timeout [選項] 運行指定命令,如果在指定時間后仍在運行則殺死該進(jìn)程。 后綴"s"代表秒(默認(rèn)值),"m"代表分,"h"代表小時,"d"代表天。

2.strace:

-f :除了跟蹤當(dāng)前進(jìn)程外,還跟蹤其子進(jìn)程。 -o file :將輸出信息寫到文件file中,而不是顯示到標(biāo)準(zhǔn)錯誤輸出(stderr)。 -p pid :綁定到一個由pid對應(yīng)的正在運行的進(jìn)程。此參數(shù)常用來調(diào)試后臺進(jìn)程。

解決問題

1.cron_status底下進(jìn)程文件的管理。
2.處理php進(jìn)程僵死的情況。發(fā)出相應(yīng)報警信息。

簡單的例子

用于測試的php腳本片段。主要實現(xiàn)功能:每隔10秒輸出數(shù)字到tset_cron.log日志。

<?php define('ROOT_PATH', dirname(__FILE__)); //一些初始化操作,常量定義以及公共函數(shù)的引入 include(ROOT_PATH . '/cron_init.php'); $log_file = LOG_DIR . '/test_cron.log';//獲取進(jìn)程pid $pid_status_log = CRON_STATUS_DIR . '/' . getmypid(); $i = 0; while (true) {// 將其放入cron_status中以供檢測file_put_contents($pid_status_log, 1);//從cron_switch.ini中來判斷此進(jìn)程是否開啟,這個函數(shù)后面會單獨解析$cron_flag = cron_switch(TEST_CRON_KEY);//若關(guān)閉則刪掉進(jìn)程文件if (!$cron_flag) {unlink($pid_status_log);exit();}// 可從隊列中取出數(shù)據(jù)進(jìn)行處理// 這里作為例子,以記錄一個日志好了$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函數(shù)

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];//第二個判斷用于重啟進(jìn)程之用。只要將cron_switch的數(shù)字設(shè)置大一點則認(rèn)為重啟,設(shè)置為0代表關(guān)閉,1代表開啟。if($GLOBALS['current_cron_switch'] && $GLOBALS['current_cron_switch']<$current_cron_switch){//若小于當(dāng)前配置文件$current_cron_switch = 0;}if($current_cron_switch){//全局標(biāo)記當(dāng)前的cron_switch值,用于當(dāng)作重啟的標(biāo)志$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

開始運行啦

加好定時任務(wù)后發(fā)現(xiàn):

日志每隔10s輸出一個數(shù)字了。此時將此php進(jìn)程kill掉,馬上發(fā)現(xiàn),有重現(xiàn)開始跑了。

此時:

現(xiàn)在試試進(jìn)程數(shù)設(shè)置為2(cron_count.ini設(shè)置“test = 2”),會發(fā)現(xiàn)以上命令后,進(jìn)程數(shù)會變?yōu)?個。(這里不截圖了,因為很晚了)

代碼demo

cron_demo

demo地址:https://github.com/supcbs/cron_demo

來源:http://blog.csdn.net/u011957758/article/details/52519748

總結(jié)

以上是生活随笔為你收集整理的一看就懂系列之 如何实现与控制php常驻进程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。