[关闭]
@gy-ban 2016-11-13T09:11:57.000000Z 字数 3729 阅读 876

linux系统调用追踪工具--strace

linux命令


简介

strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通 过系统调用访问硬件设备。
strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

参数

  1. -c 统计每一系统调用的所执行的时间,次数和出错的次数等.
  2. -d 输出strace关于标准错误的调试信息.
  3. -f 跟踪由fork调用所产生的子进程.
  4. -ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
  5. -F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
  6. -h 输出简要的帮助信息.
  7. -i 输出系统调用的入口指针.
  8. -q 禁止输出关于脱离的消息.
  9. -r 打印出相对时间关于,,每一个系统调用.
  10. -t 在输出中的每一行前加上时间信息.
  11. -tt 在输出中的每一行前加上时间信息,微秒级.
  12. -ttt 微秒级输出,以秒了表示时间.
  13. -T 显示每一调用所耗的时间.
  14. -v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
  15. -V 输出strace的版本信息.
  16. -x 以十六进制形式输出非标准字符串
  17. -xx 所有字符串以十六进制形式输出.
  18. -a column
  19. 设置返回值的输出位置.默认 40.
  20. -e expr
  21. 指定一个表达式,用来控制如何跟踪.格式如下:
  22. [qualifier=][!]value1[,value2]...
  23. qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier trace.感叹号是否定符号.例如:
  24. -eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all none.
  25. 注意有些shell使用!来执行历史记录里的命令,所以要使用\\.
  26. -e trace=set
  27. 只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
  28. -e trace=file
  29. 只跟踪有关文件操作的系统调用.
  30. -e trace=process
  31. 只跟踪有关进程控制的系统调用.
  32. -e trace=network
  33. 跟踪与网络有关的所有系统调用.
  34. -e strace=signal
  35. 跟踪所有与系统信号有关的 系统调用
  36. -e trace=ipc
  37. 跟踪所有与进程通讯有关的系统调用
  38. -e abbrev=set
  39. 设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.
  40. -e raw=set
  41. 将指 定的系统调用的参数以十六进制显示.
  42. -e signal=set
  43. 指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.
  44. -e read=set
  45. 输出从指定文件中读出 的数据.例如:
  46. -e read=3,5
  47. -e write=set
  48. 输出写入到指定文件中的数据.
  49. -o filename
  50. strace的输出写入文件filename
  51. -p pid
  52. 跟踪指定的进程pid.
  53. -s strsize
  54. 指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
  55. -u username
  56. username UIDGID执行被跟踪的命令

实例

分析某个进程
我们经常使用top这个命令来查看当前系统运行情况。如果发现某个进程cpu使用特别高,我们可以使用strace跟踪一下:

  1. [root@gy-vm02 ~]# top
  2. top - 16:43:33 up 22 min, 2 users, load average: 0.28, 0.08, 0.05
  3. Tasks: 112 total, 2 running, 110 sleeping, 0 stopped, 0 zombie
  4. Cpu0 : 0.2%us, 1.6%sy, 0.0%ni, 90.9%id, 7.3%wa, 0.0%hi, 0.0%si, 0.0%st
  5. Cpu1 : 0.2%us, 0.7%sy, 0.0%ni, 98.4%id, 0.7%wa, 0.0%hi, 0.1%si, 0.0%st
  6. Mem: 1914432k total, 721532k used, 1192900k free, 120768k buffers
  7. Swap: 2031612k total, 0k used, 2031612k free, 439248k cached
  8. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
  9. 3550 root 20 0 101m 1204 692 R 22.0 0.1 0:02.69 grep -r 192.168.1.131 apollo bi bingo boohee care cube errbi
  10. 22 root 20 0 0 0 0 S 0.6 0.0 0:00.47 [kblockd/0]
  11. 3552 root 20 0 15036 1212 936 R 0.6 0.1 0:00.03 top

我们对很多文件夹进行了一个grep的操作,但是我们通过top只知道是grep这个命令使用了很多的cpu,并不清楚它在做些什么,这个时候我们使用strace跟踪一下:

  1. [root@gy-vm02 ~]# strace -cp 3550
  2. Process 3550 attached - interrupt to quit
  3. ^CProcess 3550 detached
  4. % time seconds usecs/call calls errors syscall
  5. ------ ----------- ----------- --------- --------- ----------------
  6. 48.86 0.151804 251 605 read
  7. 25.31 0.078655 224 351 stat
  8. 7.52 0.023369 59 399 open
  9. 6.80 0.021121 53 399 close
  10. 6.68 0.020744 216 96 getdents
  11. 4.83 0.015013 43 351 351 ioctl
  12. ------ ----------- ----------- --------- --------- ----------------
  13. 100.00 0.310706 2201 351 total

通过strace输出我们可以发现,大部分的cpu使用都在read,也就是读取文件内容。
如果还想进一步分析可以使用如下命令

  1. [root@gy-vm02 ~]# strace -T -e read -p 3550

解决库依赖问题
在linux系统里面,我们经常whoami来查看当前用户,如果手动移走一个依赖库

  1. [root@gy-vm02 ~]# mv /lib64/libnss_files.so.2 /tmp/

然后再次运行

  1. [root@gy-vm02 ~]# whoami
  2. whoami: cannot find name for user ID 0

发现不能使用了,使用ldd查看

  1. [root@gy-vm02 ~]# ldd whoami
  2. ldd: ./whoami: No such file or directory

给的信息也不能帮我们找到问题所在,这个时候我们使用strace进行跟踪一下

  1. open("/lib64/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
  2. open("/lib64/tls/x86_64/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
  3. stat("/lib64/tls/x86_64", 0x7fff58969c80) = -1 ENOENT (No such file or directory)
  4. open("/lib64/tls/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
  5. stat("/lib64/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
  6. open("/lib64/x86_64/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
  7. stat("/lib64/x86_64", 0x7fff58969c80) = -1 ENOENT (No such file or directory)
  8. open("/lib64/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

你可以发现在不同目录下面查找libnss_files.so.2的尝试,但是都失败了。如果没有strace这样的工具,很难发现这个错误是由于缺少动态库造成的。现 在只需要找到libnss_files.so.2并把它放回到正确的位置就可以了

  1. [root@gy-vm02 ~]# mv /tmp/libnss_files.so.2 /lib64/
  2. [root@gy-vm02 ~]# whoami
  3. root
  4. [root@gy-vm02 ~]#
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注