workerman 5.2.3 不提供单一全局异常钩子,需分层处理:fatal error 无法拦截,靠 ini_set+register_shutdown_function 桥接日志;exception/error 可用 try/catch、set_exception_handler 和 set_error_handler 捕获转换;主进程自动重启异常 worker,配合 supervisor 和结构化日志实现不丢错误、快速恢复、准确定位。

Workerman 5.2.3 本身不提供“全局捕获所有运行异常”的单一钩子,但可通过组合 PHP 原生机制与 Workerman 的进程模型实现完整覆盖——重点不是“阻止崩溃”,而是“不丢错误、快速恢复、准确定位”。
1. Fatal Error 必须靠日志桥接,无法拦截
Fatal Error(如调用未定义函数、类不存在、语法错误在运行时暴露)会直接终止 Worker 子进程,不能被 try/catch、set_exception_handler 或 set_error_handler 捕获。Workerman 主进程检测到子进程非正常退出(exit code ≠ 0),会自动拉起新 Worker,这是默认容错行为。
关键操作是确保错误信息可追溯:
- 在
start.php开头紧贴<?php添加:ini_set('log_errors', 'On');ini_set('error_log', '/path/to/workerman_fatal.log'); - 配合
register_shutdown_function检查error_get_last(),仅当类型为E_ERROR、E_PARSE、E_COMPILE_ERROR等时,写入含worker_id、pid、时间戳的结构化日志 - 避免在 shutdown 函数中做网络请求或大文件写入,防止阻塞退出流程
2. 可捕获异常需分层处理
业务中抛出的 Exception 或 PHP 7+ 的 Error(非 Fatal 类)可以被有效拦截:
- 在
onMessage、onConnect等回调内主动try/catch,处理数据库超时、API 调用失败等预期异常 - 全局兜底:用
set_exception_handler捕获未被捕获的Throwable,记录完整堆栈并触发告警 - 把 PHP 错误(
E_WARNING、E_NOTICE)转为异常:set_error_handler(function($level, $msg, $file, $line) { throw new ErrorException($msg, 0, $level, $file, $line); });
3. 进程级异常靠主进程监控和外部工具补位
Workerman 主进程通过 SIGCHLD 信号感知 Worker 退出,但不会告诉你“为什么退出”。需结合系统级手段:
- 查看
workerman.log末尾是否有exit with status 256——这代表被内核 kill(如pcntl_fork被禁用、段错误),不是 PHP 异常 - 用
ps aux | grep start.php确认 master 是否存活;若 master 在、worker 全无,大概率是onWorkerStart抛了未捕获异常或致命错误 - 生产环境建议用 Supervisor 管理,并配置:
redirect_stderr=truestdout_logfile=/var/log/workerman_supervisor.log
否则 Fatal Error 堆栈会直接进 Supervisor 黑洞
4. 日志配置不到位,等于没监控
很多“查不到错误”本质是日志静默丢失:
- 确认
Worker::$logFile指向路径可写,磁盘未满(df -h) - 开发调试阶段,在
start.php加:error_reporting(E_ALL);ini_set('display_errors', 'on');use Workerman\Config; Config::$debug = true; - 禁用
echo/var_dump()调试——输出不可控;改用file_put_contents('/tmp/debug.log', ...)











