workerman必须用systemd实现可靠开机自启,因nohup和-d守护模式无法管理进程生命周期,systemd要求主进程前台运行(需--daemon=0)、type=simple、user非root、服务文件置于/etc/systemd/system/并执行daemon-reload。

Workerman 必须用 systemd 实现可靠开机自启,nohup 或 crontab @reboot 都不行——它们不管理进程生命周期,崩溃不重启、重启后不拉起、无法联动依赖服务(比如 Redis 未就绪时 Workerman 就抢着启动)。
为什么不能用 nohup 或 -d 守护模式?
systemd 要求主进程前台运行,否则会立刻判定为“启动失败”并杀掉。Workerman 默认加 -d 或用 --daemon=1 启动时,主进程 fork 出子进程后自己就 exit 了,systemd 看不到有效进程,状态永远是 inactive (dead)。
- 必须去掉
-d,改用--daemon=0(新版)或start -d=false(旧版) -
Type=simple是硬性要求,别写成forking——后者是给传统 daemon(如 nginx、redis)用的,Workerman 不符合其 fork+父进程退出模型 - 如果误配成
Type=forking,systemctl status会显示failed,且journalctl里看不到 PHP 错误,因为 systemd 根本没等子进程起来就放弃了
workerman.service 文件必须放对位置且重载
服务文件必须放在 /etc/systemd/system/ 下,不是 /lib/systemd/system/(那是包管理器专用路径,手动放这里 systemd 会忽略)。
- 文件名必须以
.service结尾,例如workerman.service - 写完后必须执行
sudo systemctl daemon-reload,否则systemctl start会报Unit workerman.service not found - 权限建议设为
644(sudo chmod 644 /etc/systemd/system/workerman.service),非可执行权限
关键配置项怎么填才不踩坑?
一个能跑通的最小可用配置核心就三处:用户、路径、启动命令。
-
User必须是非 root 用户(如www-data、nginx或项目专属用户),否则bind()会因权限被拒,报Permission denied -
WorkingDirectory设成项目根目录(如/var/www/myapp),否则相对路径加载配置或日志会失败 -
ExecStart的 PHP 路径必须用绝对路径(which php查),脚本路径也必须绝对(如/var/www/myapp/start.php),且末尾不能带-d -
Restart=always必须加,但注意:它只在进程退出后触发;如果start.php因语法错误直接 fatal error 退出,systemd 不认为这是“崩溃”,不会重启,得靠journalctl查日志定位
启动失败时第一反应不是改配置,而是看日志
别反复 enable、start、stop,先盯住真实输出:
- 实时日志:
sudo journalctl -u workerman -f,按 Ctrl+C 退出 - 最后一次启动的完整上下文:
sudo journalctl -u workerman -n 50 --no-pager - 常见错误信号:
code=exited, status=255多半是 PHP 解析失败或扩展缺失;code=killed, signal=KILL往往是 OOM 被系统干掉;Failed to start且无后续日志,大概率是ExecStart命令路径写错或权限不足
最易被忽略的是 WorkingDirectory 权限和 User 的 home 目录可访问性——哪怕脚本本身没读写操作,PHP 启动时也会尝试访问用户 home 下的 .phpenv 或扩展配置,若不可达可能静默失败。











