public static function checkTty() { if (self::$terminalHasClosed) { return; } if (!posix_ttyname(STDOUT)) { self::notice("The terminal is closed ,Server reloading"); self::addToRestartWorkers(array_keys(self::getPidWorkerNameMap())); self::restartWorkers(); self::$terminalHasClosed = true; } }
/** * 处理收到的管理员命令 * @param event_buffer $event_buffer * @param int $fd * @return boolean */ public static function dealCmd($connection, $length, $buffer, $fd = null) { // 管理员断开 if ($length == 0) { self::closeClient($fd); return; } self::$currentFd = $fd; $buffer = trim($buffer); $ip = self::getRemoteIp(); if ($ip != '127.0.0.1' && $buffer == 'status') { ServerLog::add("IP:{$ip} {$buffer}"); } // 判断是否认证过 self::$adminAuth[$fd] = !isset(self::$adminAuth[$fd]) ? 0 : self::$adminAuth[$fd]; if (self::$adminAuth[$fd] < 3) { if ($buffer != 'P@ssword') { if (++self::$adminAuth[$fd] >= 3) { self::sendToClient("Password Incorrect \n"); self::closeClient($fd); } self::sendToClient("Please Try Again\n"); return; } else { self::$adminAuth[$fd] = time(); self::sendToClient("Hello Admin \n"); return; } } $pid_worker_name_map = PHPServer::getPidWorkerNameMap(); // 单独停止某个worker进程 if (preg_match("/kill (\\d+)/", $buffer, $match)) { $pid = $match[1]; if (isset($pid_worker_name_map[$pid])) { self::sendToClient("Kill Pid {$pid} "); PHPServer::addToRestartWorkers(array($pid)); PHPServer::restartWorkers(); } else { self::sendToClient("Pid Not Exsits\n"); } return; } // 打印某个变量 print_r $current if (preg_match("/debug (.*)/", $buffer, $match)) { $var = trim($match[1]); $var = str_replace('$', '', $var); if (!$var) { self::sendToClient("Uesage debug var_name\n"); return; } self::sendToClient(PHPServer::debugVar($var) . "\n"); return; } switch ($buffer) { // 展示统计信息 case 'status': $status = PHPServer::getServerStatusInfo(); $worker_pids = PHPServer::getWorkerPids(); $loadavg = sys_getloadavg(); self::sendToClient("---------------------------------------GLOBAL STATUS--------------------------------------------\n"); self::sendToClient('start time:' . date('Y-m-d H:i:s', $status['start_time']) . ' run ' . floor((time() - $status['start_time']) / (24 * 60 * 60)) . ' days ' . floor((time() - $status['start_time']) % (24 * 60 * 60) / (60 * 60)) . " hours \n"); self::sendToClient('load average: ' . implode(", ", $loadavg) . "\n"); self::sendToClient(count(self::$connections) . ' users ' . count($worker_pids) . ' workers ' . count($pid_worker_name_map) . " processes\n"); self::sendToClient(str_pad('worker_name', self::$maxWorkerNameLength) . " exit_status exit_count\n"); foreach ($worker_pids as $worker_name => $pid_array) { if (isset($status['err_info'][$worker_name])) { foreach ($status['err_info'][$worker_name] as $exit_status => $exit_count) { self::sendToClient(str_pad($worker_name, self::$maxWorkerNameLength) . " " . str_pad($exit_status, 16) . " {$exit_count}\n"); } } else { self::sendToClient(str_pad($worker_name, self::$maxWorkerNameLength) . " " . str_pad(0, 16) . " 0\n"); } } PHPServer::sendCmdToAll(Cmd::CMD_REPORT_STATUS_FOR_MASTER); self::sendToClient("---------------------------------------PROCESS STATUS-------------------------------------------\n"); self::sendToClient("pid\tmemory proto port timestamp " . str_pad('worker_name', self::$maxWorkerNameLength) . " " . str_pad('total_request', 13) . " " . str_pad('recv_timeout', 12) . " " . str_pad('proc_timeout', 12) . " " . str_pad('packet_err', 10) . " " . str_pad('thunder_herd', 12) . " " . str_pad('client_close', 12) . " " . str_pad('send_fail', 9) . " " . str_pad('throw_exception', 15) . " suc/total\n"); break; // 停止server // 停止server case 'stop': PHPServer::stop(); break; // 平滑重启server // 平滑重启server case 'reload': PHPServer::addToRestartWorkers(array_keys($pid_worker_name_map)); PHPServer::restartWorkers(); self::sendToClient("Restart Workers "); break; // admin管理员退出 // admin管理员退出 case 'quit': self::sendToClient("Admin Quit\n"); self::$event->delAll(self::$connections[self::$currentFd]); fclose(self::$connections[self::$currentFd]); unset(self::$connections[self::$currentFd], self::$adminAuth[self::$currentFd]); break; case 'debug': self::sendToClient("Uesage debug var_name\n"); break; case '': break; default: self::sendToClient("Unkonw CMD \nAvailable CMD:\n status show server status\n stop stop server\n reload graceful restart server\n quit quit and close connection\n kill pid kill the worker process of the pid\n"); } }