nohup php script.php & 可能失效,因PHP依赖终端输入、缓冲未刷新、相对路径错误、fork子进程未继承nohup守护行为,且无法防止OOM或ulimit终止;推荐用systemd管理。

nohup php script.php & 为什么经常失效
因为 nohup 默认只忽略 SIGHUP,但 PHP 脚本若依赖终端输入、调用 fgets(STDIN)、或内部触发 pcntl_signal 处理,仍可能被中断;更常见的是 stdout/stderr 缓冲未刷新,日志“看起来没输出”,误判为卡死。
- 加
> /dev/null 2>&1显式重定向,避免因终端关闭导致 write error 终止进程 - PHP 脚本开头加
set_time_limit(0); ignore_user_abort(true);,防超时或连接断开干扰 - 务必用绝对路径:如
nohup php /var/www/app/script.php > /var/log/script.log 2>&1 &,相对路径在后台常因工作目录变更而报file not found
PHP 内部用 pcntl_fork 后,nohup & 还管用吗
不管用。一旦 PHP 主进程 fork 出子进程,nohup 的信号屏蔽只作用于原始 shell 启动的进程,子进程默认继承父进程的 signal handler,但不继承 nohup 的守护行为。子进程仍可能随终端关闭收到 SIGHUP。
- 子进程中需手动调用
pcntl_signal(SIGHUP, SIG_IGN)忽略挂起信号 - 更稳妥做法是子进程里再调用
posix_setsid()脱离会话,成为真正独立进程组 - 不要依赖
&让 fork 后的子进程“自动后台化”——它只是让 shell 不等待,不代表进程已 daemonize
替代方案:systemd service 比 nohup & 更可靠
Linux 服务器上,长期运行的 PHP 脚本用 systemd 管理才是正解。nohup + & 是临时应急手段,缺乏重启策略、资源限制、日志轮转和状态监控。
- 写一个 unit 文件,如
/etc/systemd/system/php-worker.service,关键配置项:Type=simple、Restart=on-failure、RestartSec=10 - 用
StandardOutput=journal和StandardError=journal,日志统一走journalctl -u php-worker - 启动后用
sudo systemctl daemon-reload && sudo systemctl enable --now php-worker,比每次手敲nohup少出错
常见错误:脚本跑着跑着就没了,查不到进程
不是挂了,是被系统 kill 掉了——最常见原因是 OOM(内存溢出)或超出 ulimit 限制,nohup 完全不干预这类终止。
立即学习“PHP免费学习笔记(深入)”;
- 检查
dmesg -T | grep -i "killed process",看是否 OOM killer 干掉的php进程 - 用
ulimit -a查当前 shell 限制,特别是virtual memory和max open files,PHP CLI 默认不受 web server 限制,容易突破 - 后台运行前先测试:加
echo $$; sleep 300到脚本开头,再ps aux | grep $PID验证是否真存活,排除脚本秒退问题



















