本文目录导读:

- 方案一:Supervisor(最推荐,PHP官方常用)
- 方案二:Systemd(系统级,适合开机自启)
- 方案三:Shell 循环 + nohup(极简临时方案)
- 方案四:Docker + Restart Policy(容器化场景)
- 方案五:PHP 内部自守护(适合单进程服务)
- 关键注意点
PHP进程意外退出(如崩溃、OOM被系统杀掉等)是非常常见的问题,拉起(守护)进程有几种成熟方案,从简单到复杂,可以根据你的实际场景选择:
Supervisor(最推荐,PHP官方常用)
这是 PHP-FPM、队列进程(如 Laravel Queue Worker)、常驻脚本最主流的守护方案。
安装
# Ubuntu / Debian apt-get install -y supervisor # CentOS / RHEL yum install -y supervisor
配置示例(守护一个PHP常驻脚本)
创建 /etc/supervisor/conf.d/my-worker.conf:
[program:my_worker] ; 启动命令 - 注意使用绝对路径 command=php /var/www/html/worker.php ; 进程用户 user=www-data ; 自动启动 autostart=true ; 意外退出自动重启 autorestart=true ; 重启间隔时间(秒) startsecs=3 startretries=3 ; 日志 stdout_logfile=/var/log/my_worker.out.log stderr_logfile=/var/log/my_worker.err.log ; 最大内存占用(超了会kill并重启,防止内存泄漏) memory_limit=512MB
启动与常用命令
supervisorctl reread supervisorctl update supervisorctl start my_worker supervisorctl status
优点:配置简单、支持多进程、有Web管理界面、内存限制、重启策略清晰。
Systemd(系统级,适合开机自启)
如果你的 PHP 进程是系统服务级别的,用 systemd 天然集成开机自启。
创建 Service 文件
/etc/systemd/system/php-worker.service:
[Unit] Description=PHP Worker Service After=network.target [Service] ; 工作目录 WorkingDirectory=/var/www/html ; 启动命令 ExecStart=/usr/bin/php /var/www/html/worker.php ; 崩溃自动重启 Restart=always RestartSec=3 ; 用户和组 User=www-data Group=www-data ; 如果卡死,强制杀掉 TimeoutStopSec=10 ; 内存限制(可选,触发 OOM 会重启) MemoryMax=512M [Install] WantedBy=multi-user.target
启用和启动
systemctl daemon-reload systemctl enable php-worker systemctl start php-worker # 查看状态和日志 systemctl status php-worker journalctl -u php-worker -f
Shell 循环 + nohup(极简临时方案)
不推荐生产,但快速验证时很好用:
#!/bin/bash
while true; do
php /var/www/html/worker.php
# 退出后等2秒再重启
sleep 2
done
后台运行:
nohup ./restart.sh > /dev/null 2>&1 &
Docker + Restart Policy(容器化场景)
如果进程跑在 Docker 里,直接依赖 Docker 的重启策略:
# docker-compose.yml 示例
services:
php-worker:
image: php:8.2-cli
command: ["php", "/app/worker.php"]
restart: always
这里 restart: always 表示:容器退出(无论退出码是什么)都会重启,除非显式 docker stop。
PHP 内部自守护(适合单进程服务)
某些长驻进程(如 WebSocket、TCP服务)可以在脚本内部捕获异常并重启协程/worker。
<?php
while (true) {
try {
// 你的核心业务代码
someLongRunningTask();
} catch (\Throwable $e) {
// 记录异常,稍后自动重试
error_log("Worker crashed: " . $e->getMessage());
sleep(5); // 防止频繁 crash
continue;
}
// 正常退出(例如任务完成一次),继续循环
usleep(100000);
}
这个只解决 PHP 代码异常导致的退出,解决不了 OOM Kill 或 段错误。
关键注意点
| 问题 | 注意事项 |
|---|---|
| 内存泄漏 | 常驻进程要定期 gc_collect_cycles(),并配合 memory_limit 触发重启 |
| 僵尸进程 | 若长时间不退出的子进程,手动 kill -9,但注意拉起策略需能应对 kill -9 |
| 日志排查 | 一定要开启 error_log 或 log_errors,否则悲剧了找不到原因 |
| 拉起频率限制 | Supervisor/Systemd 都有 restartsec 防止无限重启 |
| FPM 进程(如 Nginx+PHP-FPM) | 本身有 pm.max_children 和 pm.start_servers 自动管理,一般不推荐 supervisor 管 FPM,直接用自带机制 |
你具体是什么场景?
我见过很多:
- Laravel/ThinkPHP 队列 → 用 Supervisor 最合适
- WebSocket 长连接 → Supervisor 或 Systemd
- 定时任务(cron) → 用 Cron 本身 + 锁文件即可,不需要常驻
- TCP/UDP 服务 → 也用 Supervisor
告诉我你的具体业务,我可以给出更精准的配置。