hyperf 定时任务本身不生成 pid 文件,真正需关注的是主服务进程(master)的 runtime/hyperf.pid;crontab-dispatcher 为 fork 子进程,无 pid 文件,但内存泄漏可能间接导致 master 异常退出和 pid 失效。

Hyperf 定时任务进程本身不生成独立的 PID 文件,真正需要关注的是 crontab-dispatcher 进程 —— 它由 hyperf/crontab 组件启动,负责每秒轮询并分发定时任务。这个进程不会写入 PID 文件,也不受 Swoole worker 生命周期管理,所以不存在“PID 文件丢失”导致无法重启的问题。但用户实际遇到的,往往是 主服务进程(master)的 PID 文件缺失或失效,进而影响整体重启流程。
确认是哪个进程的 PID 文件出了问题
Hyperf 项目中只有主服务进程(即执行 php bin/hyperf.php start 启动的 master 进程)会依赖或生成运行时 PID 文件(如 runtime/hyperf.pid),而 crontab-dispatcher 是 fork 出来的子进程,不维护自己的 PID 文件。因此所谓“定时任务进程 PID 文件丢失”,本质是:
- 主服务未正常退出,残留进程占着端口,但
runtime/hyperf.pid被删或内容过期; - crontab-dispatcher 因内存泄漏持续增长,最终拖垮整个服务,导致 master 异常退出,PID 文件未被清理或更新;
- 部署脚本或 CI/CD 流程中误删了
runtime/目录,连带清除了 PID 文件。
手动清理残留 + 安全重启主服务
不要直接 kill -9 所有 php 进程。优先按顺序操作:
- 查当前主进程 PID:
ps aux | grep 'php bin/hyperf.php start' | grep -v grep | head -n1 | awk '{print $2}'; - 若存在,先尝试优雅终止:
kill -USR2 [PID](Hyperf 支持该信号触发 graceful shutdown); - 若无响应,再用
kill [PID];仍卡住才用kill -9 [PID]; - 删除旧 PID 文件:
rm -f runtime/hyperf.pid; - 启动前检查端口(如 9501)是否释放:
lsof -i :9501或netstat -tulnp | grep :9501; - 确认无占用后,再执行:
php bin/hyperf.php start。
避免 crontab-dispatcher 引发连锁故障
crontab-dispatcher 不写 PID 文件,但它长期运行会导致内存缓慢上涨,最终触发 OOM 或 worker 异常退出,间接造成主进程崩溃、PID 文件失效。关键预防措施:
- 所有定时任务类中,禁止使用静态变量缓存数据、全局连接或未关闭的协程资源;
- 数据库查询务必加
limit,避免大结果集加载到内存; - 任务逻辑里不用
sleep()或阻塞 IO,改用co::sleep(); - 本地复现时,把分钟级任务临时改为秒级 +
worker_num=1,快速观察内存变化; - 生产环境开启
crontab.max_processes限制 dispatcher 并发数(Hyperf v3.2+ 支持)。
自动化重启脚本应包含 PID 验证逻辑
单纯删除 PID 文件再启动不够可靠。推荐在重启脚本中加入验证步骤:
- 启动后等待 2 秒,读取
runtime/hyperf.pid内容; - 用
ps -p [PID] -o pid=检查该 PID 是否真实存在且属于 hyperf; - 调用
curl -s http://127.0.0.1:9501/health(如有健康接口)确认服务已响应; - 若任一环节失败,自动回滚并报错,避免“假启动”。











