workermand 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #!/usr/bin/env php
  2. <?php
  3. error_reporting(E_ALL);
  4. ini_set('display_errors', 'on');
  5. ini_set('limit_memory','512M');
  6. ini_set('opcache.enable', false);
  7. date_default_timezone_set('Asia/Shanghai');
  8. if(empty($argv[1]))
  9. {
  10. echo "Usage: workermand {start|stop|restart|reload|kill|status}".PHP_EOL;
  11. exit;
  12. }
  13. $cmd = $argv[1];
  14. define('WORKERMAN_ROOT_DIR', realpath(__DIR__."/../")."/");
  15. chdir(WORKERMAN_ROOT_DIR);
  16. if(0 === strpos(strtolower(PHP_OS), 'win'))
  17. {
  18. exit("Workerman can not run on Windows operating system\n");
  19. }
  20. if (version_compare(PHP_VERSION,'5.3.0','<'))
  21. {
  22. exit("Workerman PHP >= 5.3.0 required \n");
  23. }
  24. require_once WORKERMAN_ROOT_DIR . 'Core/Master.php';
  25. // ==pid-file==
  26. require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Config.php';
  27. Man\Core\Lib\Config::instance();
  28. if(!($pid_file = Man\Core\Lib\Config::get('workerman.pid_file')))
  29. {
  30. $pid_file = '/var/run/workerman.pid';
  31. }
  32. define('WORKERMAN_PID_FILE', $pid_file);
  33. // ==log-dir==
  34. if(!($log_dir = Man\Core\Lib\Config::get('workerman.log_dir')))
  35. {
  36. $log_dir = WORKERMAN_ROOT_DIR . 'logs/';
  37. }
  38. define('WORKERMAN_LOG_DIR', $log_dir . '/');
  39. // ==ipc-key==
  40. if(!($ipc_key = Man\Core\Lib\Config::get('workerman.ipc_key')))
  41. {
  42. $ipc_key = fileinode(WORKERMAN_ROOT_DIR);
  43. }
  44. define('IPC_KEY', $ipc_key);
  45. // ==shm-size==
  46. if(!($shm_size = Man\Core\Lib\Config::get('workerman.shm_size')))
  47. {
  48. $shm_size = 393216;
  49. }
  50. define('DEFAULT_SHM_SIZE', $shm_size);
  51. // ==msg-qbytes==
  52. if(!($msg_qbytes = Man\Core\Lib\Config::get('workerman.msg_qbytes')))
  53. {
  54. $msg_qbytes = 65535;
  55. }
  56. define('DEFAULT_MSG_QBYTES', $msg_qbytes);
  57. //检查pid对应的进程是否存在,不存在删除PID文件
  58. if($cmd != 'status' && is_file(WORKERMAN_PID_FILE))
  59. {
  60. //检查权限
  61. if(!posix_access(WORKERMAN_PID_FILE, POSIX_W_OK))
  62. {
  63. if($stat = stat(WORKERMAN_PID_FILE))
  64. {
  65. if(($start_pwuid = posix_getpwuid($stat['uid'])) && ($current_pwuid = posix_getpwuid(posix_getuid())))
  66. {
  67. exit("\n\033[31;40mWorkerman is started by user {$start_pwuid['name']}, {$current_pwuid['name']} can not $cmd Workerman, Permission denied\033[0m\n\n\033[31;40mWorkerman $cmd failed\033[0m\n\n");
  68. }
  69. }
  70. exit("\033[31;40mCan not $cmd Workerman, Permission denied\033[0m\n");
  71. }
  72. //检查pid进程是否存在
  73. if($pid = @file_get_contents(WORKERMAN_PID_FILE))
  74. {
  75. if(false === posix_kill($pid, 0))
  76. {
  77. if(!unlink(WORKERMAN_PID_FILE))
  78. {
  79. exit("\033[31;40mCan not $cmd Workerman\033[0m\n\n");
  80. }
  81. }
  82. }
  83. }
  84. switch($cmd)
  85. {
  86. case 'start':
  87. Man\Core\Master::run();
  88. break;
  89. case 'stop':
  90. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  91. if(empty($pid))
  92. {
  93. exit("\033[33;40mWorkerman not running?\033[0m\n");
  94. }
  95. stop_and_wait();
  96. break;
  97. case 'restart':
  98. stop_and_wait();
  99. Man\Core\Master::run();
  100. break;
  101. case 'reload':
  102. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  103. if(empty($pid))
  104. {
  105. exit("\033[33;40mWorkerman not running?\033[0m\n");
  106. }
  107. posix_kill($pid, SIGHUP);
  108. echo "reload Workerman\n";
  109. break;
  110. case 'kill':
  111. force_kill();
  112. force_kill();
  113. break;
  114. case 'status':
  115. $address = Man\Core\Lib\Config::get('Monitor.listen');
  116. $sock = @stream_socket_client($address);
  117. if(!$sock)
  118. {
  119. exit("\n\033[31;40mcan not connect to $address \033[0m\n\n\033[31;40mWorkerman not running\033[0m\n\n");
  120. }
  121. fwrite($sock, 'status');
  122. $read_fds = array($sock);
  123. $write_fds = $except_fds = array();
  124. while($ret = stream_select($read_fds, $write_fds, $except_fds, 1))
  125. {
  126. if(!$ret)break;
  127. foreach($read_fds as $fd)
  128. {
  129. if($ret_str = fread($fd, 8192))
  130. {
  131. echo $ret_str;
  132. }
  133. else
  134. {
  135. exit;
  136. }
  137. }
  138. }
  139. break;
  140. default:
  141. echo "Usage: workermand {start|stop|restart|reload|kill|status}\n";
  142. exit;
  143. }
  144. function force_kill()
  145. {
  146. $ret = $match = array();
  147. exec("ps aux | grep -E '".Man\Core\Master::NAME.":|workermand' | grep -v grep", $ret);
  148. $this_pid = posix_getpid();
  149. $this_ppid = posix_getppid();
  150. foreach($ret as $line)
  151. {
  152. if(preg_match("/^[\S]+\s+(\d+)\s+/", $line, $match))
  153. {
  154. $tmp_pid = $match[1];
  155. if($this_pid != $tmp_pid && $this_ppid != $tmp_pid)
  156. {
  157. posix_kill($tmp_pid, SIGKILL);
  158. }
  159. }
  160. }
  161. }
  162. function stop_and_wait($wait_time = 6)
  163. {
  164. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  165. if(empty($pid))
  166. {
  167. //exit("server not running?\n");
  168. }
  169. else
  170. {
  171. $start_time = time();
  172. posix_kill($pid, SIGINT);
  173. while(is_file(WORKERMAN_PID_FILE))
  174. {
  175. clearstatcache();
  176. usleep(1000);
  177. if(time()-$start_time >= $wait_time)
  178. {
  179. force_kill();
  180. force_kill();
  181. unlink(WORKERMAN_PID_FILE);
  182. usleep(500000);
  183. break;
  184. }
  185. }
  186. echo "Workerman stoped\n";
  187. }
  188. }