首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 進程監控與自動重啟實戰指南

     編輯:PHP 綜合知識

針對長時間運行的後台腳本(如 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);
}

避坑指南:三個關鍵細節

1. grep 過濾自身輸出

直接執行 ps ax | grep perl > file 時,grep 進程本身會出現在輸出中。加入 grep -v "> $psfile" 可過濾包含重定向文件名的行,避免誤判。

2. system() 的阻塞陷阱

system() 會等待子進程結束才返回,導致多進程重啟時串行等待。解決方法:命令末尾加 & 讓進程在後台運行,並改用 shell_exec() 或 exec() 非阻塞調用。

3. 輸出重定向防止殭屍進程

重啟命令建議加上 > /dev/null 2>&1 或導向日誌文件,避免標準輸出/錯誤輸出阻塞進程退出。

進階優化建議

  • PID 文件鎖定:啟動時寫入 PID 文件,停止時讀取 PID 發送信號,比 grep 更精準
  • Systemd/Supervisor 托管:生產環境建議使用成熟的進程管理工具,而非自製腳本
  • 健康檢查端點:進程內建 HTTP/TCP 健康檢查,比單純進程存活判斷更可靠

完整監控腳本範例

<?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);
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved