使用 strace 命令了解 Linux 系统调用

系统
桌面上运行的每个进程都使用系统调用与操作系统通信。 使用 strace,您可以轻松跟踪此类系统调用。

桌面上运行的每个进程都使用系统调用与操作系统通信。 使用 strace,您可以轻松跟踪此类系统调用。

当在 Linux 上运行的程序想要使用操作系统管理的资源(读取文件、创建进程等)时,它们会对操作系统进行系统调用。 系统调用在内核级别工作并执行必要的操作,将控制权留回调用程序。strace 工具提供了在 Linux 上跟踪这些系统调用的功能。

strace 命令的典型用法

要监视应用程序的系统调用,只需使用以下格式使用 strace 调用命令:

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ strace ls /tmp

但是,通常有些进程开始得更早,并继续在后台工作。由于任何问题,您可能希望收集与此类进程关联的其他信息。通过将进程的进程 ID 提供给 -p 参数,可以将 strace 附加到任何正在运行的应用程序:

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ strace -p 5007

输出:

跟踪应用程序的线程和分支

使用 strace,您可以使用 -f 标志检查作为应用程序分支的所有线程和其他子进程。

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ strace -f -p 5007

输出:

使用 strace 检查某些系统调用

默认的 strace 输出有时可能非常拥挤。如果只想跟踪某些系统调用,可以使用 -e 参数执行此操作:

strace -f -e trace=open,write,close,connect,select -p 26757

要仅跟踪与文件操作相关的系统调用,请使用 -e trace=file:

strace -e trace=file -p 26757

要仅过滤与网络相关的系统调用,请在命令中指定 -e trace=network:

strace -e trace=network -p 26757

以微秒为单位获取精确时间信息

输出系统调用时,可以使用 -t 参数获取以秒为单位的精确时间信息。大多数情况下,精度不足以满足您的需求。在这种情况下,可以使用 -tt 参数以微秒精度获取时间信息:

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ strace -tt ls /tmp

收集有关系统调用的统计信息

使用 -c 参数,您可以根据需要收集有关系统调用的统计信息:

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ strace -f -c -p 26757

将日志保存到文件

如果长时间运行 strace,并希望稍后更详细地检查生成的日志,则需要保存日志。使用 -o 参数,您可以指定 strace 应在其中保存日志的文件:

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ strace -f -o /tmp/strace.log -e trace=file ls /tmp

跟踪阻塞过程

使用 prctl 系统调用,Linux下的任何应用程序都可以防止自己被使用 ptrace 的非 root 用户控制。如果应用程序通过 prctl 为自己清除 PR_SET_DUMPABLE 标志,则 root 以外的用户将无法使用 ptrace 控制此应用程序,即使他们有权向应用程序发出信号。

此功能最典型的用途之一是在 OpenSSH 身份验证代理软件中看到的。因此,在用户身份验证时,可以防止另一个应用程序使用 ptrace 控制应用程序。

跟踪和安全

由于在传统的 Linux 进程模型中设置了 ptrace 工具,因此您与用户一起在系统上运行的任何软件都有权在其中插入恶意代码。从最简单的 xterm 工具到高级 Web 浏览器应用程序,此类恶意软件可以控制所有其他正在运行的应用程序(这要归功于 ptrace 系统调用),并在您不知不觉中复制重要信息。

为了应对许多用户不知道的这种情况,已经使用Linux内核中名为Yama的安全模块开发了一种保护机制。

您可以通过 /proc/sys/kernel/yama/ptrace_scope 文件控制对 ptrace 系统调用的响应。默认情况下,此文件写入的值为 0。

以下值是可以接受的:


含义

0

常规行为:可以检查所有有权跟踪的应用程序。

1

受限跟踪:只有应用程序的直接父级或具有 PR_SET_PTRACER 选项的应用程序允许的调试应用程序才具有控制权。因此,gdb program_name 和 strace program_name 的使用将继续有效,但之后您将无法附加正在运行的应用程序。

2

跟踪到系统管理员:只能控制具有已定义CAP_SYS_PTRACE属性的应用程序或使用 prctl 定义PTRACE_TRACEME选项的子进程。

