strace应该如何使用?


273

一位同事曾经告诉我,在Linux上一切都无法调试时,最后的选择是使用strace

我试图学习这种奇怪工具背后的科学知识,但是我不是系统管理员,我并没有真正获得结果。

所以,

  • 到底是什么,它做什么?
  • 应该如何使用?在哪种情况下应使用?
  • 应该如何理解和处理输出?

总之,在简单的话,怎么做这个东西的工作?


2
strace -p <pid>会告诉您程序当前正在发生什么.....比GDB更快更容易
ernesto 2014年

1
我个人觉得man strace真的很容易阅读和有用。(PS昨天之前还不了解strace,而且不是Linux专家)
Alexander Malakhov 2014年

1
“ strace是系统调用跟踪程序” –它仅显示您由于程序而正在调用哪些内核函数(及其参数)。
Pithikos

Answers:


184

Strace概述
strace可以看作是轻量级的调试器。它允许程序员/用户快速找出程序如何与OS交互。它通过监视系统调用和信号来做到这一点。


当您没有源代码或不想为真正的源代码而烦恼时,可以使用 Good。
另外,如果您不想打开GDB,而只是对了解外部交互感兴趣,则对您自己的代码很有用。


几天我对strace进行了介绍,这是一个很好的小介绍strace hello world


那么,如果您在strace监视的层下面使用某些东西,该怎么办?
Pacerier,2014年

在那种情况下,@ Pacerier检查ltrace stackoverflow.com/a/52012215/5884955
prosti

这对于调试仅存在/主要用于进行有趣的系统调用的低级程序或调试系统调用的新选项以查看操作系统的功能非常有用。基本上省去了为一次性实验编写日志记录/错误检查代码的麻烦。(或者,如果您正在用asm编写程序,或者很可能不小心传递了错误的args甚至是电话号码。)strace比GDB快得多,因为它为您查找errno代码,例如-EFAULT(哎呀,只读)缓冲区)或-ENOENT(哎呀,从相对路径不起作用的错误目录中运行。)
Peter Cordes

62

简而言之,strace跟踪程序发出的所有系统调用及其返回代码。考虑一下诸如文件/套接字操作之类的事情,以及更多晦涩难懂的事情。

如果您对C有一定的了解,这将非常有用,因为此处的系统调用将更准确地代表标准C库调用。

假设您的程序是/ usr / local / bin / cough。只需使用:

strace /usr/local/bin/cough <any required argument for cough here>

要么

strace -o <out_file> /usr/local/bin/cough <any required argument for cough here>

写入“ out_file”。

所有strace输出都将发送到stderr(请注意,其庞大的体积通常要求重定向到文件)。在最简单的情况下,您的程序将因错误中止,您将能够在strace输出中查看其与操作系统的最后交互作用。

更多信息应与:

man strace

36

strace列出了由其应用到的进程完成的所有系统调用。如果您不知道系统调用的含义,那么您将无法从中获得很多收益。

但是,如果您的问题涉及文件,路径或环境值,则在有问题的程序上运行strace并将输出重定向到文件,然后将该文件grep为path / file / env字符串,可能会帮助您了解程序实际上在尝试执行什么操作与您的预期有所不同。


7
对于非平凡的程序,这通常就像从消防水带中喝水,因此您需要为完成结果而
烦恼

17
strace <prog_name>跟踪程序。strace -o <out_file> <prog_name>到了放一个文件
JESTIN悦城

