会。fatal error会导致worker进程立即终止,无法被try/catch捕获;主进程检测到异常退出后自动拉起新worker,register_shutdown_function仅能事后记录日志,无法阻止退出。

Workerman里Fatal Error会直接杀掉Worker进程吗?
会。PHP的Fatal Error(比如调用未定义函数、类找不到、语法错误在运行时暴露)会导致当前Worker子进程立即终止,无法被try/catch捕获。主进程检测到子进程异常退出(exit code ≠ 0),就会拉起一个新Worker替代它——这是Workerman内置的容错机制,无需额外配置。
为什么set_error_handler和set_exception_handler都抓不到Fatal Error?
因为set_error_handler只处理E_WARNING、E_NOTICE这类错误;set_exception_handler只兜底未被捕获的Exception或Error(PHP 7+)。而Fatal Error属于更底层的PHP引擎中断,连register_shutdown_function都只能“事后收尸”,无法阻止进程退出。
-
register_shutdown_function能执行,但此时进程已处于退出路径,不能“救活”Worker - 它适合记录日志、清理资源,但不能阻止重启发生
- 若在
shutdown里再抛出异常或触发新Fatal Error,会导致日志丢失或supervisor报FATAL
怎么让Fatal Error发生后还能留痕并快速定位?
关键不是阻止重启,而是确保错误信息不丢。Workerman自身不接管PHP错误输出,必须手动桥接:
- 在
start.php顶部加:ini_set('log_errors', 'On');+ini_set('error_log', '/path/to/workerman_error.log'); - 配合
register_shutdown_function读取error_get_last(),判断是否为Fatal Error,然后写入结构化日志(含worker_id、pid、时间戳) - 避免在shutdown里做耗时操作(如网络请求、大文件写入),否则可能卡住进程退出
- 如果用Supervisor管理,务必配
redirect_stderr=true和stdout_logfile,否则Fatal Error的堆栈会直接进supervisor黑洞
Supervisor报FATAL是不是因为Fatal Error?
不一定。Supervisor的FATAL状态表示它连续多次(默认3次)启动Workerman主进程失败,常见真因是:
- 启动脚本本身有
Fatal Error(如require错路径、扩展没装),导致php start.php start -d秒退 -
pidFile路径不可写,-d静默失败,主进程启动后立刻退出 - 权限问题:比如
user=www-data但runtime/目录属主是root,Worker写日志失败后崩溃 - 别只看supervisor日志,先
php start.php start前台运行,看真实报错
真正难排查的是那些不报错但反复退出的情况——往往卡在onWorkerStart里某个阻塞操作(如没设超时的file_get_contents),让Supervisor误判为启动失败。











