[转帖]神器之strace

神器之strace

https://www.jianshu.com/p/33521124bdf2
什么是strace

strace是Linux环境下的一款程序调试工具,用来监察一个应用程序所使用的系统调用。
Strace是一个简单的跟踪系统调用执行的工具。在其最简单的形式中,它可以从开始到结束跟踪二进制的执行,并在进程的生命周期中输出一行具有系统调用名称,每个系统调用的参数和返回值的文本行。

在Linux中,进程是不能直接去访问硬件设备的,比如读取磁盘文件、接收网络数据等,但可以将用户态模式切换到内核模式,通过系统调用来访问硬件设备。这时strace就可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间、调用次数,成功和失败的次数。

strace能做什么

  • 它可以基于特定的系统调用或系统调用组进行过滤
  • 它可以通过统计特定系统调用的使用次数,所花费的时间,以及成功和错误的数量来分析系统调用的使用。
  • 它跟踪发送到进程的信号。
  • 可以通过pid附加到任何正在运行的进程。
  • 调试性能问题,查看系统调用的频率,找出耗时的程序段
  • 查看程序读取的是哪些文件从而定位比如配置文件加载错误问题
  • 查看某个php脚本长时间运行“假死”情况
  • 当程序出现“Out of memory”时被系统发出的SIGKILL信息所kill
    另外因为strace拿到的是系统调用相关信息,一般也即是IO操作信息,这个对于排查比如cpu占用100%问题是无能为力的。这个时候就可以使用GDB工具了。

phptrace
因为strace只能追踪到系统调用信息,而拿不到php代码层的调用信息。phptrace扩展就是为了解决这个问题,phptrace包含两个功能:1. 打印当前PHP调用栈,2. 实时追踪PHP调用。这样就能更方便我们去查看到我们需要的信息。phptrace wiki

strace的使用

1、找出程序在启动时读取的配置文件

[root@localhost ~]# strace php 2>&1 | grep php.ini open("/Data/apps/php7/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/Data/apps/php7/etc/php.ini", O_RDONLY) = 3 

2、使用strace来跟踪cat查看一个文件做了什么

