mp_work.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. $actList = array("start","stop","reload");//命令合集
  3. $pidFile = dirname(__FILE__).'/../deBUG/work/work.pid';//正在运行的进程-记录
  4. $worklogFile =dirname(__FILE__).'/../deBUG/work/work.log';//运行日志信息
  5. $process_num = 2;
  6. $children_list = [];
  7. $masterPid = 0;
  8. $chiledNum = 0;
  9. //命令提示
  10. function useageExit(){
  11. global $argv,$actList;
  12. echo "may be you can try:{$argv[0]} [ ".implode(' | ', $actList)." ]\n";
  13. exit(1);
  14. }
  15. /**
  16. Note:杀死进程
  17. @var $type 类型stop reload
  18. */
  19. function killPids($type){
  20. global $masterPid,$pidFile,$worklogFile;
  21. if(!isset($type)) exit(0);
  22. $pidStr = file_get_contents($pidFile);
  23. $pidlist = $pids = explode(" ", $pidStr);
  24. foreach ($pids as $k=>$pid) {
  25. if($k==0){//reload跳过master进程
  26. if($type=='reload'||$type=='restart'){
  27. $masterPid = $pid;
  28. continue;
  29. }
  30. }
  31. exec("kill -9 $pid");
  32. file_put_contents($worklogFile,date('Y-m-d H:i:s')."##{$type}--kill {$pid} \n", FILE_APPEND | LOCK_EX);
  33. unset($pidlist[$k]);
  34. }
  35. unlink($pidFile);//删除进程记录文件
  36. }
  37. //创建多子进程
  38. function createWorkProcess($process_num) {
  39. global $children_list,$chiledNum;
  40. for($i=0;$i<$process_num;$i++){
  41. $pid = pcntl_fork();
  42. if($pid == -1){
  43. exit("err:fork children fail");
  44. }
  45. $chiledNum++;
  46. if($pid == 0){//业务功能逻辑部分
  47. $tpid = posix_getpid();//当前子进程pid
  48. cli_set_process_title("mp_work_{$chiledNum}");//设置当前进程名
  49. doWork2($chiledNum);
  50. exit(0);
  51. }
  52. array_push($children_list, $pid);
  53. }
  54. return $process_num==1?$pid:$children_list;
  55. }
  56. //======工作业务逻辑========
  57. function doWork($chiledNum){
  58. include(dirname(__FILE__)."/../crontab/crontab.inc.php");
  59. include(dirname(__FILE__)."/../com.php");
  60. $memoryLogFile = dirname(__FILE__)."/../deBUG/work/memoryLog_{$chiledNum}.log";
  61. $thisWPid = posix_getpid();
  62. while (true) {
  63. sleep(2);
  64. $res = oo::async()->do_async($chiledNum);
  65. if(!$res){
  66. oo::commonOprDb('common')->close();
  67. }
  68. }
  69. }
  70. function doWork2($chiledNum){
  71. include(dirname(__FILE__)."/../crontab/crontab.inc.php");
  72. include(dirname(__FILE__)."/../com.php");
  73. $memoryLogFile = dirname(__FILE__)."/../deBUG/work/memoryLog_{$chiledNum}.log";
  74. $thisWPid = posix_getpid();
  75. while (true) {
  76. sleep(5);
  77. file_put_contents($memoryLogFile,date('Y-m-d H:i:s')."##PID:{$thisWPid} -chiled:{$chiledNum} -do:ok \n");
  78. try{
  79. // $memoryOne = memory_get_usage()/1024;
  80. $res = oo::async()->do_async($chiledNum);
  81. // $memoryTwe = memory_get_usage()/1024;
  82. // file_put_contents($memoryLogFile, date('Y-m-d H:i:s')."##PID:{$thisWPid} - startMemory:{$memoryOne} - endMemory:{$memoryTwe}\n",FILE_APPEND | LOCK_EX);
  83. if(!$res){
  84. $err = error_get_last();
  85. throw new Exception('任务异常-'.json_encode($err));
  86. }
  87. }catch (Exception $e){
  88. $msg = $e->getMessage();
  89. file_put_contents($memoryLogFile,date('Y-m-d H:i:s')."##PID:{$thisWPid} - error:{$msg} \n");
  90. }
  91. //大于100M内存退出程序,防止内存泄漏被系统杀死导致任务终端
  92. if(memory_get_usage()>100*1024*1024){
  93. exit('内存溢出');
  94. }
  95. }
  96. }
  97. //==========================
  98. if(!isset($argv[1])||!in_array($argv[1],$actList)){
  99. useageExit();
  100. }
  101. //结束进程
  102. if($argv[1] == 'stop'){
  103. killPids('stop');
  104. file_put_contents($worklogFile, date('Y-m-d H:i:s')."##work is stop <<===\n=======\n", FILE_APPEND | LOCK_EX);
  105. exit(0);
  106. }
  107. //验证扩展
  108. if (!extension_loaded("pcntl")) {
  109. die("require pcntl extension loaded");
  110. }
  111. //验证运行模式
  112. if (substr(php_sapi_name(), 0, 3) !== 'cli') {
  113. die("This Programe can only be run in CLI mode");
  114. }
  115. //重载子进程(尚未完整)
  116. if($argv[1] == 'reload'){
  117. exit(0);
  118. killPids('reload');
  119. createWorkProcess($process_num);//创建子进程
  120. array_unshift($children_list,$masterPid);
  121. file_put_contents($pidFile,implode(" ", $children_list));
  122. file_put_contents($worklogFile, date('Y-m-d H:i:s')."##work is reload \n",FILE_APPEND | LOCK_EX);
  123. }
  124. //启动进程
  125. if($argv[1]!= 'start')
  126. {
  127. usageExit();
  128. }
  129. if(is_file($pidFile))
  130. {
  131. die("mp_work is run. \n");
  132. }
  133. $pid = pcntl_fork();//分出子进程下行
  134. // 创建子进程失败
  135. if ( $pid == -1 ) {
  136. die("err: start server fail. can not create process.\n");
  137. } elseif ( $pid > 0 ) {
  138. exit(0);
  139. }
  140. //创建新会话,防止工作进程关联控制终端
  141. if(-1 ==posix_setsid()){
  142. die("err: create session id fail");
  143. }
  144. $masterPid = posix_getpid();//当前进程pid
  145. cli_set_process_title('mp_work_master');//设置当前进程名
  146. createWorkProcess($process_num);//创建子进程
  147. $childstr = json_encode($children_list);
  148. echo "work is start===master:{$masterPid}===children_list:{$childstr}"."\r\n";
  149. array_unshift($children_list,$masterPid);//master进程入进程组
  150. file_put_contents($pidFile,implode(" ", $children_list));
  151. file_put_contents($worklogFile, date("Y-m-d H:i:s")."##work is start ===>>\n", FILE_APPEND | LOCK_EX);
  152. //监控
  153. while (true) {
  154. $pid = pcntl_wait($status/*, WNOHANG*/);
  155. if ( $pid > 0 && in_array($pid,$children_list) ) {
  156. sleep(2);
  157. unset($children_list[array_search($pid, $children_list)]);//移除进程组中的被kill pid
  158. $newpid = 0;
  159. // $newpid = createWorkProcess(1);//创建新子进程
  160. unlink($pidFile);
  161. file_put_contents($pidFile,implode(" ", $children_list));
  162. file_put_contents($worklogFile, date('Y-m-d H:i:s')."##work is restart (out {$pid} join {$newpid})\n",FILE_APPEND | LOCK_EX);
  163. }
  164. }