Linux 学习资料 https://pan.baidu.com/s/1A6qqBk2ViE_Le2cQjSowkQ?pwd=7uz8
一、命令简介
pstack 是一个用于显示指定进程的栈跟踪(stack trace)信息的命令行工具。它能够输出进程内所有线程的调用栈,这对于调试程序挂起、死锁或性能瓶颈等问题非常有用。该命令通常需要由目标进程的属主用户或 root 用户执行。
二、语法格式
bash
运行
pstack [选项] <进程ID (PID)>参数说明:
<进程ID (PID)>:必需参数,指定要查看栈跟踪的目标进程的进程 ID。
三、常用选项及说明
pstack 命令本身通常没有复杂的选项。其核心功能就是接受一个进程 PID 作为参数。在某些发行版或实现中,可能会支持以下选项:
表格
| 选项 | 说明 |
|---|---|
| -h, --help | 显示帮助信息。 |
| -V, --version | 显示版本信息。 |
注意:pstack 的实现可能因 Linux 发行版而异。在一些系统中,它可能是一个简单的 shell 脚本包装器,调用 gstack 或 gdb 来实现功能。最可靠的方式是查看您系统上 pstack 的手册页 (man pstack)。
四、示例用法
示例 1:查看指定进程的栈跟踪
这是最基础的用法,直接提供进程 PID。
bash
运行
sudo pstack 1234输出将显示进程 1234 中每个线程的调用栈,格式类似于:
text
Thread 1 (Thread 0x7f8a5a7fe700 (LWP 1234)): #0 0x00007f8a59e8bf0d in nanosleep () from /lib64/libc.so.6 #1 0x00007f8a59e8bd94 in sleep () from /lib64/libc.so.6 #2 0x0000561f3a4a5a1b in main ()示例 2:结合 ps 和 grep 命令定位并分析进程
首先,使用 ps 命令找到目标进程的 PID,然后使用 pstack 进行分析。
bash
运行
# 1. 查找名为 “my_server” 的进程 ps aux | grep my_server # 假设输出显示 PID 为 4551 # 2. 查看该进程的栈跟踪 sudo pstack 4551输出将详细列出进程 4551 中所有线程的栈帧,帮助开发者理解程序在特定时刻的执行路径和状态。
示例 3:分析多线程程序的线程状态
对于一个多线程程序(如示例中 PID 为 4551 的进程),pstack 会清晰地列出每个线程(LWP,轻量级进程)的栈跟踪。
bash
运行
sudo pstack 4551典型输出结构如下,可以看到主线程(Thread 1)和多个工作线程(Thread 2-N)各自在执行的函数调用链:
text
Thread 7 (Thread 0x7f3c2b7fe700 (LWP 4552)): #0 0x00007f3c2a5d23dc in epoll_wait () from /lib64/libc.so.6 #1 0x000055a1b2a01730 in ub::EPollEx::poll () ... Thread 1 (Thread 0x7f3c2c7fe700 (LWP 4551)): #0 0x00007f3c2a59b1a5 in __nanosleep_nocancel () from /lib64/libc.so.6 #1 0x00007f3c2a59b010 in sleep () from /lib64/libc.so.6 #2 0x000055a1b29a0d79 in Ad_preprocess::run ()五、注意事项
- 权限要求:pstack 需要访问目标进程的内存空间,因此通常必须由 root 用户或目标进程的属主用户运行。普通用户无法查看其他用户进程的栈信息。
- 进程状态:pstack 会短暂挂起(ptrace)目标进程以获取其内存信息。对于生产环境中关键的核心服务,需谨慎使用,避免对服务造成影响。
- 依赖关系:pstack 的功能依赖于系统的调试信息和 ptrace 系统调用。如果目标进程被剥离了符号表(strip),输出的栈跟踪中函数名可能显示为内存地址,可读性会变差。
- 命令可用性:并非所有 Linux 发行版都默认安装 pstack。如果找不到该命令,可能需要安装 gdb(GNU 调试器),因为 pstack 有时是 gdb 的一个脚本或功能别名。您也可以直接使用 gdb -p <PID> 然后输入 thread apply all bt 命令来达到类似效果。
- 输出解读:栈跟踪的输出是从当前执行点(#0)向调用者(#1, #2...)回溯。#0 通常是线程当前阻塞或正在执行的函数。这对于定位死锁(多个线程互相等待锁)或无限循环非常有效。
Linux 学习资料 https://pan.baidu.com/s/1A6qqBk2ViE_Le2cQjSowkQ?pwd=7uz8