如何使用 strace?

2024-10-09 09:10:00
admin
原创
209
摘要:问题描述:一位同事曾经告诉我,在 Linux 上调试一切都失败时,最后的选择是使用strace。我试图了解这个奇怪工具背后的科学原理,但我不是系统管理专家,而且我并没有真正得到结果。所以,它到底是什么以及它有什么作用?应该如何使用以及在什么情况下使用?输出应该如何被理解和处理?简而言之,用简单的话说,这个东西...

问题描述:

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

我试图了解这个奇怪工具背后的科学原理,但我不是系统管理专家,而且我并没有真正得到结果。

所以,

  • 它到底是什么以及它有什么作用?

  • 应该如何使用以及在什么情况下使用?

  • 输出应该如何被理解和处理?

简而言之,用简单的话说,这个东西是如何工作的?


解决方案 1:

Strace 概述

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

用途

适用于您没有源代码或不想费心真正阅读源代码的情况。

此外,如果您不想打开 GDB,而只是想了解外部交互,那么这对您自己的代码也很有用。

一个很好的小介绍

下面是使用 strace 调试进程挂起的简单介绍:strace 介绍

解决方案 2:

简单来说,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

解决方案 3:

strace 列出了它所应用的进程执行的所有系统调用。如果你不知道系统调用是什么意思,那么你将无法从中获得太多信息。

尽管如此,如果您的问题涉及文件、路径或环境值,则在有问题的程序上运行 strace 并将输出重定向到文件,然后在该文件中 grep 您的路径/文件/环境字符串,这可能会帮助您了解您的程序实际上正在尝试做什么,与您预期的不同。

解决方案 4:

Strace 是一款出色的工具,可用于调查无法在调试器下运行这些程序的生产系统。具体来说,我们在以下两种情况下使用了 strace:

  • 程序 foo 似乎处于死锁状态,并且没有响应。这可能是 gdb 的目标;但是,我们并不总是有源代码,或者有时处理的脚本语言不能直接在调试器下运行。在这种情况下,您可以在已经运行的程序上运行 strace,您将获得正在进行的系统调用列表。如果您正在调查客户端/服务器应用程序或与数据库交互的应用程序,这尤其有用

  • 调查程序运行缓慢的原因。具体来说,我们刚刚迁移到一个新的分布式文件系统,而系统的新吞吐量非常慢。您可以使用“-T”选项指定 strace,它将告诉您每个系统调用花费了多少时间。这有助于确定文件系统导致程序运行缓慢的原因。

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

解决方案 5:

我经常使用 strace 来调试权限问题。技巧如下:

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

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

解决方案 6:

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

解决方案 7:

最小可运行示例

如果某个概念不清楚,可以有一个你没见过的更简单的例子来解释它。

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

你好.S

.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   /* syscall number */
    mov $0, %rdi    /* exit status */
    syscall
msg:
    .ascii "hello
"
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

我们使用:

  • env -i ASDF=qwer控制环境变量: https: //unix.stackexchange.com/questions/48994/how-to-run-a-program-in-a-clean-environment-in-bash

  • -s999 -v显示更完整的日志信息

strace.log现在包含:

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

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

  • execve行:显示如何strace执行hello.out,包括 CLI 参数和环境,如以下文档中所述man execve

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

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

  • exit行:显示我们执行的退出系统调用。没有返回值,因为程序已退出!

更复杂的例子

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

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

在内部,glibc 包装器使用内联汇编或多或少像这样:如何在内联汇编中通过 syscall 或 sysenter 调用系统调用?

您应该学习的下一个示例是 POSIX writehello world:

主程序

#define _XOPEN_SOURCE 700
#include <unistd.h>

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

编译并运行:

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

main这一次,您将看到 glibc在设置主程序的良好环境之前进行了一系列系统调用。

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

然后,在每个末端都strace.log包含:

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

因此我们得出结论:writePOSIX 函数使用了 Linuxwrite系统调用!令人惊讶的是。

我们还观察到 会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 中测试。

解决方案 8:

Strace 可以用作调试工具,也可以用作原始分析器。

作为调试器,您可以看到给定的系统调用是如何被调用、执行的以及它们返回什么。这非常重要,因为它不仅可以让您看到程序失败了,还可以看到程序失败的原因。通常,这只是糟糕的编码没有捕捉到程序的所有可能结果的结果。其他时候,它只是硬编码的文件路径。如果没有 strace,您可以猜测哪里出了问题以及如何出了问题。使用 strace,您可以了解系统调用的细分,通常只需查看返回值就可以知道很多信息。

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

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

strace/ltrace 最大的问题是读取它们的输出。如果你不知道调用是如何进行的,或者至少不知道系统调用/函数的名称,那么解读它们的含义将非常困难。了解函数返回的内容也非常有益,尤其是对于不同的错误代码。虽然解读起来很麻烦,但它们有时确实能带来宝贵的知识;有一次我看到一种情况,我用完了 inode,但没有用完可用空间,因此所有常用的实用程序都没有给我任何警告,我只是无法创建新文件。从 strace 的输出中读取错误代码为我指明了正确的方向。

解决方案 9:

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

它通过告诉您应用程序使用了哪些操作系统调用以及使用哪些参数来调用它们来实现这一点。

举例来说,您可以看到程序尝试打开哪些文件,以及调用是否成功。

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

而这还只是冰山一角。

解决方案 10:

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

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

它也适合调试崩溃。您可能会发现这篇关于 strace 和调试崩溃的文章很有用。

解决方案 11:

以下是我使用 strace 深入挖掘网站的一些示例。希望对您有所帮助。

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

time php index.php > timeTrace.txt

查看操作所占百分比。大量lstat操作fstat可能表示需要清除缓存了:

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

输出 atrace.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

解决方案 12:

我喜欢其中的一些答案,它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,但它很可能是系统调用跟踪,因为这是显而易见的。

有三点比较值得一提strace

注 1:这两个函数straceltrace都使用系统调用ptrace。因此ptrace系统调用实际上是这样strace工作的。

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

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

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用