/** * 解析运行命令 * php yourfile.php start | stop | restart | reload | status * @return void */ protected static function parseCommand() { // 检查运行命令的参数 global $argv; $start_file = $argv[0]; if (!isset($argv[1])) { exit("Usage: php yourfile.php {start|stop|restart|reload|status|kill}\n"); } // 命令 $command = trim($argv[1]); // 子命令,目前只支持-d -f $command2 = isset($argv[2]) ? $argv[2] : ''; // 记录日志 $mode = ''; if ($command === 'start') { if ($command2 === '-d') { $mode = 'in DAEMON mode'; } else { $mode = 'in DEBUG mode'; self::$force_delayed_kill = true; } } self::log("WorkerClient[{$start_file}] {$command} {$mode}"); // 检查主进程是否在运行 $master_pid = @file_get_contents(self::$pidFile); $master_is_alive = $master_pid && @posix_kill($master_pid, 0); if ($master_is_alive) { if ($command === 'start') { self::log("WorkerClient[{$start_file}] already running"); exit; } else { if ($command2 === '-f') { //向主进程发送SIGHUP信号,启用强制退出 self::$force_delayed_kill = true; self::log("WorkerClient[{$start_file}] turn on force_delayed_kill"); $master_is_alive && posix_kill($master_pid, SIGHUP); } } } elseif ($command !== 'start' && $command !== 'restart') { self::log("WorkerClient[{$start_file}] not running"); } // 根据命令做相应处理 switch ($command) { case 'kill': exec("ps aux | grep {$start_file} | grep -v grep | awk '{print \$2}' |xargs kill -SIGINT"); exec("ps aux | grep {$start_file} | grep -v grep | awk '{print \$2}' |xargs kill -SIGKILL"); break; // 启动 workerclient // 启动 workerclient case 'start': if ($command2 === '-d') { Worker::$daemonize = true; } break; // 显示 workerclient 运行状态 // 显示 workerclient 运行状态 case 'status': // 尝试删除统计文件,避免脏数据 if (is_file(self::$_statisticsFile)) { @unlink(self::$_statisticsFile); } // 向主进程发送 SIGUSR2 信号 ,然后主进程会向所有子进程发送 SIGUSR2 信号 // 所有进程收到 SIGUSR2 信号后会向 $_statisticsFile 写入自己的状态 posix_kill($master_pid, SIGUSR2); // 睡眠100毫秒,等待子进程将自己的状态写入$_statisticsFile指定的文件 usleep(100000); // 展示状态 readfile(self::$_statisticsFile); exit(0); // 重启 workerclient // 重启 workerclient case 'restart': // 停止 workeran // 停止 workeran case 'stop': self::log("WorkerClient[{$start_file}] is stopping ..."); // 向主进程发送SIGINT信号,主进程会向所有子进程发送SIGINT信号 $master_pid && posix_kill($master_pid, SIGINT); // 如果 $timeout 秒后主进程没有退出则展示失败界面 $timeout = 5; $start_time = time(); while (1) { // 检查主进程是否存活 $master_is_alive = $master_pid && posix_kill($master_pid, 0); if ($master_is_alive) { // 检查是否超过$timeout时间 if (time() - $start_time >= $timeout) { self::log("WorkerClient[{$start_file}] stop worker instantly fail"); if (self::$force_delayed_kill) { self::log("WorkerClient[{$start_file}] SIGKILL will be sent to alive workers."); } exit; } usleep(10000); continue; } self::log("WorkerClient[{$start_file}] stop success"); // 是restart命令 if ($command === 'stop') { exit(0); } // -d 说明是以守护进程的方式启动 if ($command2 === '-d') { Worker::$daemonize = true; } break; } break; // 平滑重启 workerclient // 平滑重启 workerclient case 'reload': posix_kill($master_pid, SIGUSR1); self::log("WorkerClient[{$start_file}] reload"); exit; // 未知命令 // 未知命令 default: exit("Usage: php yourfile.php {start|stop|restart|reload|status|kill}\n"); } }