pstack无法执行的根本原因是其底层调用gdb attach进程,而Linux ptrace机制默认限制非属主/非root用户attach其他进程,常见于权限不足、ptrace_scope=1或进程处于D状态。

pstack 无法执行:Permission denied 或 Cannot attach 到进程
根本原因是 pstack 底层调用 gdb attach,而 Linux 的 ptrace 机制默认禁止非属主/非 root 用户 attach 其他进程。常见触发场景包括:
- 目标进程由其他用户启动,你没加
sudo -
/proc/sys/kernel/yama/ptrace_scope值为1(Ubuntu/Debian 默认),普通用户只能 attach 自己的子进程 - 目标进程状态是
D(不可中断睡眠),比如卡在磁盘 I/O 或 NFS 挂载点上,ps -o pid,comm,state -p可验证
临时放开限制(仅调试用):echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope;长期方案应改用进程属主身份运行 pstack。
pstack 输出全是 ??() 或十六进制地址
说明二进制缺少调试符号,pstack 只能回溯到汇编层级,无法映射到函数名和行号。确认方式:file /proc/ —— 若输出含 stripped,即符号已被移除。
- 自己编译的 C/C++ 程序:重编译时加
-g参数,例如gcc -g -O2 server.c -o server - 系统库缺失符号:安装对应 debuginfo 包,如 CentOS 上装
glibc-debuginfo,Ubuntu 上装libc6-dbg - Go/Java/Rust 等语言:不用
pstack,Go 用kill -SIGUSR1,Java 用jstack
多线程程序中快速定位卡点
pstack 默认打印所有线程堆栈,每组以 Thread N (LWP XXXX): 开头。关键不是逐行读完,而是聚焦异常模式:
- 看哪些线程长期停在锁相关调用:如
__lll_lock_wait、futex、pthread_mutex_lock—— 大概率是锁竞争或死锁 - 对比多次采样:执行
for i in {1..5}; do pstack,再用>> trace.log; sleep 2; done grep "#0" trace.log | sort | uniq -c | sort -nr找高频栈顶行 - 关注重复出现的源码位置:比如连续 3 次都停在
server.c:88,那行就是第一怀疑对象
替代方案:不依赖 gdb 的轻量级方法
当 pstack 不可用(如没装 gdb、权限受限、或进程状态为 D)时,可尝试:
-
cat /proc/:只对内核态栈有效,且需进程处于内核态(如卡在系统调用中),输出极简,无用户态信息/stack -
kill -SIGUSR2(部分服务支持):如 nginx、redis 会打印内部状态,但非标准行为,需查文档确认 - 结合
top -H -p找出高 CPU 线程 LWP ID,再用cat /proc/查其内核栈(仍受限于状态)/task/ /stack
真正通用、可靠的方式仍是 pstack,但必须确保三要素齐备:权限、gdb 可用、符号完整——缺一不可,漏掉任一环节都会让输出失去诊断价值。









