workermand 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. Man\Core\Master::run();
  90. break;
  91. case 'stop':
  92. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  93. if(empty($pid))
  94. {
  95. exit("\033[33;40mWorkerman not running?\033[0m\n");
  96. }
  97. stop_and_wait();
  98. break;
  99. case 'restart':
  100. stop_and_wait();
  101. Man\Core\Master::run();
  102. break;
  103. case 'reload':
  104. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  105. if(empty($pid))
  106. {
  107. exit("\033[33;40mWorkerman not running?\033[0m\n");
  108. }
  109. posix_kill($pid, SIGHUP);
  110. echo "reload Workerman\n";
  111. break;
  112. case 'kill':
  113. force_kill();
  114. force_kill();
  115. break;
  116. case 'status':
  117. $address = Man\Core\Lib\Config::get('Monitor.listen');
  118. $sock = @stream_socket_client($address);
  119. if(!$sock)
  120. {
  121. exit("\n\033[31;40mcan not connect to $address \033[0m\n\n\033[31;40mWorkerman not running\033[0m\n\n");
  122. }
  123. fwrite($sock, 'status');
  124. $read_fds = array($sock);
  125. $write_fds = $except_fds = array();
  126. while($ret = stream_select($read_fds, $write_fds, $except_fds, 1))
  127. {
  128. if(!$ret)break;
  129. foreach($read_fds as $fd)
  130. {
  131. if($ret_str = fread($fd, 8192))
  132. {
  133. echo $ret_str;
  134. }
  135. else
  136. {
  137. exit;
  138. }
  139. }
  140. }
  141. break;
  142. default:
  143. echo "Usage: workermand {start|stop|restart|reload|kill|status}\n";
  144. exit;
  145. }
  146. function force_kill()
  147. {
  148. $ret = $match = array();
  149. exec("ps aux | grep -E '".Man\Core\Master::NAME.":|workermand' | grep -v grep", $ret);
  150. $this_pid = posix_getpid();
  151. $this_ppid = posix_getppid();
  152. foreach($ret as $line)
  153. {
  154. if(preg_match("/^[\S]+\s+(\d+)\s+/", $line, $match))
  155. {
  156. $tmp_pid = $match[1];
  157. if($this_pid != $tmp_pid && $this_ppid != $tmp_pid)
  158. {
  159. posix_kill($tmp_pid, SIGKILL);
  160. }
  161. }
  162. }
  163. }
  164. function stop_and_wait($wait_time = 6)
  165. {
  166. $pid = @file_get_contents(WORKERMAN_PID_FILE);
  167. if(empty($pid))
  168. {
  169. //exit("server not running?\n");
  170. }
  171. else
  172. {
  173. $start_time = time();
  174. posix_kill($pid, SIGINT);
  175. while(is_file(WORKERMAN_PID_FILE))
  176. {
  177. clearstatcache();
  178. usleep(1000);
  179. if(time()-$start_time >= $wait_time)
  180. {
  181. force_kill();
  182. force_kill();
  183. unlink(WORKERMAN_PID_FILE);
  184. usleep(500000);
  185. break;
  186. }
  187. }
  188. echo "Workerman stoped\n";
  189. }
  190. }