<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] * * * * * ## 1 源代碼 ~~~ public static function runAll() { self::checkSapiEnv(); self::init(); self::parseCommand(); self::daemonize(); self::initWorkers(); self::installSignal(); self::saveMasterPid(); self::forkWorkers(); self::displayUI(); self::resetStd(); self::monitorWorkers(); } ~~~ ## 2 文件分析 ### 0 總體流程 ~~~ checkSapiEnv() ;檢查sapi環境是否為cli init() ;worker環境初始化 parseComand() ;命令行參數解析 daemonize() ;主進程守護模式啟動 initWorkers() ;初始化worker實例 installSignal() ;安裝信號處理句柄 saveMasterPid() ;保存主pid forkWorkers() ;創建worker子進程 displayUI() ;啟動信息顯示 resetStd() ;重定向輸入輸出 monitorWorkers() ;監控所有worker子進程 ~~~ ### 1 checkSapiEnv() 檢查sapi環境是否為wcli ~~~ if (php_sapi_name() != "cli") { exit("only run in command line mode \n"); } ~~~ 調用php_sapi_name()檢查sapi運行環境是否為cli ### 2 init() 環境初始化 ~~~ $backtrace = debug_backtrace(); self::$_startFile = $backtrace[count($backtrace) - 1]['file']; ~~~ 啟動文件 ~~~ if (empty(self::$pidFile)) { self::$pidFile = __DIR__ . "/../" . str_replace('/', '_', self::$_startFile) . ".pid"; } ~~~ 進程文件 ~~~ if (empty(self::$logFile)) { self::$logFile = __DIR__ . '/../workerman.log'; } touch(self::$logFile); chmod(self::$logFile, 0622); ~~~ 日志文件 `self::$_status = self::STATUS_STARTING;` worker狀態 ~~~ self::$_globalStatistics['start_timestamp'] = time(); self::$_statisticsFile = sys_get_temp_dir() . '/workerman.status'; ~~~ 啟動狀態記錄 `self::setProcessTitle('WorkerMan: master process start_file=' . self::$_startFile);` 設置進程名稱 worker::setProcessTitle() 見框架工具 worker文件 `self::initId();` 初始化workerid數據 worker::setProcessTitle() `Timer::init();` 計時器初始化 ### 3 parseComand() 命令行解析 `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]); $command2 = isset($argv[2]) ? $argv[2] : ''; ~~~ 命令參數獲取 ~~~ $mode = ''; if ($command === 'start') { if ($command2 === '-d') { $mode = 'in DAEMON mode'; } else { $mode = 'in DEBUG mode'; } } ~~~ php yourfile.php start debug調試模式啟動 php yourfile.php start -d 守護進程模式啟動 `self::log("Workerman[$start_file] $command $mode");` 日志記錄啟動信息 worker::log()見 框架工具 worker ~~~ $master_pid = @file_get_contents(self::$pidFile); $master_is_alive = $master_pid && @posix_kill($master_pid, 0); ~~~ 主進程id獲取與狀態檢測 posix_kill 見 基礎原理 基礎函數 ~~~ if ($master_is_alive) { if ($command === 'start') { self::log("Workerman[$start_file] already running"); exit; } } elseif ($command !== 'start' && $command !== 'restart') { self::log("Workerman[$start_file] not run"); } ~~~ 主進程啟動檢測 其他命令執行 `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; ~~~ >[info] kill命令的執行 exec() 見 基礎原理 基礎函數 ~~~ case 'start': if ($command2 === '-d') { Worker::$daemonize = true; } break; ~~~ >[info] start 命令的執行 設置守護進程模式 ~~~ case 'status': if (is_file(self::$_statisticsFile)) { @unlink(self::$_statisticsFile); } posix_kill($master_pid, SIGUSR2); usleep(100000); @readfile(self::$_statisticsFile); exit(0); ~~~ >[info] status命令的執行 刪除狀態文件 發送信號 等待一會 讀取狀態文件 ~~~ case 'restart': case 'stop': self::log("Workerman[$start_file] is stoping ..."); // Send stop signal to master process. $master_pid && posix_kill($master_pid, SIGINT); // Timeout. $timeout = 5; $start_time = time(); // Check master process is still alive? while (1) { $master_is_alive = $master_pid && posix_kill($master_pid, 0); if ($master_is_alive) { // Timeout? if (time() - $start_time >= $timeout) { self::log("Workerman[$start_file] stop fail"); exit; } // Waiting amoment. usleep(10000); continue; } // Stop success. self::log("Workerman[$start_file] stop success"); if ($command === 'stop') { exit(0); } if ($command2 === '-d') { Worker::$daemonize = true; } break; } break; ~~~ >[info] restart,stop命令的執行 ~~~ self::log("Workerman[$start_file] is stoping ..."); ~~~ 日志記錄 正在停止信息 ~~~ $master_pid && posix_kill($master_pid, SIGINT); ~~~ 主進程停止信號 ~~~ $timeout = 5; $start_time = time(); ~~~ 延遲計時 ~~~ $master_is_alive = $master_pid && posix_kill($master_pid, 0); ~~~ ~~~ if ($master_is_alive) { // Timeout? if (time() - $start_time >= $timeout) { self::log("Workerman[$start_file] stop fail"); exit; } // Waiting amoment. usleep(10000); continue; } ~~~ 檢測是否停止成功 ~~~ self::log("Workerman[$start_file] stop success"); ~~~ 日志記錄停止成功 ~~~ if ($command === 'stop') { exit(0); } ~~~ stop命令 直接退出 ~~~ if ($command2 === '-d') { Worker::$daemonize = true; } break; ~~~ restart -d 命令 設置守護模式 ~~~ case 'reload': posix_kill($master_pid, SIGUSR1); self::log("Workerman[$start_file] reload"); exit; ~~~ >[info] reload 命令 ~~~ default : exit("Usage: php yourfile.php {start|stop|restart|reload|status|kill}\n"); ~~~ 提示 命令行格式信息 ### 4 daemonize() 以守護模式啟動 ~~~ if (!self::$daemonize) { return; } ~~~ 檢測是否需要守護模式啟動 `umask(0);` 修改mask ~~~ $pid = pcntl_fork(); if (-1 === $pid) { throw new Exception('fork fail'); } elseif ($pid > 0) { exit(0); } ~~~ 創建進程 pcntl_fork() 見 基礎原理 基礎函數 ~~~ if (-1 === posix_setsid()) { throw new Exception("setsid fail"); } ~~~ session初始化 posix_setsid() 見 基礎原理 基礎函數 ~~~ $pid = pcntl_fork(); if (-1 === $pid) { throw new Exception("fork fail"); } elseif (0 !== $pid) { exit(0); } ~~~ ?? ### 5 initWorkers() 初始化所有worker實例 `foreach (self::$_workers as $worker) {}` 遍歷worker實例數組 ~~~ if (empty($worker->name)) { $worker->name = 'none'; } ~~~ 獲取worker名稱 ~~~ $worker_name_length = strlen($worker->name); if (self::$_maxWorkerNameLength < $worker_name_length) { self::$_maxWorkerNameLength = $worker_name_length; } $socket_name_length = strlen($worker->getSocketName()); if (self::$_maxSocketNameLength < $socket_name_length) { self::$_maxSocketNameLength = $socket_name_length; } ~~~ 名稱長度檢測 ~~~ if (empty($worker->user)) { $worker->user = self::getCurrentUser(); } else { if (posix_getuid() !== 0 && $worker->user != self::getCurrentUser()) { self::log('Warning: You must have the root privileges to change uid and gid.'); } } ~~~ 獲取用戶信息 ~~~ $user_name_length = strlen($worker->user); if (self::$_maxUserNameLength < $user_name_length) { self::$_maxUserNameLength = $user_name_length; } ~~~ 用戶名稱長度檢測 ~~~ if (!$worker->reusePort) { $worker->listen(); } ~~~ 開啟監聽端口 worker::listen() 見 框架工具的 worker類 ### 6 installSignal() 安裝主進程信號處理函數 ~~~ pcntl_signal(SIGINT, array('\Workerman\Worker', 'signalHandler'), false); pcntl_signal(SIGUSR1, array('\Workerman\Worker', 'signalHandler'), false); pcntl_signal(SIGUSR2, array('\Workerman\Worker', 'signalHandler'), false); pcntl_signal(SIGPIPE, SIG_IGN, false); ~~~ stop,reload,status,ignore信號接口函數注冊為worker::signalHanlder() signalHanlder() 見 框架工具 worker類 ### 7 saveMasterPid() 保存主進程id到pid文件 ~~~ self::$_masterPid = posix_getpid(); ~~~ 獲取pid信息 ~~~ if (false === @file_put_contents(self::$pidFile, self::$_masterPid)) { throw new Exception('can not save pid to ' . self::$pidFile); } ~~~ 寫入pid信息 ### 8 forkWorkers() 創建workers子進程 ~~~ foreach (self::$_workers as $worker) {} ~~~ 遍歷workers數組 ~~~ if (self::$_status === self::STATUS_STARTING) { if (empty($worker->name)) { $worker->name = $worker->getSocketName(); } $worker_name_length = strlen($worker->name); if (self::$_maxWorkerNameLength < $worker_name_length) { self::$_maxWorkerNameLength = $worker_name_length; } } ~~~ worker名稱獲取 ~~~ while (count(self::$_pidMap[$worker->workerId]) < $worker->count) { static::forkOneWorker($worker); } ~~~ 依次創建worker進程 forkOneWorker() 見 Worker功能函數 ### 9 displayUI() 輸出服務器啟動信息 ### 10 resetStd() 重定向標準輸出 設置標準輸出到指定輸出文件, ### 11 monitorWorkers() 監控worker進程 `self::$_status = self::STATUS_RUNNING;` 設置啟動狀態 `pcntl_signal_dispatch();` 根據信號調用相關 ~~~ $status = 0; $pid = pcntl_wait($status, WUNTRACED); ~~~ 等待子進程退出信號 `pcntl_signal_dispatch();` 根據信號調用相關 `if ($pid > 0) {}` 子進程退出處理 ~~~ else { // If shutdown state and all child processes exited then master process exit. if (self::$_status === self::STATUS_SHUTDOWN && !self::getAllWorkerPids()) { self::exitAndClearAll(); } } ~~~ 所有子進程退出后清理 ## 3 總結 worker啟動過程,完成啟動主流程。 >[info] 1 環境檢測與初始化 ~~~ self::checkSapiEnv(); self::init(); ~~~ >[info] 2 命令行解析 `self::parseCommand();` >[info] 3 主進程創建與運行 ~~~ self::daemonize(); self::initWorkers(); self::installSignal(); self::saveMasterPid(); ~~~ >[info] 4 子進程創建與啟動 `self::forkWorkers();` >[info] 5 監控子進程信號 ~~~ self::displayUI(); self::resetStd(); self::monitorWorkers(); ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看