如何在Linux上使用strace追踪进程的系统调用?

有时候,我们需要检查运行中的应用程序在底层做了什么,以及在执行过程中执行了什么系统调用是很有用的。要在Linux上完成这样的任务,我们可以使用strace实用程序。在本文中,我们将了解如何安装它,并了解它的基本用法。
在本文中,您将了解到:
①如何安装strace
②如何使用 strace 追踪进程的系统调用?
③如何过滤具体的系统调用
④如何附加到一个已经运行的进程
⑤如何生成系统调用摘要
一、安装strace
虽然默认情况下没有安装,但是strace实用程序可以在所有主要Linux发行版的官方存储库中使用,我们可以通过使用最喜欢的包管理器非常容易的安装它。
如果我们运行在Fedora(或红帽家族的任何其他发行版)上,我们必须使用dnf:
$ sudo dnf install strace
如果我们更习惯使用Debian或基于Debian的发行版(例如Ubuntu或Linux Mint),则可以使用apt来获得相同的结果:
$ sudo apt install strace
如果使用的是Arch Linu,我们可以使用pacman来安装应用程序,这是在提供额外的存储库:
$ sudo pacman -S strace
安装软件后,我们可以继续进行操作,并查看其用法示例。
二、strace介绍
就像我们已经说过的那样,strace是一种工具,用于跟踪正在运行的进程进行的系统调用以及该进程接收到的信号。系统调用是应用程序和Linux内核之间的基本接口。当我们使用strace时,进程进行的调用的名称以及它们的参数和返回值将显示在stderr(标准错误文件描述符)上。
让我们看一下strace的基本用法,以便熟悉其输出。在其最基本的用法中,我们先将strace调用,然后再调用我们要执行的程序以及要分析其行为的程序。对于此示例,我们将仅使用cp命令复制文件:
$ strace cp ~/.bashrc bashrc
该命令的输出很长,当然这里我们不能详细分析它。我们只看第一行。strace输出的每一行都包含:
系统调用名称
括号中传递给系统调用的参数
系统调用返回值
我们可以在输出中看到的第一个系统调用是execve。该调用用于执行带有指定参数数组的程序。被接受的第一个参数execv是我们要执行的文件的路径;第二个是字符串数组,代表要传递给程序的参数(按照惯例,第一个参数是程序本身的名称)。
在我们的例子中,被调用的二进制文件是/usr/bin/cp,传递给该调用的参数数组是:程序名称(cp),源路径和目标路径:
execve("/usr/bin/cp", [“cp”, “/home/egdoc/.bashrc”, “bashrc”], 0x7fff53d4e4c0 /* 46 vars /) = 0
其中/
46 vars */符号表示从调用过程继承了46个变量(在execv函数中,环境是从外部environ变量获取的)。最后,我们有返回值是0(实际上exec,函数族仅在发生错误时才返回值)。
1、仅过滤特定的系统调用
在使用strace时,有时我们可能只想跟踪进程进行的特定系统调用。在这种情况下,我们可以使用-e选项后跟一个表达式,该表达式指示应跟踪的系统调用。假设我们运行与上一个示例相同的命令,但是我们只希望read系统调用显示在输出中,我们将运行:
$ strace -e read cp ~/.bashrc bashrc
顺便说一句,该read系统调用有三个参数:第一个是一个 文件描述符与应读的文件相关联; 第二个是应读取文件的缓冲区,第三个 是应读取的字节数。成功后,该函数将返回从文件读取的字节数,正如我们在上面的输出中可以看到的那样。
2、在正在运行的进程上附加strace
到现在为止,我们调用strace传递给它要执行的命令并保持跟踪;如果我们要跟踪现有的并且已经在运行的流程该怎么办?在这种情况下,我们必须使用(或)选项调用strace,并传递要附加到其上的进程的PID(进程ID)。-p–attach
要找到程序的PID,在其他解决方案中,我们可以使用pidof 实用程序。为了这个示例,我们将strace附加到正在运行的gnome-terminal-server实例:
$ pidof gnome-terminal-server
121316
返回的pidof命令121316是gnome-terminal-server的PID。知道了这一点,我们可以将strace附加到流程中:
$ strace -p 121316
“ strace -p 121316”命令的输出
上面的输出将在执行系统调用时“即时”更新。要“分离” 曲线,我们只需按Ctrl+C一下键盘即可。我们将收到有关“分离”的通知,但是跟踪的过程将继续运行:
strace: Process 121316 detached
3、追踪信号
通过strace,我们还可以观察到进程何时接收到信号,以及它如何对信号做出反应。演示一下,首先,我们作为top启动一个长期运行的进程,它是一个进程监视器:
$ top
然后,在获得其PID后,我们将strace附加到它,在这种情况下为 44825:
$ strace -p 44825
此时,strace开始跟踪top发出的系统调用,以及它接收到的信号。为了证明这一点,我们将SIGTERM发送给PID 44825:
$ kill 44825
如预期的那样,该事件在strace输出中报告:
— SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=44888, si_uid=1000} —
在上面的输出中,si_signo是要传送的信号数(SIGTERM = 15), si_code包含标识信号原因的代码(SI_USER = 0):在这种情况下,信号是由用户进程生成的。的si_pid和si_uid 字段报告,分别PID发送进程的和其UID。
4、将strace的输出保存到文件中
如果在启动strace时使用-o选项(的缩写–ouput),则可以将其输出重定向到文件,并通过路径作为参数,例如:
$ strace -p 121316 -o strace_output
strace: Process 121316 attached
该strace_output文件将被创建和输出strace的会里面写。要观看文件中的更新,我们可以使用tail:通常,此命令读取文件的最后10行并退出,但是如果我们使用-f选项(short --follow)进行调用,则可以观察到附加了新内容:
$ tail -f strace_output
5、打印系统调用摘要
该strace的工具配备了一个非常有用的功能:产生一个指定的进程的所有系统调用的总结的能力。如果要生成这样的报告,我们要做的就是使用-c或–summary-only选项调用程序 。让我们以以前使用的cp命令为例:
$ strace -c cp ~/.bashrc bashrc
上面的命令将生成此报告:
如何在Linux上使用strace追踪进程的系统调用?
由于我们生成了摘要,因此 不会显示strace的正常输出。如果我们要生成摘要但仍获得程序的常规输出,则必须使用-C选项,即summary。
在本文中,我们学习了如何安装和使用strace,这是一个很好的实用程序,可用于调试目的,并且更广泛地用于跟踪进程执行的系统调用。我们看到了strace的输出是如何组织的,如何启动程序并跟踪它所进行的系统调用,如何将strace附加 到已经运行的进程以及如何通知进程接收到的信号。最后,我们看到了如何生成流程所有调用的摘要。
A5互联https://www.a5idc.net/