如何知道程序在linux中卡在哪里?

Pav*_*ath 52 linux process debugging

我在我的 ubuntu 服务器上运行以下命令

root@slot13:~# lxc-stop --name pavan --logfile=test1.txt --logpriority=trace
Run Code Online (Sandbox Code Playgroud)

它似乎无限期地挂起。每当这发生在 AIX 上时,我只是用来获取违规进程的 PID 并说

$ procstack <pid_of_stuck_process>
Run Code Online (Sandbox Code Playgroud)

它用于显示进程的整个调用堆栈。procstack在 linux/ubuntu 中是否有任何等价物?

Tho*_*erk 48

我的第一步是在这个过程中运行 strace,最好

 strace -s 99 -ffp 12345
Run Code Online (Sandbox Code Playgroud)

如果您的进程 ID 是 12345。这将显示程序正在执行的所有系统调用。如何跟踪进程会告诉您更多信息。

如果你坚持要获得堆栈跟踪,谷歌告诉我相当于 pstack。但由于我没有安装它,我使用 gdb:

 tweedleburg:~ # sleep 3600 &
 [2] 2621
 tweedleburg:~ # gdb
 (gdb) attach 2621
 (gdb) bt
 #0  0x00007feda374e6b0 in __nanosleep_nocancel () from /lib64/libc.so.6
 #1  0x0000000000403ee7 in ?? ()
 #2  0x0000000000403d70 in ?? ()
 #3  0x000000000040185d in ?? ()
 #4  0x00007feda36b8b05 in __libc_start_main () from /lib64/libc.so.6
 #5  0x0000000000401969 in ?? ()
 (gdb)
Run Code Online (Sandbox Code Playgroud)


Lek*_*eyn 41

找到程序的堆栈跟踪已经给出了两个答案(记住首先安装调试符号!)。如果您想找出系统调用卡在何处,请检查/proc/PID/stack,其中列出了内核堆栈。例子:

$ cat /proc/self/stack
[<ffffffff81012b72>] save_stack_trace_tsk+0x22/0x40
[<ffffffff81213abe>] proc_pid_stack+0x8e/0xe0
[<ffffffff81214960>] proc_single_show+0x50/0x90
[<ffffffff811cd970>] seq_read+0xe0/0x3e0
[<ffffffff811a6a84>] vfs_read+0x94/0x180
[<ffffffff811a7729>] SyS_read+0x49/0xb0
[<ffffffff81623ad2>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
Run Code Online (Sandbox Code Playgroud)

  • 注意:根据 http://man7.org/linux/man-pages/man5/proc.5.html ... "/proc/[pid]/stack (自 Linux 2.6.29) 此文件提供了函数在此进程的内核堆栈中调用。**仅当内核是使用 CONFIG_STACKTRACE 配置选项构建时才提供此文件。**” (6认同)

Gil*_*il' 30

在大多数 unix 系统上,您可以使用GDB

gdb -batch -ex bt -p 1234
Run Code Online (Sandbox Code Playgroud)

还有pstack(不是标准实用程序,您可能必须手动安装)。它看起来相当于 AIX 的procstack. 但是在我的 Debian wheezy amd64 上,它似乎总是出错。在 i386 上,对于没有调试符号编译的程序,它不打印任何符号,甚至不打印调试符号可用的库中的任何符号。

您还可以使用strace -p1234来查看进程执行的系统调用。

  • [pstack 的 README](http://code.lm7.fr/p/pstack/source/tree/master/README) 确实说它仅适用于 32 位、ELF、x86、GNU。 (2认同)

Mik*_*nen 7

你想要eu-stackelfutils. 例如,

$ sudo eu-stack -id -p $$
PID 9189 - process
TID 9189:
#0  0x00007fd36c69e687 __GI___waitpid
#1  0x000055ba004c0c19
#2  0x000055ba004c234b wait_for
#3  0x000055ba004b1b64 execute_command_internal
#4  0x000055ba004b1bf2 execute_command
#5  0x000055ba0049c274 reader_loop
#6  0x000055ba0049ac7f main
#7  0x00007fd36c5dbb97 __libc_start_main
#8  0x000055ba0049b54a _start
Run Code Online (Sandbox Code Playgroud)

人们可以为更复杂的事情写一句俏皮话。例如,要列出 Google Chrome 的所有线程堆栈(正在运行多个进程和线程!),可以这样做

sudo true
pidof chrome | sudo xargs -rn1 timeout 1s eu-stack -id -p
Run Code Online (Sandbox Code Playgroud)

用于timeout防止进程在不间断睡眠中停止(一些较新的内核版本也可能允许获取这些进程的堆栈)。如果您愿意等待更长的时间来获取堆栈,请将超时设置得更长。

如果您有一个繁忙的系统,其中只有部分线程或进程被锁定,则可以像这样拍摄当前进程状态的快照

sudo true
pidof apache2 | sort -n | sudo xargs -rn1 timeout 1s eu-stack -id -p > snap1
sleep 10s
pidof apache2 | sort -n | sudo xargs -rn1 timeout 1s eu-stack -id -p > snap2
diff -u100 --color snap1 snap2
Run Code Online (Sandbox Code Playgroud)

您可以识别在 10 秒内未更改的堆栈(sort需要使堆栈顺序稳定,以便您可以有意义地比较输出)。如果您收到诸如以下错误

eu-stack: dwfl_linux_proc_report pid 25062: No such file or directory
eu-stack: dwfl_linux_proc_report pid 25068: Exec format error
Run Code Online (Sandbox Code Playgroud)

这只是意味着进程 25062 在pidof列出它之后但在eu-stack查询其状态之前退出,并且进程 25068 在构建堆栈跟踪的同时正在拆除,因此在读取通过proc文件系统指向的可执行文件时堆栈构建失败。