正确写法是 gdb ./path/to/program -p pid 或 gdb /usr/bin/nginx -p 12345,必须指定可执行文件路径以加载符号表,否则 list 看不到源码、print 报“no symbol table is loaded”。

gdb -p 附加运行中进程的正确写法
必须带可执行文件路径,不能只用 gdb -p <pid></pid>。否则 GDB 无法加载符号表,list 看不到源码,print 可能报 No symbol table is loaded。
正确命令是:gdb ./path/to/program -p <pid></pid>(开发环境常见路径如 ./bin/ceph-osd)或 gdb /usr/bin/nginx -p 12345(生产环境常用绝对路径)。
- 先确认进程真实可执行路径:
readlink -f /proc/<pid>/exe</pid> - 确保该二进制带调试符号(编译时用了
-g或-ggdb),否则变量名、行号全不可见 - 若提示
Permission denied,需用 root 或进程所属用户运行 gdb
为什么 attach 后经常 list 不出源码
核心原因是 GDB 找不到源文件位置。即使符号表存在,GDB 默认按编译时记录的绝对路径查找源码(比如 /home/user/ceph/src/osd/OSD.cc),而你当前工作目录或源码已移动/重建。
- 用
info sources查看 GDB 认为源码该在哪儿 - 用
directory /your/actual/src/path告诉 GDB 新位置(可多次添加) - 临时方案:启动时加
-d /path,如gdb -d ~/ceph/src ./bin/ceph-osd -p 1234 - 如果源码彻底没了,至少还能用
disassemble和info registers看汇编和寄存器
attach 进程后程序立即卡住?别急着 kill
GDB attach 默认会向目标进程发 SIGSTOP,这是正常行为——它得先暂停才能控制执行流。你看到进程状态变成 T (stopped) 是预期结果,不是崩溃。
- 用
continue(或简写c)恢复运行 - 想让它一 attach 就继续跑,启动后立刻输
c,别等 prompt - 如果
c后仍无响应,检查是否被断点拦截(info breakpoints)、或进程本身正在等锁/信号 - 误操作停太久?用
detach安全退出,不终止目标进程
调试守护进程(daemon)前必须确认的三件事
nginx、ceph-osd、redis-server 这类进程 fork 后会脱离终端、重设 uid、关闭 fd,直接 gdb -p 可能失败或看不到完整上下文。
- 确认进程没被
prctl(PR_SET_DUMPABLE, 0)禁止调试(cat /proc/<pid>/status | grep Dumpable</pid>,值为0则不行) - 检查是否以
nohup或 systemd 启动:systemd 需先sudo systemctl set-property ceph-osd@0 Delegate=true再sudo systemctl daemon-reload - 守护进程常关闭 stdio,attach 后用
call write(2,"hello\n",6)测试是否还能系统调用,避免误判“无响应”
info sources 和 info files,比反复重启进程省十分钟。











