strace命令使用

Easter79
• 阅读 833
命令介绍

strace是Linux环境下的一款程序调试工具,用来输出一个应用程序所使用的系统调用。

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

什么是系统调用?

系统调用是通向操作系统本身的接口,是面向底层硬件的。通过系统调用,可以使得用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互,是操作系统留给应用程序的一个接口。

常用选项

-t 在每行输出的前面显示时间(精确到秒)
-tt 在每行输出的前面显示时间(精确到毫秒)
-T 显示每次系统调用所花费的时间
-v 对于某些相关调用,显示详细信息(把完整的环境变量,文件stat结构等打出来)
-f 跟踪目标进程,以及目标进程创建的所有子进程
-e 指定要跟踪的系统调用
-o 把strace的输出写到文件中
-s 当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节
-p 指定要跟踪的进程pid, 要同时跟踪多个pid, 重复多次-p选项即可。
-c 统计每种系统调用所执行的时间,调用次数,出错次数。

使用

1.追踪打开文件的系统调用

[root@localhost ~]# strace cat /etc/hosts

execve("/usr/bin/cat", ["cat", "/etc/hosts"], 0x7fff79f5beb8 /* 26 vars */) = 0
brk(NULL)                               = 0x81e000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3cee950000
access("/etc/ld.so.preload", R_OK)      = -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=20640, ...}) = 0
mmap(NULL, 20640, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3cee94a000
close(3)                                = 0
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=2156240, ...}) = 0
mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f3cee362000
mprotect(0x7f3cee525000, 2097152, PROT_NONE) = 0
mmap(0x7f3cee725000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f3cee725000
mmap(0x7f3cee72b000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f3cee72b000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3cee949000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3cee947000
arch_prctl(ARCH_SET_FS, 0x7f3cee947740) = 0
mprotect(0x7f3cee725000, 16384, PROT_READ) = 0
mprotect(0x60b000, 4096, PROT_READ)     = 0
mprotect(0x7f3cee951000, 4096, PROT_READ) = 0
munmap(0x7f3cee94a000, 20640)           = 0
brk(NULL)                               = 0x81e000
brk(0x83f000)                           = 0x83f000
brk(NULL)                               = 0x83f000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106176928, ...}) = 0
mmap(NULL, 106176928, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3ce7e1f000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
open("/etc/hosts", O_RDONLY)            = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=158, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "127.0.0.1   localhost localhost."..., 65536) = 158
write(1, "127.0.0.1   localhost localhost."..., 158127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
) = 158
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

2.显示系统调用的时间

[root@localhost ~]# strace -tt  -T  cat /etc/hosts