8
strace编2>&1 | grep ^ open \(
eisbaw 2011年

10
或者只是:strace -e open myprogOR对于所有与文件相关的系统调用:strace -e file myprog
Amit Naidu

17

Strace作为调查生产系统的工具而出类拔萃,您无法在调试器中运行这些程序。特别是,我们在以下两种情况下使用了strace:

  • 程序foo似乎处于死锁状态,并且没有响应。这可能是gdb的目标;但是,我们并不总是拥有源代码,或者有时我们所处理的脚本语言并非在调试器下直接运行。在这种情况下,您可以在已经运行的程序上运行strace,然后将获得正在进行的系统调用的列表。如果您要研究客户端/服务器应用程序或与数据库交互的应用程序,则此功能特别有用
  • 调查程序运行缓慢的原因。特别是,我们刚刚移至新的分布式文件系统,并且该系统的新吞吐量非常慢。您可以使用-T选项指定strace,该选项将告诉您每个系统调用花费了多少时间。这有助于确定文件系统导致速度变慢的原因。

有关使用strace分析的示例,请参阅我对这个问题的回答


15

我一直使用strace调试权限问题。该技术是这样的:

$ strace -e trace=open,stat,read,write gnome-calculator

gnome-calculator您要在哪里运行命令。


8

strace -tfp PID将监视PID进程的系统调用,因此我们可以调试/监视我们的进程/程序状态。


6

Strace可用作调试工具或原始分析器。

作为调试器,您可以查看给定系统调用的调用,执行方式以及返回的内容。这非常重要,因为它不仅使您可以看到程序失败,而且可以看到为什么程序失败。通常,这只是糟糕的编码导致无法捕获程序所有可能结果的结果。其他时候,它只是文件的硬编码路径。没有痕迹,您就可以猜测出哪里出问题以及怎么出问题了。使用strace可以得到系统调用的详细信息,通常仅查看返回值即可了解很多内容。

分析是另一种用途。您可以使用它来设置每个系统调用的执行时间,也可以作为一个整体。尽管这可能不足以解决您的问题,但至少会大大缩小潜在犯罪嫌疑人的范围。如果在单个文件上看到很多fopen / close对,则可能不必要在每次循环执行时打开和关闭文件,而不是在循环外部打开和关闭文件。

Ltrace是strace的近亲,也非常有用。您必须学会区分瓶颈所在。如果总执行时间为8秒,而您在系统调用上仅花费了0.05秒,那么跟踪程序并不能为您带来很多好处,问题出在您的代码中,这通常是逻辑问题,或者程序实际上需要花那么长时间才能运行。

strace / ltrace的最大问题是读取其输出。如果您不知道如何进行调用,或者至少不知道syscalls / functions的名称,那么将很难理解其含义。知道函数返回什么也将非常有益,特别是对于不同的错误代码。尽管很难破解,但有时它们确实会返回知识的明珠。一旦看到一种情况,我的索引节点用完了,但没有可用空间不足,因此所有常用的公用程序都没有给我任何警告,我只是无法制作一个新文件。从strace的输出中读取错误代码将我指向正确的方向。


4

Strace是一种工具,可以告诉您应用程序如何与操作系统交互。

它通过告诉您什么OS系统调用您的应用程序使用以及使用什么参数来实现此目的。

因此,例如,您看到了程序尝试打开的文件,并且成功进行了调用。

您可以使用此工具调试各种问题。例如,如果应用程序说它找不到您知道已安装的库,则strace会告诉您应用程序在哪里寻找该文件。

那只是冰山一角。


这是非常精确的。
prosti

4

strace是学习程序如何进行各种系统调用(对内核的请求)以及报告失败的程序以及与该失败相关的错误值的好工具。并非所有故障都是错误。例如,尝试搜索文件的代码可能会收到ENOENT(没有这样的文件或目录)错误,但是在代码逻辑上可能是可以接受的情况。

使用strace的一个好用例是在临时文件创建期间调试竞争条件。例如,可能通过将进程ID(PID)附加到某些预定字符串来创建文件的程序在多线程方案中可能会遇到问题。[使用PID + TID(进程ID +线程ID)或更好的系统调用(例如mkstemp)可以解决此问题]。

这对于调试崩溃也很有用。您可能会发现有关strace和调试崩溃的这篇(我的)文章很有用。


4

最小的可运行示例

如果概念不清楚,那么您可能还没有看到一个更简单的示例来解释它。

在这种情况下,该示例是独立的Linux x86_64程序集(无libc)的hello世界:

你好

.text
.global _start
_start:
    /* write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    mov $msg, %rsi  /* buffer */
    mov $len, %rdx  /* buffer len */
    syscall

    /* exit */
    mov $60, %rax   /* exit status */
    mov $0, %rdi    /* syscall number */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

GitHub上游

组装并运行:

as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out

输出预期:

hello

现在,在该示例上使用strace:

env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log

我们用:

strace.log 现在包含:

execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6)                  = 6
exit(0)                                 = ?
+++ exited with 0 +++

通过这样一个最小的示例,输出的每个字符都是不言而喻的:

  • execve行:显示如何strace执行hello.out,包括CLI参数和环境,如记录man execve

  • writeline:显示我们进行的写入系统调用。6是字符串的长度"hello\n"

    = 6是系统调用的返回值,如记录中man 2 write所述,它是写入的字节数。

  • exitline:显示我们进行的退出系统调用。由于程序已退出,因此没有返回值!

更复杂的例子

strace的应用程序当然是要查看复杂程序实际上在执行哪些系统调用来帮助调试/优化程序。

值得注意的是,您在Linux中可能会遇到的大多数系统调用都带有glibc包装器,其中许多来自POSIX

在内部,glibc包装器或多或少使用内联汇编,如下所示:如何通过内联汇编中的sysenter调用系统调用?

您应该研究的下一个示例是POSIX writehello world:

main.c

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *msg = "hello\n";
    write(1, msg, 6);
    return 0;
}

