当前位置: 首页 > Linux, shell > 正文

About strace

作为软件的使用者而非开发者,平时会遇到很多奇怪的问题

这个程序为什么不动呢,它是不是僵死了?它为什么没有按照预想的方式工作?

时至今日,应用程序已经完全和硬件隔离,具体的操作(文件读写,网络访问等)都要使用 syscalls(系统调用)来完成

如果可以跟踪程序使用的syscall,就意味着几乎知道了程序的所有动作,比如

    open -> read/write						读写文件
    socket -> connect -> read -> write		                访问网络
    fork -> execve						衍生子进程
    wait, kill, pipe						控制子进程
    clock_gettime						获知系统时间

这时,我们可以寻求系统自带的调试利器 strace 的帮助

    strace	跟踪process系统调用或者信号产生的情况
    ltrace	跟踪process调用库函数的情况

strace和ltrace的使用方式差不多,只是跟踪的范围不一样

0. 基本使用

    strace command args

直接使用strace调用具体的程序,会显示程序运行过程中的所有syscall

1. 看看程序正在干什么

    strace -p pid

除了基本的使用方式,strace还可以在线调试运行中的程序

这时,就能够很容易的知道为啥这个程序会不动呢? 它是在等待别的资源,还是在勤劳的干活?

2. 看看程序在启动的时候打开了什么文件

    [root@h4-61 tmp]# strace -e read,access ping -c 1 8.8.8.8 > /dev/null
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0) = 832
    read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0) = 832

strace默认会显示所有的系统调用,有时。我们可能只关心少量的syscall,可以使用 -e 参数来实现

多个syscall使用逗号(,)分割;甚至,可以使用 read=3 来查看使用 3 这个描述符的 read 调用

3. 显示syscall的时间戳

    [root@h4-61 tmp]# strace -tt -e read,access ping -c 1 8.8.8.8 > /dev/null
    17:59:05.205188 access("/etc/ld.) = -1 ENOENT (No such file or directory)
    17:59:05.205660 read(3, "\177ELF\2\1\) = 832
    17:59:05.205972 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0) = 832

有时需要知道syscall发生的时间,可以使用 -t 参数:

-t 表示秒

-tt 表示毫秒

-T 显示每个系统调用从开始到结束使用的时间

4. 控制syscall显示信息的程度

    [root@h4-61 tmp]# strace -tt -e read,access -s 10 ping -c 1 8.8.8.8 > /dev/null
    17:59:42.831239 access("/etc/ld.) = -1 ENOENT (No such file or directory)
    17:59:42.831660 read(3, "\177ELF\2\1\1\0\0\0"..., 832) = 832
    17:59:42.831967 read(3, "\177ELF\2\1\1\3\0\0"..., 832) = 832

默认情况下,strace对于每个系统调用只显示32个字符的信息,使用 -s 数字可以改变默认行为

-s 0 表示显示所有的信息

5. 分类查看syscall

除了使用 -e syscallname 查看具体的syscall,我们还可以按照类别产看,如

trace=file

显示文件操作 open,stat,chmod,unlink,..

    [root@h4-61 tmp]# strace -e trace=file ping -c 1 8.8.8.8 > /dev/null
    execve("/bin/ping", ["ping", "-c", "1", "8.8.8.8"], [/* 26 vars */]) = 0
    access("/etc/ld.so.prel)      = -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    open("/lib64/libidn.so.11", O_RDONLY)   = 3
    open("/lib64/libc.so.6", O_RDONLY)      = 3
    open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

trace=process

显示进程操作 fork, wait, and exec

    [root@h4-61 tmp]# strace -e trace=process ping -c 1 8.8.8.8 > /dev/null
    execve("/bin/ping", ["ping", "-c", "1", "8.8) = 0
    arch_prctl(ARCH_SET_FS, 0x7fc9afee4700) = 0
    exit_group(0)  = ?

trace=network

网络操作相关的syscall

    [root@h4-61 tmp]# strace -e trace=network ping -c 1 8.8.8.8 > /dev/null
    socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
    socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
    省略号
    setsockopt(3, SOL_SOCKET, SO_SNDBUF, [324], 4) = 0
    setsockopt(3, SOL_SOCKET, SO_RCVBUF, [65536], 4) = 0
    getsockopt(3, SOL_SOCKET, SO_RCVBUF, [3427721778695372800], [4]) = 0
    setsockopt(3, SOL_SOCKET, SO_TIMESTAMP, [1], 4) = 0
    省略号

trace=signal

信号操作相关的syscall

    [root@h4-61 tmp]# strace -e trace=signal ping -c 1 8.8.8.8 > /dev/null
    rt_sigaction(SIGINT, {0x7f8f4d04da40, [], SA_RESTORER|SA_IN) = 0
    rt_sigaction(SIGALRM, {0x7f8f4d04da40, [], SA_RESTORER|SA_I) = 0
    rt_sigaction(SIGQUIT, {0x7f8f4d04da50, [], SA_RESTORER|SA_INT) = 0

trace=ipc

进程间通信相关的syscall

trace=desc

文件描述符相关的syscall

    [root@h4-61 tmp]# strace -e trace=desc ping -c 1 8.8.8.8 > /dev/null
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=61926, ...}) = 0
    close(3)                                = 0
    open("/lib64/libidn.so.11", O_RDONLY)   = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1) = 832
    省略号
    write(1, "\n", 1)                       = 1
    write(1, "--- 8.8.8.8 ping statistics ---\n"..., 146) = 146

6. 跟踪子进程

    -f 

有时候程序会fork出子进程,使用 -f 参数可以跟踪到子进程

7. strace的输出格式

    fstat(3, {st_mode=S_IFREG|0644, st_size=61926, ...}) = 0

每行的syacall格式为, syscall名字,syscall的参数, syscall的返回值

如果返回值为 -1 ,则顺带的返回具体的错误说明

To be continued …

参考文档

strace_the_sysadmin_s_microscope

5-simple-ways-to-troubleshoot-using-strace

strace man page

    分享到:

本文固定链接: http://klwang.info/about-strace/ | 数据库|Linux|软件开发

该日志由 klwang 于2013年06月21日发表在 Linux, shell 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: About strace | 数据库|Linux|软件开发
关键字: , ,

About strace:等您坐沙发呢!

发表评论

*
快捷键:Ctrl+Enter