11:25:50.561449 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000023>
11:25:50.561522 fstat(3, {st_mode=S_IFREG|0644, st_size=106176928, ...}) = 0 <0.000013>
11:25:50.561585 mmap(NULL, 106176928, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7ecb038000 <0.000018>
11:25:50.561649 close(3)                = 0 <0.000013>
11:25:50.561830 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 <0.000017>
11:25:50.561908 open("/etc/hosts", O_RDONLY) = 3 <0.000024>
11:25:50.561979 fstat(3, {st_mode=S_IFREG|0644, st_size=158, ...}) = 0 <0.000014>
11:25:50.562046 fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0 <0.000014>
11:25:50.562118 read(3, "127.0.0.1   localhost localhost."..., 65536) = 158 <0.000019>
11:25:50.562183 write(1, "127.0.0.1   localhost localhost."..., 158127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
) = 158 <0.000018>
11:25:50.562244 read(3, "", 65536)      = 0 <0.000014>
11:25:50.562304 close(3)                = 0 <0.000016>
11:25:50.562386 close(1)                = 0 <0.000013>
11:25:50.562443 close(2)                = 0 <0.000012>
# 时间戳                                # 花费的时间

3.跟踪特定系统调用

-e trace=file 文件相关的调用(参数中有文件名)
-e trace=process 进程管理相关的调用,比如fork/exec/exit_group
-e trace=network 网络通信相关的调用,比如socket/sendto/connect
-e trace=signal 信号相关的调用,比如kill/sigaction
-e trace=desc 和文件描述符相关,比如write/read/select/epoll等
-e trace=ipc 进程通信相关的调用,比如shmget等

# 跟踪文件访问相关系统调用
[root@localhost ~]# strace -e file  cat /etc/hosts
execve("/usr/bin/cat", ["cat", "/etc/hosts"], 0x7fff79c90c58 /* 26 vars */) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/hosts", O_RDONLY)            = 3

4.跟踪多线程(进程)应用的系统调用

下面是一个多线程demo代码。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

void* ThreadA(void* par)
{
    while(1)
     {
        printf("hello world\n");
        sleep(1);
     }
}

int main()
{
    pthread_t t1;
    pthread_create(&t1, NULL, ThreadA, NULL);
    pthread_join(t1, NULL);
    
    return 0;
}

编译代码

# gcc demo.c  -o demo -lpthread

开始跟踪

# strace -ff -o out ./demo

执行完成后得到两个文件(每个线程一个)

# ls out.*
out.7611  out.7612

主线程 out.7611

mprotect(0x7fa0e4b6e000, 16384, PROT_READ) = 0
mprotect(0x7fa0e4d8f000, 4096, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7fa0e4fb6000, 4096, PROT_READ) = 0
munmap(0x7fa0e4faf000, 20776)           = 0
set_tid_address(0x7fa0e4faca10)         = 7611
set_robust_list(0x7fa0e4faca20, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7fa0e4b7f860, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7fa0e4b88630}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7fa0e4b7f8f0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7fa0e4b88630}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fa0e3faa000
brk(NULL)                               = 0x15c8000
brk(0x15e9000)                          = 0x15e9000
brk(NULL)                               = 0x15e9000
mprotect(0x7fa0e3faa000, 4096, PROT_NONE) = 0
clone(child_stack=0x7fa0e47a9fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fa0e47aa9d0, tls=0x7fa0e47aa700, child_tidptr=0x7fa0e47aa9d0) = 7612
futex(0x7fa0e47aa9d0, FUTEX_WAIT, 7612, NULL) = 0
exit_group(0)                           = ?
+++ exited with 0 +++

工作线程 out.7612

set_robust_list(0x7fa0e47aa9e0, 24)     = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa0e4fb4000
write(1, "hello world\n", 12)           = 12
madvise(0x7fa0e3faa000, 8368128, MADV_DONTNEED) = 0
exit(0)                                 = ?
+++ exited with 0 +++
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
2年前
strace命令
strace命令是一个集诊断、调试、统计与一体的工具,我们可以使用strace对应用的系统调用和信号传递的跟踪结果来对应用进行分析,以达到解决问题或者是了解应用工作过程的目的。当然strace与专业的调试工具比如说gdb(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fman.li
Stella981 Stella981
2年前
Linux下的strace命令介绍
简介strace常用来跟踪进程执行时的系统调用和所接收的信号。在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。输出参数含义
Wesley13 Wesley13
2年前
VirtualBox导入已安装好的操作系统的方法
VirtualBox导入已安装好的操作系统的方法1、修改UUID进入VirtualBox安装目录,运行VBoxManage修改UUID,命令运行如下:D:\\VirtualBoxVBoxManage.exe internalcommands setvdiuuid E:\\VirtualX
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
2年前
Linux神器strace的使用方法及实践
在Linux系统中,strace命令是一个集诊断、调试、统计与一体的工具,可用来追踪调试程序,能够与其他命令搭配使用,接下来就Linux系统调用工具strace的使用方法和实践给大家做个详细介绍,一起来了解下strace的操作实例吧。【场景】1、在操作系统运维中会出现程序或系统命令运行失败,通过报错和日志无法定位问题根因。
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
7个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k