123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- <?php
- $actList = array("start","stop","reload");//命令合集
- $pidFile = dirname(__FILE__).'/../deBUG/work/work.pid';//正在运行的进程-记录
- $worklogFile =dirname(__FILE__).'/../deBUG/work/work.log';//运行日志信息
- $process_num = 2;
- $children_list = [];
- $masterPid = 0;
- $chiledNum = 0;
- //命令提示
- function useageExit(){
- global $argv,$actList;
- echo "may be you can try:{$argv[0]} [ ".implode(' | ', $actList)." ]\n";
- exit(1);
- }
- /**
- Note:杀死进程
- @var $type 类型stop reload
- */
- function killPids($type){
- global $masterPid,$pidFile,$worklogFile;
- if(!isset($type)) exit(0);
- $pidStr = file_get_contents($pidFile);
- $pidlist = $pids = explode(" ", $pidStr);
- foreach ($pids as $k=>$pid) {
- if($k==0){//reload跳过master进程
- if($type=='reload'||$type=='restart'){
- $masterPid = $pid;
- continue;
- }
- }
- exec("kill -9 $pid");
- file_put_contents($worklogFile,date('Y-m-d H:i:s')."##{$type}--kill {$pid} \n", FILE_APPEND | LOCK_EX);
- unset($pidlist[$k]);
- }
- unlink($pidFile);//删除进程记录文件
- }
- //创建多子进程
- function createWorkProcess($process_num) {
- global $children_list,$chiledNum;
- for($i=0;$i<$process_num;$i++){
- $pid = pcntl_fork();
- if($pid == -1){
- exit("err:fork children fail");
- }
- $chiledNum++;
- if($pid == 0){//业务功能逻辑部分
- $tpid = posix_getpid();//当前子进程pid
- cli_set_process_title("mp_work_{$chiledNum}");//设置当前进程名
- doWork2($chiledNum);
- exit(0);
- }
- array_push($children_list, $pid);
- }
- return $process_num==1?$pid:$children_list;
- }
- //======工作业务逻辑========
- function doWork($chiledNum){
- include(dirname(__FILE__)."/../crontab/crontab.inc.php");
- include(dirname(__FILE__)."/../com.php");
- $memoryLogFile = dirname(__FILE__)."/../deBUG/work/memoryLog_{$chiledNum}.log";
- $thisWPid = posix_getpid();
- while (true) {
- sleep(2);
- $res = oo::async()->do_async($chiledNum);
- if(!$res){
- oo::commonOprDb('common')->close();
- }
- }
- }
- function doWork2($chiledNum){
- include(dirname(__FILE__)."/../crontab/crontab.inc.php");
- include(dirname(__FILE__)."/../com.php");
- $memoryLogFile = dirname(__FILE__)."/../deBUG/work/memoryLog_{$chiledNum}.log";
- $thisWPid = posix_getpid();
- while (true) {
- sleep(5);
- file_put_contents($memoryLogFile,date('Y-m-d H:i:s')."##PID:{$thisWPid} -chiled:{$chiledNum} -do:ok \n");
- try{
- // $memoryOne = memory_get_usage()/1024;
- $res = oo::async()->do_async($chiledNum);
- // $memoryTwe = memory_get_usage()/1024;
- // file_put_contents($memoryLogFile, date('Y-m-d H:i:s')."##PID:{$thisWPid} - startMemory:{$memoryOne} - endMemory:{$memoryTwe}\n",FILE_APPEND | LOCK_EX);
- if(!$res){
- $err = error_get_last();
- throw new Exception('任务异常-'.json_encode($err));
- }
- }catch (Exception $e){
- $msg = $e->getMessage();
- file_put_contents($memoryLogFile,date('Y-m-d H:i:s')."##PID:{$thisWPid} - error:{$msg} \n");
- }
- //大于100M内存退出程序,防止内存泄漏被系统杀死导致任务终端
- if(memory_get_usage()>100*1024*1024){
- exit('内存溢出');
- }
- }
- }
- //==========================
- if(!isset($argv[1])||!in_array($argv[1],$actList)){
- useageExit();
- }
- //结束进程
- if($argv[1] == 'stop'){
- killPids('stop');
- file_put_contents($worklogFile, date('Y-m-d H:i:s')."##work is stop <<===\n=======\n", FILE_APPEND | LOCK_EX);
- exit(0);
- }
- //验证扩展
- if (!extension_loaded("pcntl")) {
- die("require pcntl extension loaded");
- }
- //验证运行模式
- if (substr(php_sapi_name(), 0, 3) !== 'cli') {
- die("This Programe can only be run in CLI mode");
- }
- //重载子进程(尚未完整)
- if($argv[1] == 'reload'){
- exit(0);
- killPids('reload');
- createWorkProcess($process_num);//创建子进程
- array_unshift($children_list,$masterPid);
- file_put_contents($pidFile,implode(" ", $children_list));
- file_put_contents($worklogFile, date('Y-m-d H:i:s')."##work is reload \n",FILE_APPEND | LOCK_EX);
- }
- //启动进程
- if($argv[1]!= 'start')
- {
- usageExit();
- }
- if(is_file($pidFile))
- {
- die("mp_work is run. \n");
- }
- $pid = pcntl_fork();//分出子进程下行
- // 创建子进程失败
- if ( $pid == -1 ) {
- die("err: start server fail. can not create process.\n");
- } elseif ( $pid > 0 ) {
- exit(0);
- }
- //创建新会话,防止工作进程关联控制终端
- if(-1 ==posix_setsid()){
- die("err: create session id fail");
- }
- $masterPid = posix_getpid();//当前进程pid
- cli_set_process_title('mp_work_master');//设置当前进程名
- createWorkProcess($process_num);//创建子进程
- $childstr = json_encode($children_list);
- echo "work is start===master:{$masterPid}===children_list:{$childstr}"."\r\n";
- array_unshift($children_list,$masterPid);//master进程入进程组
- file_put_contents($pidFile,implode(" ", $children_list));
- file_put_contents($worklogFile, date("Y-m-d H:i:s")."##work is start ===>>\n", FILE_APPEND | LOCK_EX);
- //监控
- while (true) {
- $pid = pcntl_wait($status/*, WNOHANG*/);
- if ( $pid > 0 && in_array($pid,$children_list) ) {
- sleep(2);
- unset($children_list[array_search($pid, $children_list)]);//移除进程组中的被kill pid
- $newpid = 0;
- // $newpid = createWorkProcess(1);//创建新子进程
- unlink($pidFile);
- file_put_contents($pidFile,implode(" ", $children_list));
- file_put_contents($worklogFile, date('Y-m-d H:i:s')."##work is restart (out {$pid} join {$newpid})\n",FILE_APPEND | LOCK_EX);
- }
- }
|