编译并运行:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

这次,您将看到glibc在main为main设置一个不错的环境之前正在进行大量系统调用。

这是因为我们现在不使用独立程序,而是使用更通用的glibc程序,该程序允许libc功能。

然后,在每一端strace.log包含:

write(1, "hello\n", 6)                  = 6
exit_group(0)                           = ?
+++ exited with 0 +++

因此,我们得出的结论是,writePOSIX函数使用Linux write系统调用令人惊讶!

我们还观察到return 0导致exit_group呼叫而不是exit。哈,我不知道这件事!这就是为什么strace这么酷。man exit_group然后说明:

此系统调用等效于exit(2),不同之处在于它不仅终止调用线程,而且终止调用进程的线程组中的所有线程。

这是我研究哪个系统调用dlopen使用的另一个示例:https : //unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710

在Ubuntu 16.04,GCC 6.4.0,Linux内核4.4.0中进行了测试。


2

这是一些我如何使用strace深入网站的示例。希望这会有所帮助。

像这样检查到第一个字节的时间:

time php index.php > timeTrace.txt

看看有多少百分比的动作在做什么。大量的lstatfstat可能是一个迹象,是时候清除缓存:

strace -s 200 -c php index.php > traceLstat.txt

输出a,trace.txt这样您就可以准确看到正在进行的调用。

strace -Tt -o Fulltrace.txt php index.php

用这个来检查是否任何带之间.1.9第二负载的:

cat Fulltrace.txt | grep "[<]0.[1-9]" > traceSlowest.txt

查看丢失了哪些文件或目录strace。这将输出很多涉及我们系统的内容-唯一相关的部分涉及客户的文件:

strace -vv php index.php 2>&1 | sed -n '/= -1/p' > traceFailures.txt

1

我喜欢其中的一些答案,这些答案可以strace检查您如何与操作系统进行交互。

这正是我们所看到的。系统调用。如果比较straceltrace则差异更加明显。

$>strace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         7           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        11           close
  0.00    0.000000           0        10           fstat
  0.00    0.000000           0        17           mmap
  0.00    0.000000           0        12           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         8         8 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         9           openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    93        10 total

另一方面,它ltrace具有跟踪功能。

$>ltrace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 15.52    0.004946         329        15 memcpy
 13.34    0.004249          94        45 __ctype_get_mb_cur_max
 12.87    0.004099        2049         2 fclose
 12.12    0.003861          83        46 strlen
 10.96    0.003491         109        32 __errno_location
 10.37    0.003303         117        28 readdir
  8.41    0.002679         133        20 strcoll
  5.62    0.001791         111        16 __overflow
  3.24    0.001032         114         9 fwrite_unlocked
  1.26    0.000400         100         4 __freading
  1.17    0.000372          41         9 getenv
  0.70    0.000222         111         2 fflush
  0.67    0.000214         107         2 __fpending
  0.64    0.000203         101         2 fileno
  0.62    0.000196         196         1 closedir
  0.43    0.000138         138         1 setlocale
  0.36    0.000114         114         1 _setjmp
  0.31    0.000098          98         1 realloc
  0.25    0.000080          80         1 bindtextdomain
  0.21    0.000068          68         1 opendir
  0.19    0.000062          62         1 strrchr
  0.18    0.000056          56         1 isatty
  0.16    0.000051          51         1 ioctl
  0.15    0.000047          47         1 getopt_long
  0.14    0.000045          45         1 textdomain
  0.13    0.000042          42         1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00    0.031859                   244 total

尽管我多次检查了手册,但我没有找到名称的由来,strace但很可能是系统调用跟踪,因为这很明显。

有3个较大的注释要说strace

注意1:这两个函数straceltrace都在使用系统调用ptrace。因此,ptrace系统调用实际上是有效的strace

ptrace()系统调用提供了一种方法,一个进程(“跟踪程序”)可以通过它观察并控制另一进程(“跟踪”)的执行,并检查和更改该跟踪程序的内存和寄存器。它主要用于实现断点调试和系统调用跟踪。

注意2:可以使用多个不同的参数strace,因为strace它们可能很冗长。我喜欢尝试一下-c,就像总结一下。根据-c您可以选择一个系统调用,例如-e trace=open您将只能看到该调用。如果要检查在跟踪命令期间将打开哪些文件,这可能会很有趣。当然,您可以将grep用作相同的目的,但请注意,您需要像这样2>&1 | grep etc进行重定向,以了解在发出命令时引用了配置文件。

注3:我发现这个非常重要的注解。您不限于特定的体系结构。strace会让您大吃一惊,因为它可以跟踪不同体系结构的二进制文件。 在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.