3

完全禁用:在任何情况下都不允许跟踪。如果此属性定义一次,则无法在运行时再次更改它。

许多开发人员不知道应用程序可以通过 prctl 禁用 ptrace,除了 root 用户。尽管与安全相关的软件(如 OpenSSH 代理)执行这些操作,但期望系统上运行的所有软件都具有相同的行为是不对的。

最近,一些 Linux 发行版开始将上述 ptrace_scope 文件的默认值设置为 1。因此,在限制 ptrace 操作的情况下,整个系统提供了更安全的工作环境。

使用示例跟踪

使用名称 ministrace.c 注册下面的示例应用程序。然后你可以用以下命令编译它:

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ gcc -o ministrace ministrace.c

┌──(linuxmi㉿linuxmi)-[~/www.linuxmi.com]
└─$ ./ministrace date

代码:

#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int wait_for_syscall (pid_t child)
{
int status;
while (1) {
ptrace(PTRACE_SYSCALL, child, 0, 0);
waitpid(child, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80)
return 0;
if (WIFEXITED(status))
return 1;
}
}

int do_child (int argc, char **argv)
{
char *args [argc+1];
memcpy(args, argv, argc * sizeof(char*));
args[argc] = NULL;
ptrace(PTRACE_TRACEME);
kill(getpid(), SIGSTOP);
return execvp(args[0], args);
}

int do_trace (pid_t child)
{
int status, syscall, retval;
waitpid(child, &status, 0);
ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD);
while(1) {
if (wait_for_syscall(child) != 0) break;

syscall = ptrace(PTRACE_PEEKUSER, child, sizeof(long)*ORIG_RAX);
fprintf(stderr, "syscall(%d) = ", syscall);

if (wait_for_syscall(child) != 0) break;

retval = ptrace(PTRACE_PEEKUSER, child, sizeof(long)*RAX);
fprintf(stderr, "%d\n", retval);
}
return 0;
}

int main (int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s prog args\n", argv[0]);
exit(1);
}
pid_t child = fork();
if (child == 0) {
return do_child(argc-1, argv+1);
} else {
return do_trace(child);
}
}

编译应用程序后,您可以使用 ministrace 运行任何命令并检查输出:

您可以将 strace 用于多种目的

Strace 可以帮助查找不必要地使用系统资源的程序中的错误。同样,程序在使用操作系统资源时表现出的特征也可以通过 strace 显示出来。

由于 strace 直接侦听系统调用,因此无论正在运行的程序的代码是打开还是关闭,它都可以揭示运行时动态。可以了解为什么程序在使用 strace 启动时会抛出错误。

同样,strace 可帮助您了解程序意外终止的原因。因此,熟悉 strace 在 Linux 内核开发和系统管理中非常重要。

责任编辑:赵宁宁 来源: Linux迷
相关推荐

2019-11-07 15:02:00

Linuxstrace系统调用

2009-12-25 10:52:50

Linux监管命令

2023-12-27 14:08:00

LinuxTop命令工具

2010-01-07 13:59:11

Linux入门命令

2010-01-07 13:53:43

Linux入门

2020-01-03 14:16:20

Windows软件编程语言

2015-09-21 11:28:57

使用Linux系统

2018-08-23 10:18:02

PtraceLinux系统调用

2010-03-03 09:43:34

Linux软件包

2009-12-23 17:50:07

Linux网络命令

2011-03-04 10:04:31

Linux文件操作命令

2009-03-10 19:19:16

Linux日志文件系统安装使用

2010-12-22 10:26:41

straceLinux服务器

2019-09-29 16:42:35

straceEmacsLinux

2009-08-03 12:02:13

linux at命令linux at命令详使用案例

2010-06-24 11:05:41

Linux cal

2009-12-24 17:12:30

2017-12-19 11:00:54

Linux系统日志

2021-09-26 15:00:18

Linux命令行工具NVMe驱动器

2019-10-23 11:24:44

LinuxLinux目录Linux系统
点赞
收藏

51CTO技术栈公众号