workerman 加 -d 启动后消失的根本原因是 pidfile 写入失败,必须设为绝对路径并确保 php 运行用户有写权限;日志在 -d 模式下默认丢弃,需手动指定绝对路径的 stdoutfile 和 stderrfile;代码更新必须 reload 或 restart,-d 本身不支持热重载。

Workerman 必须加 -d 参数才能真正守护进程运行,不加就是前台进程,关终端就死;但加了之后若 pidFile 路径不可写或为相对路径,会静默失败——进程几秒后自动退出,表面看“启动成功”实则没跑。
为什么 php start.php start -d 有时启动了又消失?
根本原因不是命令写错,而是 Workerman 在 daemon 模式下依赖 pidFile 写入成功来维持子进程生命周期。它内部会 fork 两次、调用 posix_setsid() 脱离终端,但若写 pidFile 失败(比如权限不足、目录不存在、路径是相对路径),主进程会直接退出,子进程没机会真正接管。
-
Worker::$pidFile必须设为绝对路径,例如/var/run/workerman.pid或/path/to/your/project/runtime/workerman.pid - 确保运行 PHP 的用户对该路径有写权限:
mkdir -p /var/run/workerman && chown www-data:www-data /var/run/workerman - 不要依赖默认的
workerman.pid(相对路径),在start.php开头显式设置:Worker::$pidFile = '/var/run/workerman.pid'; - 启动后立刻检查:
ls -l /var/run/workerman.pid和ps aux | grep start.php
-d 和前台运行(不加参数)的日志行为差异
日志不是“有没有”,而是“输出到哪”:前台模式下所有 echo、var_dump 直接刷到终端;-d 模式下默认全部丢进 /dev/null,相当于静音。
- 想保留日志,必须手动指定:
Worker::$stdoutFile = '/path/to/stdout.log';和Worker::$stderrFile = '/path/to/stderr.log'; - 这两个路径也必须是绝对路径,且 PHP 用户有写权限
- 日志文件不会自动轮转,生产环境需配合 logrotate 或自行实现
- 调试阶段别用
-d,先用php start.php start看清报错再切后台
守护进程 ≠ 热重载,改代码必须 reload 或 restart
Workerman 的 -d 只解决“后台常驻”,不解决“代码更新”。它没有 Swoole 那种 inotify 自动 reload 机制,所有代码变更都需显式触发进程重启。
-
php start.php reload:平滑重启,已建立连接不中断,适合 HTTP/WebSocket 服务 -
php start.php restart:先 stop 再 start,会有短暂服务中断 -
php start.php stop -g:优雅停止,等当前请求结束再退,比普通stop更安全 - 注意:
reload仅重载 PHP 文件内容,不重读配置文件(如数据库连接参数),这类变更仍需restart
真正容易被忽略的是 pidFile 的路径和权限——它不像 Web 服务那样报错明显,而是默默失败。每次加 -d 启动后,第一件事不是看服务是否响应,而是查 pidFile 是否存在、内容是否为真实 PID、对应进程是否活着。











