針對長時間運行的後台腳本(如 Perl、Python 或 PHP CLI 守護進程),建立一套可靠的監控與自動重啟機制至關重要。本文分享一個基於 PHP 實現的進程監控方案,涵蓋進程掃描、狀態判斷、非阻塞重啟等關鍵技術點。
系統通過 ps ax | grep 進程關鍵字 獲取進程列表,解析輸出判斷目標進程是否存活;若不存在,則以非阻塞方式啟動新進程。
// 1. 將進程列表導出到臨時文件
$psfile = '/tmp/process_list.txt';
$command = "ps ax | grep perl | grep -v \"> $psfile\" > $psfile";
exec($command);
// 2. 讀取並解析進程列表
$process_array = file($psfile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$found = false;
foreach ($process_array as $line) {
if (strpos($line, $target_process_id) !== false) {
$found = true;
break;
}
}
// 3. 進程不存在時,後台重啟(關鍵在於結尾的 &)
if (!$found) {
$restart_cmd = "perl {$program} > {$log_path} 2>&1 &";
// 使用 shell 執行,確保 & 生效
shell_exec($restart_cmd);
}
直接執行 ps ax | grep perl > file 時,grep 進程本身會出現在輸出中。加入 grep -v "> $psfile" 可過濾包含重定向文件名的行,避免誤判。
system() 會等待子進程結束才返回,導致多進程重啟時串行等待。解決方法:命令末尾加 & 讓進程在後台運行,並改用 shell_exec() 或 exec() 非阻塞調用。
重啟命令建議加上 > /dev/null 2>&1 或導向日誌文件,避免標準輸出/錯誤輸出阻塞進程退出。
<?php
// monitor.php - 每分鐘通過 crontab 執行
$config = [
'perl_worker' => [
'pattern' => 'perl worker.pl',
'start_cmd' => 'cd /var/www/worker && php worker.php > worker.log 2>&1 &',
],
'python_task' => [
'pattern' => 'python task.py',
'start_cmd' => 'cd /var/www/task && python3 task.py > task.log 2>&1 &',
],
];
foreach ($config as $name => $cfg) {
$ps_file = sys_get_temp_dir() . "/ps_{$name}.txt";
exec("ps ax | grep '{$cfg['pattern']}' | grep -v grep > {$ps_file}");
$lines = file($ps_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (empty($lines)) {
error_log("[$name] 進程不存在,嘗試重啟...");
shell_exec($cfg['start_cmd']);
}
@unlink($ps_file);
}