直接attach正在运行的swoole worker进程可高效定位静默退出、协程卡死与内存泄漏等问题:先用ps精准获取活跃worker pid,再执行gdb -p pid -ex "thread apply all bt"捕获全栈快照,结合info proc mappings查rwx内存段、dump memory提取堆片段分析,全程无需中断服务。

直接 attach 正在运行的 Swoole Worker 进程,是定位静默退出、协程卡死、内存泄漏等底层问题最有效的方式之一。关键不在于“能不能 attach”,而在于“attach 后怎么看、看什么、怎么验证”。
快速定位目标 Worker 进程 PID
Worker 进程通常由 Swoole Master 进程 fork,独立运行且无明显命名标识,需结合进程树和启动参数识别:
- 用 ps aux --forest | grep php 查看进程层级,找到子进程(非 master_pid、非 manager_pid)中带
swoole或worker字样的行 - 更精准方式:ps -eo pid,ppid,cmd | awk '$2 == $(pgrep -f "php.*server.php" | head -1) && $3 ~ /php/' —— 筛出直属 Worker 子进程
- 确认进程活跃性:kill -0 PID 返回 0 表示进程仍在运行,可安全 attach
Attach 并获取全线程堆栈快照
无需中断服务,一条命令即可捕获当前所有线程的调用链,适合线上紧急诊断:
-
gdb -p PID -ex "thread apply all bt" -ex "quit" —— 输出全部线程完整回溯,重点观察是否有线程卡在
swReactorEpoll_wait、curl_multi_perform或无限循环函数内 - 若输出过长难以阅读,加
| grep -A5 -B5 "your_function_name"快速定位可疑帧 - 注意区分主线程(通常是 reactor 线程)与协程调度线程(如
sw_coro_create调用栈),Swoole v5.1.3+ 的符号已支持协程 ID(cid)标注
检查内存映射与可疑执行页
RSS 持续上涨但无明显泄漏点?可能是动态生成代码或 JIT 内存页异常增长:
- gdb -p PID -ex "info proc mappings" -ex "quit" | grep rwx —— 找出带可执行权限(rwx)的内存段,正常情况下应极少;若发现多个 >2MB 的 rwx 段,高度疑似 curl_hook 或扩展未清理的 JIT 缓冲区
- 配合 /proc/PID/status 中的
VmExe和VmLib值对比历史基线,判断是否新增异常可执行区域
导出堆内存片段供离线分析
当怀疑 zval 或 swString 缓冲区累积时,需提取原始内存做结构化解析:
- 先用 cat /proc/PID/maps | grep heap 获取主堆地址范围(如
7f0000000000-7f0000100000) - 执行 gdb -p PID -ex "dump memory /tmp/heap.bin 0x7f0000000000 0x7f0000100000" -ex "quit"
- 后续可用
php-meminfo或自定义脚本解析该二进制 dump,定位重复分配未释放的字符串或 resource 句柄
整个过程不依赖源码编译选项,只要系统装有 gdb 且 PHP 进程未被 strip 符号(Swoole 官方扩展默认保留),就能完成从 attach 到证据提取的闭环。难点不在命令本身,而在读懂堆栈里哪一帧真正阻塞了事件循环,或哪一段内存映射违背了预期行为模式。











