workermand 5.2 KB

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