workerman进程关闭终端即退出是因为默认以前台模式运行,需加-d参数或用systemd管理才能守护运行;-d依赖pidfile路径可写且为绝对路径,否则静默失败。

Workerman进程启动后为什么一关闭终端就退出?
因为默认以调试模式运行,php start.php start 启动的是前台进程,终端断开即父进程被 kill。这不是 bug,是设计如此——Workerman 本身不内置 daemonize 逻辑,得靠参数或系统服务接管。
正确做法是加 -d 参数: php start.php start -d。它会触发 Workerman 内部的 fork + setsid 流程,脱离终端控制。注意:必须确保当前用户有权限写 runtime 目录(如 storage/logs 或自定义的 pid_file 路径),否则 -d 会静默失败,进程看似启动实则几秒后退出。
-
start.php中需明确设置$worker->pidFile = '/var/run/workerman.pid';,否则默认用workerman.pid(相对路径),daemon 模式下容易因工作目录变化导致写入失败 - 不要依赖
nohup php start.php start &,Workerman 自身未处理 SIGHUP,子进程仍可能被中断 - 检查
ulimit -n,生产环境建议设为 65535;Workerman 启动时若提示"Too many open files",就是这里卡住
如何安全重启 Worker 进程而不丢连接?
Workerman 的 reload 不是简单 kill + fork,而是平滑 reload:新进程启动并 ready 后,旧进程才开始拒绝新连接、等待已有连接 close。但前提是你的代码没阻塞事件循环。
执行 php start.php reload 前务必确认:
- 所有耗时操作(如数据库查询、curl)必须异步或超时控制,否则
onWorkerStart或onMessage里 sleep(5) 会导致 reload 卡住,旧进程无法退出 - 使用
Worker::reloadGracefully()是更可控的方式,可在代码中主动触发,适合配合配置热更新 - 若用
register_shutdown_function做清理,要留意 reload 时该函数是否被重复注册(多次 include 同一文件易触发)
systemd 管理 Workerman 时常见权限和路径问题
用 systemd 替代 -d 更可靠,但 Unit 文件里几个字段极易出错:
-
User=www-data必须与 PHP 进程实际运行用户一致,否则pidFile写入失败,status查不到进程 -
WorkingDirectory必须设为项目根目录(不是start.php所在目录),否则自动加载器找不到类,报Class not found -
Restart=always要搭配RestartSec=3,避免频繁崩溃触发 systemd 限流;同时在start.php中捕获致命错误,防止未 catch 的Fatal error导致 worker 异常退出却不打日志 - 日志别只依赖
StandardOutput=journal,Workerman 内部的Worker::$logFile仍要指向可写的绝对路径,否则onError回调的日志全丢
为什么 php start.php status 总显示 no worker?
核心原因只有两个:pid 文件读取失败,或 worker 进程已僵死但 pid 文件残留。先手动检查 cat /var/run/workerman.pid 是否存在且内容是数字,再 kill -0 $(cat /var/run/workerman.pid) 看是否返回 0。
常见干扰项:
- 多个
start.php实例用了同一pidFile,后启的覆盖前者的 pid,status只查最后一个 - PHP 版本不兼容:Workerman 4.x 要求 PHP >= 7.1,用 PHP 5.6 运行虽能启动,但
pcntl_fork行为异常,status无法获取子进程状态 - SELinux 启用时,
pidFile路径若不在/var/run或/tmp标准上下文内,会被拦截写入,setenforce 0临时验证即可定位
真正难排查的是多端口监听时部分 worker 启动失败——比如 TextProtocol 和 WebSocket 共用一个 Worker 实例但端口冲突,只会静默跳过,status 仍显示“running”,实际少了一组进程。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