[root@localhost mau]# strace cat index.php
execve("/usr/bin/cat", ["cat", "index.php"], [/* 27 vars */]) = 0 brk(0) = 0x60d000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7ff9000 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=106900, ...}) = 0 mmap(NULL, 106900, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7fde000 close(3) = 0 open("/usr/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\0\34\2\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=2107768, ...}) = 0 mmap(NULL, 3932736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff7a1b000 mprotect(0x7ffff7bd1000, 2097152, PROT_NONE) = 0 mmap(0x7ffff7dd1000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7ffff7dd1000 mmap(0x7ffff7dd7000, 16960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dd7000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fdd000 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fdb000 arch_prctl(ARCH_SET_FS, 0x7ffff7fdb740) = 0 mprotect(0x7ffff7dd1000, 16384, PROT_READ) = 0 mprotect(0x60b000, 4096, PROT_READ) = 0 mprotect(0x7ffff7ffc000, 4096, PROT_READ) = 0 munmap(0x7ffff7fde000, 106900) = 0 brk(0) = 0x60d000 brk(0x62e000) = 0x62e000 brk(0) = 0x62e000 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=106065056, ...}) = 0 mmap(NULL, 106065056, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff14f4000 close(3) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0 open("index.php", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=17, ...}) = 0 fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0 read(3, "<?php\nphpinfo();\n", 65536) = 17 write(1, "<?php\nphpinfo();\n", 17<?php phpinfo(); ) = 17 read(3, "", 65536) = 0 close(3) = 0 close(1) = 0 close(2) = 0 exit_group(0) = ? +++ exited with 0 +++ 

跟踪read函数

[root@localhost mau]# strace -e read cat index.php
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\34\2\0\0\0\0\0"..., 832) = 832
read(3, "<?php\nphpinfo();\n", 65536)   = 17
<?php
phpinfo();
read(3, "", 65536)                      = 0
+++ exited with 0 +++

统计每一系统调用的所执行的时间,次数和出错的次数

[root@localhost mau]# strace -c cat index.php
<?php phpinfo(); % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 22.22 0.000016 2 8 mmap 15.28 0.000011 3 4 open 12.50 0.000009 2 4 mprotect 9.72 0.000007 7 1 write 9.72 0.000007 1 6 close 6.94 0.000005 1 5 fstat 6.94 0.000005 5 1 munmap 5.56 0.000004 1 3 read 4.17 0.000003 1 4 brk 2.78 0.000002 2 1 1 access 2.78 0.000002 2 1 fadvise64 1.39 0.000001 1 1 execve 0.00 0.000000 0 1 arch_prctl ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000072 40 1 total 

显示每一调用所耗的时间

[root@localhost mau]# strace -T cat index.php 2>&1|grep read
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\34\2\0\0\0\0\0"..., 832) = 832 <0.000007>
read(3, "<?php\nphpinfo();\n", 65536)   = 17 <0.000009>
read(3, "", 65536)                      = 0 <0.000007>

3、为什么这个程序不能打开我的文件?

当我们开发了一个PHP扩展,可以PHP为什么加载不到我们的扩展文件,通过命令:

[root@localhost mau]# strace -e open php 2>&1 | grep phpfuns 

在输出的结果中查找失败的open()或access()系统调用,很有可能是因为权限问题导致的。

4、查看程序在干什么

[root@localhost system]# strace -p $pid
Process 3625 attached
futex(0x13517c4, FUTEX_WAIT_PRIVATE, 527904, NULL) = -1 EAGAIN (Resource temporarily unavailable) futex(0x13517c4, FUTEX_WAIT_PRIVATE, 527912, NULL) = 0 futex(0x134e7e0, FUTEX_WAKE_PRIVATE, 1) = 0 setsockopt(39, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 sendto(39, "J\0\0\0\n5.6.30\0\35\7\4\0j;'O<{xh\0\377\367\10\2\0\177\200"..., 78, MSG_DONTWAIT, NULL, 0) = 78 recvfrom(39, "\263\0\0\1", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(39, "\215\242?\0\0\0\0@\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 179, MSG_DONTWAIT, NULL, NULL) = 179 access("./db_firewall_log", F_OK) = 0 open("./db_firewall_log/db.opt", O_RDONLY) = -1 ENOENT (No such file or directory) sendto(39, "\7\0\0\2\0\0\0\2\0\0\0", 11, MSG_DONTWAIT, NULL, 0) = 11 recvfrom(39, "\17\0\0\0", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(39, "\3SET NAMES utf8", 15, MSG_DONTWAIT, NULL, NULL) = 15 sendto(39, "\7\0\0\1\0\0\0\2\0\0\0", 11, MSG_DONTWAIT, NULL, 0) = 11 recvfrom(39, "\21\0\0\0", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(39, "\3set autocommit=0", 17, MSG_DONTWAIT, NULL, NULL) = 17 

5、为什么****不能连接到该服务器?

[root@localhost mau]# strace -e poll,select,connect,recvfrom,sendto ssh root@172.16.1.137 connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) poll([{fd=3, events=POLLIN}], 1, 10) = 1 ([{fd=3, revents=POLLIN}]) connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) sendto(3, "\24\0\0\0\26\0\1\3\3537\365Z\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 connect(4, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_INET, sin_port=htons(22), sin_addr=inet_addr("172.16.1.137")}, 16) = -1 ETIMEDOUT (Connection timed out) ssh: connect to host 172.16.1.137 port 22: Connection timed out +++ exited with 255 +++ 

strace调试php

[root@localhost mau]# strace -ff -o strace.log -f -F -T /Data/apps/php7/sbin/php-fpm -c /Data/apps/php7/etc/php-fpm.conf [root@localhost mau]# ls index.php0 

欢迎关注个人微信公众号:

猜你喜欢

转载自www.cnblogs.com/jinanxiaolaohu/p/12670954.html