strace -p PID卡住不动通常因目标进程处于D状态(不可中断睡眠),如等待磁盘I/O或内核锁;此时应先用ps确认STAT列含D,再结合iostat、dmesg等排查根因。

strace -p PID 为什么卡住不动?
执行 strace -p PID 后终端没输出、不响应,不是命令错了,而是目标进程本身已无法响应内核——最常见原因是它卡在 D 状态(不可中断睡眠),比如等待磁盘 I/O 完成、持有内核锁或陷入驱动死循环。
先确认状态:ps -o pid,stat,comm -p PID,看 STAT 列是否含 D。如果是,strace 只是在忠实地同步阻塞,强行 Ctrl+C 多次反而可能让 strace 自身进入异常状态,后续无法再 attach。
- 真要退出跟踪:换终端执行
kill -SIGUSR1 $(pgrep -f "strace.*PID")(仅部分 strace 版本支持) - 想保留耗时但减少干扰:改用
strace -p PID -e trace=none -T,它只显示系统调用耗时,不刷参数和返回值 - 别反复重试 attach:D 状态下重试无意义,应转向检查 iostat、dmesg 或对应设备驱动日志
怎么定位是哪个系统调用卡住的?
默认全量输出容易淹没关键线索,尤其当程序高频调用 gettimeofday 或 clock_gettime 时,真正卡住的调用反而被刷屏盖过。
- 聚焦可疑类别:文件类用
-e trace=openat,read,write,fsync;网络类用-e trace=connect,recvfrom,sendto;锁相关留意futex和epoll_wait - 强制只看失败项:
strace -z -e trace=all -p PID,-z会跳过所有成功调用,只留= -1行 - 加
-T显示耗时,卡死调用通常显示为<...></...>(超长未返回)或时间值极大(如) - 配合
-s 256防止路径或地址被截断成"...",否则看不出 openat 打的是哪个路径
子进程卡死,strace 却没反应?
很多服务(如 nginx、python 多进程程序)主进程只做调度,实际干活的是子进程。不加 -f 就等于只盯大门,里面人干啥完全看不见。
- 必须加
-f:例如strace -f -p PID,否则 fork 出的子进程调用全被忽略 - 日志分离更清晰:用
-ff -o trace.log,每个子进程生成独立文件(如trace.log.1234、trace.log.1235),方便逐个排查 - 注意
-f会显著增加开销,生产环境慎用;若只关心某类子进程,可先ps --ppid PID找出其 PID,再单独strace -p 子PID
Permission denied 怎么办?
普通用户执行 strace -p PID 报 Operation not permitted,90% 是内核 ptrace_scope 拦住了,尤其 Ubuntu/Debian 默认设为 1。
- 查当前值:
cat /proc/sys/kernel/yama/ptrace_scope,值为 1 表示非 root 不能 trace 其他用户进程 - 临时放开:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope(重启失效) - 容器内运行需额外确认:
--cap-add=SYS_PTRACE是否启用,seccomp profile 是否禁用了ptrace系统调用 - 即使 root 用户,在容器中也受此限制,不能只看用户权限,得看容器能力集
真正卡死的系统调用往往藏在 D 状态、子进程、权限限制和过滤不当这四个交叉点里。漏掉任一环节,都可能把 futex 等待当成正常行为,或者把容器里缺 CAP 导致的 attach 失败误判为程序自身问题。


















