workermand 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. //检查pid对应的进程是否存在,不存在删除PID文件
  52. if($cmd != 'status' && is_file(WORKERMAN_PID_FILE))
  53. {
  54. //检查权限
  55. if(!posix_access(WORKERMAN_PID_FILE, POSIX_W_OK))
  56. {
  57. if($stat = stat(WORKERMAN_PID_FILE))
  58. {
  59. if(($start_pwuid = posix_getpwuid($stat['uid'])) && ($current_pwuid = posix_getpwuid(posix_getuid())))
  60. {
  61. 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");
  62. }
  63. }
  64. exit("\033[31;40mCan not $cmd Workerman, Permission denied\033[0m\n");
  65. }
  66. //检查pid进程是否存在
  67. if($pid = @file_get_contents(WORKERMAN_PID_FILE))
  68. {
  69. if(false === posix_kill($pid, 0))
  70. {
  71. if(!unlink(WORKERMAN_PID_FILE))
  72. {
  73. exit("\033[31;40mCan not $cmd Workerman\033[0m\n\n");
  74. }
  75. }
  76. }
  77. }
  78. // 必须是root启动
  79. if($user_info = posix_getpwuid(posix_getuid()))
  80. {
  81. if($user_info['name'] !== 'root')
  82. {
  83. exit("\033[31;40mYou should ran Workerman as root , Permission denied\033[0m\n");
  84. }
  85. }
  86. switch($cmd)
  87. {
  88. case 'start':
  89. $worker_user = isset($argv[2]) ? $argv[2] : '';
  90. Man\Core\Master::run($worker_user);
  91. break;
  92. case 'stop':
  93. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  94. if(empty($pid))
  95. {
  96. exit("\033[33;40mWorkerman not running?\033[0m\n");
  97. }
  98. stop_and_wait();
  99. break;
  100. case 'restart':
  101. stop_and_wait();
  102. $worker_user = isset($argv[2]) ? $argv[2] : '';
  103. Man\Core\Master::run();
  104. break;
  105. case 'reload':
  106. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  107. if(empty($pid))
  108. {
  109. exit("\033[33;40mWorkerman not running?\033[0m\n");
  110. }
  111. posix_kill($pid, SIGHUP);
  112. echo "reload Workerman\n";
  113. break;
  114. case 'kill':
  115. force_kill();
  116. force_kill();
  117. break;
  118. case 'status':
  119. $address = Man\Core\Lib\Config::get('Monitor.listen');
  120. $sock = @stream_socket_client($address);
  121. if(!$sock)
  122. {
  123. exit("\n\033[31;40mcan not connect to $address \033[0m\n\n\033[31;40mWorkerman not running\033[0m\n\n");
  124. }
  125. fwrite($sock, 'status');
  126. $read_fds = array($sock);
  127. $write_fds = $except_fds = array();
  128. while($ret = stream_select($read_fds, $write_fds, $except_fds, 1))
  129. {
  130. if(!$ret)break;
  131. foreach($read_fds as $fd)
  132. {
  133. if($ret_str = fread($fd, 8192))
  134. {
  135. echo $ret_str;
  136. }
  137. else
  138. {
  139. exit;
  140. }
  141. }
  142. }
  143. break;
  144. default:
  145. echo "Usage: workermand {start|stop|restart|reload|kill|status}\n";
  146. exit;
  147. }
  148. function force_kill()
  149. {
  150. $ret = $match = array();
  151. exec("ps aux | grep -E '".Man\Core\Master::NAME.":|workermand' | grep -v grep", $ret);
  152. $this_pid = posix_getpid();
  153. $this_ppid = posix_getppid();
  154. foreach($ret as $line)
  155. {
  156. if(preg_match("/^[\S]+\s+(\d+)\s+/", $line, $match))
  157. {
  158. $tmp_pid = $match[1];
  159. if($this_pid != $tmp_pid && $this_ppid != $tmp_pid)
  160. {
  161. posix_kill($tmp_pid, SIGKILL);
  162. }
  163. }
  164. }
  165. }
  166. function stop_and_wait($wait_time = 6)
  167. {
  168. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  169. if(empty($pid))
  170. {
  171. //exit("server not running?\n");
  172. }
  173. else
  174. {
  175. $start_time = time();
  176. posix_kill($pid, SIGINT);
  177. while(is_file(WORKERMAN_PID_FILE))
  178. {
  179. clearstatcache();
  180. usleep(1000);
  181. if(time()-$start_time >= $wait_time)
  182. {
  183. force_kill();
  184. force_kill();
  185. unlink(WORKERMAN_PID_FILE);
  186. usleep(500000);
  187. break;
  188. }
  189. }
  190. echo "Workerman stoped\n";
  191. }
  192. }