Workerman中echo和var_dump无输出是因为常驻进程将stdout重定向至/dev/null;应改用Worker::log或写stderr,日志需指定路径并注意权限与轮转,调试WebSocket宜用十六进制查看原始数据,xdebug需配置多会话监听。

Workerman里echo和var_dump为什么经常没输出
因为Workerman是常驻进程,标准输出(stdout)默认被重定向到/dev/null,或者由主进程统一接管,子进程的echo和var_dump根本不会刷到终端。
常见错误现象:var_dump($data)执行了但控制台完全没反应;调试代码加在onMessage里却看不到任何输出。
- 不要依赖
echo或var_dump直接打屏,尤其在Linux后台运行时 - 如果非要临时看,得先确认当前Worker实例是否启用了
daemonize => false,且运行在前台模式 - 更稳妥的做法:用
file_put_contents('php://stderr', print_r($data, true) . "\n", FILE_APPEND)强行写stderr(部分环境仍可见)
Workerman日志该往哪写、怎么配才不丢数据
Workerman自带Worker::log(),但它底层用的是error_log(),默认走系统syslog或stderr——而这两者在守护进程模式下极易被吞掉或缓冲延迟。
使用场景:需要长期观察连接状态、协议解析异常、定时器触发情况等。
- 必须显式指定日志文件路径:
Worker::$logFile = '/tmp/workerman.log'; - 避免用
file_put_contents反复打开写入,性能差还可能丢行;改用error_log($msg, 3, $path)或封装成带锁的写入函数 - 注意权限:确保Worker进程用户(如www-data)对日志目录有写权限,否则静默失败
- 日志量大时,建议配合
rotating逻辑(比如按天切文件),否则单个日志滚到几百MB会拖慢tail -f
调试WebSocket连接时怎么看到真实收发的原始数据
Workerman的onMessage收到的是解包后的Frame内容,不是原始字节流;想确认前端发来的是否合规、有没有乱码或截断,得在更底层拦截。
参数差异:$connection->recv()不可直接调,WebSocket连接已被封装;必须用$connection->onWebSocketConnect或监听onBufferFull前的原始buffer。
- 最简单有效的方式:在
onMessage开头加Worker::log('RAW: ' . bin2hex($data));,十六进制看是否含非法字节 - 若需完整抓包,临时把
WebsocketConnection类里的decode方法打日志,但别改vendor源码——用继承+重写方式覆盖 - 注意UTF-8边界:
var_dump中文可能被截半显示,优先用mb_strlen($data, '8bit')确认长度,再判断是否完整
用xdebug连Workerman为什么总断连或不生效
Workerman多进程模型会让xdebug的IDE key、端口、超时配置全部失效——每个子进程启动时都得重新协商调试会话,而默认配置只支持单次请求。
性能影响:开启xdebug后,每个连接建立都会多一次TCP握手等待,高并发下直接卡死或拒绝新连接。
- 必须设置
xdebug.mode=debug+xdebug.start_with_request=yes(PHP ≥ 8.1) - CLI模式下要额外传参:
php -dxdebug.mode=debug -dxdebug.client_host=127.0.0.1 your_start.php - IDE里别只监听9003,得开“多会话监听”,否则第二个Worker进程的调试请求会被忽略
- 更轻量的替代:用
pcov做代码覆盖率分析,或blackfire查性能瓶颈,比xdebug稳定得多
真正麻烦的不是写日志,而是日志写到一半进程被kill -USR1 reload了——buffer没flush完就没了。所以关键操作前加fflush(STDERR)或ob_flush(),比写一百行var_dump都管用。










