史上最强strace命令详解

strace是一个强大的Linux工具,用于跟踪进程的系统调用和信号。它利用ptrace实现,帮助运维人员在故障排查和性能分析中定位问题。通过strace,可以观察进程异常退出、共享内存异常等,配合不同参数如-c、-f、-p等进行详细监控。虽然strace在某些情况下可能无法捕捉用户态卡死,但它仍然是系统调用分析的得力助手。
摘要由CSDN通过智能技术生成

系列文章目录



前言


一、strace是什么?

按照 strace 官网的描述,strace 是一个可用于诊断、调试和教学的 Linux 用户空间跟踪器。我们用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。

strace 底层使用内核的ptrace 特性来实现其功能。

在运维的日常工作中,故障处理和问题诊断是个主要的内容,也是必备的技能。strace 作为一种动态跟踪工具,能够帮助运维高效地定位进程和服务故障。它像是一个侦探,通过系统调用的蛛丝马迹,告诉你异常的真相。

strace最简单的用法是执行一个指定的命令(过程中,starce会记录和解析命令进程的所有系统调用及这个进程的所有的信号值),在指定命令结束后立即退出。

strace问题定位案例
1、定位进程异常退出
2、定位共享内存异常
3、性能分析

strace 常用参数:
-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-a column
设置返回值的输出位置.默认 为40.
-e expr

二、strace怎么用

strace 有两种运行模式。
1、一种是通过它启动要跟踪的进程。用法很简单,在原本的命令前加上 strace 即可。

strace ./tt tt.conf

结果如下:

[root@MiWiFi-R3-srv performance]# strace ./tt tt.conf
execve("./tt", ["./tt", "tt.conf"], 0x7fff4cab6ee8 /* 41 vars */) = 0
brk(NULL)                               = 0x141d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0b0009000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/tls/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/tls/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/tls/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/tls", {st_mode=S_IFDIR|0555, st_size=6, ...}) = 0
open("/opt/rh/devtoolset-8/root/usr/lib64/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64", {st_mode=S_IFDIR|0555, st_size=148, ...}) = 0
open("/opt/rh/devtoolset-8/root/usr/lib/tls/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/tls/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/tls/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/tls", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib", {st_mode=S_IFDIR|0555, st_size=17, ...}) = 0
open("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/tls/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/tls/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/tls/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/tls", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/dyninst/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib64/dyninst", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/dyninst/tls/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/dyninst/tls/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/dyninst/tls/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/dyninst/tls", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/dyninst/x86_64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/dyninst/x86_64", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/dyninst/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/opt/rh/devtoolset-8/root/usr/lib/dyninst", 0x7ffc3d3b97b0) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=90926, ...}) = 0
mmap(NULL, 90926, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb0afff2000
close(3)                                = 0
open("/lib64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\303\t\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=14965112, ...}) = 0
mmap(NULL, 4282752, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb0af9d3000
mprotect(0x7fb0afbd9000, 2093056, PROT_NONE) = 0
mmap(0x7fb0afdd8000, 57344, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x205000) = 0x7fb0afdd8000
mmap(0x7fb0afde6000, 10624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb0afde6000
close(3)                                = 0
open("/opt/rh/devtoolset-8/root/usr/lib64/tls/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0PS\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1136944, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0afff1000
mmap(NULL, 3150136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb0af6d1000
mprotect(0x7fb0af7d2000, 2093056, PROT_NONE) = 0
mmap(0x7fb0af9d1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x100000) = 0x7fb0af9d1000
close(3)                                = 0
open("/opt/rh/devtoolset-8/root/usr/lib64/tls/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib64/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320*\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=88720, ...}) = 0
mmap(NULL, 2184192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb0af4bb000
mprotect(0x7fb0af4d0000, 2093056, PROT_NONE) = 0
mmap(0x7fb0af6cf000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14000) = 0x7fb0af6cf000
close(3)                                = 0
open("/opt/rh/devtoolset-8/root/usr/lib64/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/opt/rh/devtoolset-8/root/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156272, ...}) = 0
mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb0af0ed000
mprotect(0x7fb0af2b1000, 2093056, PROT_NONE) = 0
mmap(0x7fb0af4b0000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7fb0af4b0000
mmap(0x7fb0af4b6000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb0af4b6000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0afff0000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0affee000
arch_prctl(ARCH_SET_FS, 0x7fb0affee740) = 0
mprotect(0x7fb0af4b0000, 16384, PROT_READ) = 0
mprotect(0x7fb0af6cf000, 4096, PROT_READ) = 0
mprotect(0x7fb0af9d1000, 4096, PROT_READ) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0affed000
mprotect(0x7fb0afdd8000, 45056, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7fb0b000a000, 4096, PROT_READ) = 0
munmap(0x7fb0afff2000, 90926)           = 0
brk(NULL)                               = 0x141d000
brk(0x144f000)                          = 0x144f000
fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 11), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0b0008000
read(0, 123
"123\n", 1024)                  = 4
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 11), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb0b0007000
write(1, "123\n", 4123
)                    = 4
exit_group(0)                           = ?
+++ exited with 0 +++

2、第二种运行模式,是跟踪已经在运行的进程,在不中断进程执行的情况下,理解它在干嘛。即给 strace 传递个 -p pid 选项即可。完成跟踪时,按 Ctrl + C 结束 strace 即可。

./tt tt.conf
strace -c -p $(pidof tt)

在这里插入图片描述
在这里插入图片描述

如定位问题:
strace ./tt 运行后,通过kill -9 $(pidof tt),打印如下,发现tt进程被kill掉了。
在这里插入图片描述


总结

当发现进程或服务异常时,我们可以通过 strace 来跟踪其系统调用,“看看它在干啥”,进而找到异常的原因。熟悉常用系统调用,能够更好地理解和使用strace。
当然,万能的 strace 也不是真正的万能。当目标进程卡死在用户态时,strace 就没有输出了。这个时候我们需要其他的跟踪手段,比如 gdb / perf / SystemTap 等。

参考:https://blog.csdn.net/itworld123/article/details/122961879

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c+猿辅导

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值