最新消息:

关于strace

debug admin 3258浏览 0评论

简单说,strace是可以跟踪一个程序在做什么的命令。

一 它可以监控某个要执行的命令,比如平时最常见的ls命令:

[root@localhost a]# strace ls
execve(“/bin/ls”, [“ls”], [/* 26 vars */]) = 0
brk(0)                                  = 0x11a8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4792b00000
access(“/etc/ld.so.preload”, R_OK)      = -1 ENOENT (No such file or directory)
open(“/etc/ld.so.cache”, O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=63053, …}) = 0
mmap(NULL, 63053, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4792af0000
close(3)                                = 0
open(“/lib64/libselinux.so.1”, O_RDONLY) = 3
….

由上面可以看出,打开的是那个文件,还有依赖的文件

二 也可以监控正在执行的命令,比如nginx

[root@localhost a]# ps aux|grep nginx
root      1496  0.0  0.0 127536  1564 ?        Ss   Sep18   0:00 nginx: master process /Data/apps/nginx/sbin/nginx
daemon    1499  2.2  0.2 162008 36640 ?        S    Sep18 128:43 nginx: worker process

[root@localhost a]# strace -p 1499
Process 1499 attached – interrupt to quit
epoll_wait(25, {{EPOLLIN|EPOLLOUT, {u32=3002737265, u64=140018936586865}}}, 512, 141) = 1
recvfrom(1067, “”, 16384, 0, NULL, NULL) = 0
close(1067)                             = 0
epoll_wait(25, {{EPOLLIN|EPOLLOUT, {u32=3002704696, u64=140018936554296}}}, 512, 138) = 1
recvfrom(812, “1613v2X-Powered-By: PHP/5.2.13″…, 4096, 0, NULL, NULL) = 4096
readv(812, [{“.aslibra.com/” target=”_blank”…, 4096}], 1) = 4096

由上面可以看出,nginx在从后端的php接收数据

三 用strace细节可以做什么呢?

1 监测程序做什么: strace 命令
2 监测某个进程:strace -p pid
3 参数,man strace可以获知每个参数说明,说一些常用的:
监测每个步骤花了多少时间: -t 秒 -tt 毫秒 -ttt 时间戳
统计每个操作类型的用时 -c
只列举指定的操作 -e,比如 -e open,只列出打开文件的操作
输出到文件 -o filename
记录相对时间 -r

四 操作实例

1 检查程序引用的配置文件和打开的依赖文件,以nginx为例

[root@pic ~]# strace -e open /Data/apps/nginx/sbin/nginx -t
#加载依赖的库文件
open(“/etc/ld.so.cache”, O_RDONLY)      = 3
open(“/lib/libcrypt.so.1”, O_RDONLY)    = 3
open(“/lib/libpcre.so.0”, O_RDONLY)     = 3
open(“/lib/libcrypto.so.4”, O_RDONLY)   = 3
open(“/usr/lib/libz.so.1”, O_RDONLY)    = 3
open(“/lib/tls/libc.so.6”, O_RDONLY)    = 3
open(“/usr/lib/libgssapi_krb5.so.2”, O_RDONLY) = 3
open(“/usr/lib/libkrb5.so.3”, O_RDONLY) = 3
open(“/lib/libcom_err.so.2”, O_RDONLY)  = 3
open(“/usr/lib/libk5crypto.so.3”, O_RDONLY) = 3
open(“/lib/libresolv.so.2”, O_RDONLY)   = 3
open(“/lib/libdl.so.2”, O_RDONLY)       = 3
open(“/etc/localtime”, O_RDONLY)        = 3
#加载配置文件和检查系统配置文件
open(“/Data/apps/nginx/logs/error.log”, O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE, 0644) = 3
open(“/Data/apps/nginx/conf/nginx.conf”, O_RDONLY|O_LARGEFILE) = 4
open(“/etc/nsswitch.conf”, O_RDONLY)    = 5
open(“/etc/ld.so.cache”, O_RDONLY)      = 5
open(“/lib/libnss_files.so.2”, O_RDONLY) = 5
open(“/etc/passwd”, O_RDONLY)           = 5
open(“/etc/group”, O_RDONLY)            = 5
open(“/Data/apps/nginx/conf/mime.types”, O_RDONLY|O_LARGEFILE) = 5
open(“/etc/resolv.conf”, O_RDONLY)      = 5
open(“/etc/host.conf”, O_RDONLY)        = 5
open(“/etc/hosts”, O_RDONLY)            = 5
open(“/etc/ld.so.cache”, O_RDONLY)      = 5
open(“/lib/libnss_dns.so.2”, O_RDONLY)  = 5
open(“/etc/hosts”, O_RDONLY)            = 5
open(“/etc/hosts”, O_RDONLY)            = 5
open(“/etc/hosts”, O_RDONLY)            = 5
#加载自定义的配置文件
open(“/Data/apps/nginx/conf/fastcgi_params”, O_RDONLY|O_LARGEFILE) = 5
open(“/Data/apps/nginx/conf/fastcgi_params”, O_RDONLY|O_LARGEFILE) = 5
open(“/Data/apps/nginx/conf/fastcgi_params”, O_RDONLY|O_LARGEFILE) = 5
open(“/Data/apps/nginx/conf/dyw.cdn.conf”, O_RDONLY|O_LARGEFILE) = 5
open(“/Data/apps/nginx/conf/fastcgi_params”, O_RDONLY|O_LARGEFILE) = 6
the configuration file /Data/apps/nginx/conf/nginx.conf syntax is ok
open(“/Data/apps/nginx/logs/nginx.pid”, O_RDWR|O_CREAT|O_LARGEFILE, 0644) = 4
open(“/Data/logs/error.nginx.log”, O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE, 0644) = 4
configuration file /Data/apps/nginx/conf/nginx.conf test is successful
Process 18083 detached

2 监测程序做了什么,用php为例

写个测试的代码

<?
echo “test”;
file_get_contents(‘http://www.baidu.com’);
sleep(3);
file_put_contents(‘/tmp/test.php.txt’,’test’);

先看看执行概况:

strace -c /Data/apps/php/bin/php test.php
test% time     seconds  usecs/call     calls    errors syscall
—— ———– ———– ——— ——— —————-
59.91    0.000263           0      7977           select
32.35    0.000142           0      7985           poll
4.10    0.000018           1        29           munmap
2.51    0.000011           0       159           mmap

看上面的代码,select和poll其实是网络操作

strace -tt /Data/apps/php/bin/php test.php12:30:59.371957 execve(“/Data/apps/php/bin/php”, [“/Data/apps/php/bin/php”, “test.php”], [/* 26 vars */]) = 0

#尝试加载的路径优先级
12:30:59.372570 open(“/Data/apps/mysql/lib/mysql/tls/x86_64/libcrypt.so.1”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.372599 stat(“/Data/apps/mysql/lib/mysql/tls/x86_64”, 0x7ffff6f97f40) = -1 ENOENT (No such file or directory)
12:30:59.372626 open(“/Data/apps/mysql/lib/mysql/tls/libcrypt.so.1”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.372653 stat(“/Data/apps/mysql/lib/mysql/tls”, 0x7ffff6f97f40) = -1 ENOENT (No such file or directory)
12:30:59.372679 open(“/Data/apps/mysql/lib/mysql/x86_64/libcrypt.so.1”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.372708 stat(“/Data/apps/mysql/lib/mysql/x86_64”, 0x7ffff6f97f40) = -1 ENOENT (No such file or directory)
12:30:59.372737 open(“/Data/apps/mysql/lib/mysql/libcrypt.so.1”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.372765 stat(“/Data/apps/mysql/lib/mysql”, {st_mode=S_IFDIR|0755, st_size=4096, …}) = 0
12:30:59.372824 open(“/etc/ld.so.cache”, O_RDONLY) = 3

12:30:59.389336 access(“/Data/apps/php/bin/php”, X_OK) = 0
#看看读取了哪个配置文件
12:30:59.389380 open(“/Data/apps/php/bin/php-cli.ini”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.389413 open(“/Data/apps/php/etc/php-cli.ini”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.389443 open(“/Data/apps/php/bin/php.ini”, O_RDONLY) = -1 ENOENT (No such file or directory)
12:30:59.389472 open(“/Data/apps/php/etc/php.ini”, O_RDONLY) = 3

#读取配置文件
12:30:59.389773 read(3, “[PHP]nn;;;;;;;;;;;n; WARNING ;n;”…, 8192) = 8192
12:30:59.389886 read(3, “ay only alter environment variab”…, 8192) = 8192

#加载配置文件的模块
12:30:59.391577 open(“/Data/apps/php/lib/php/extensions/no-debug-non-zts-20060613/memcache.so”, O_RDONLY) = 3
12:30:59.391612 read(3, “177ELF21133>1 <”…, 832) = 832
12:30:59.391641 fstat(3, {st_mode=S_IFREG|0755, st_size=237176, …}) = 0
12:30:59.391677 mmap(NULL, 2154224, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1ff8fa9000
12:30:59.391705 mprotect(0x7f1ff8fb6000, 2097152, PROT_NONE) = 0
12:30:59.391732 mmap(0x7f1ff91b6000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd000) = 0x7f1ff91b6000
12:30:59.391814 close(3)                = 0

#eaccelerator尝试建立文件夹
12:30:59.400960 mkdir(“/Data/cache/eaccelerator_cache/0”, 0777) = -1 EEXIST (File exists)
12:30:59.401002 umask(0)                = 0

#读取执行的php文件
12:30:59.416912 open(“test.php”, O_RDONLY) = 3

#关闭该文件
12:30:59.417840 close(3)                = 0
12:30:59.417866 munmap(0x7f1ffff83000, 4096) = 0
12:30:59.417906 write(1, “test”, 4test)     = 4

#socket通信
12:30:59.418067 socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
12:30:59.418099 close(3)                = 0
12:30:59.418136 socket(PF_NETLINK, SOCK_RAW, 0) = 3
12:30:59.418162 bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
12:30:59.418189 getsockname(3, {sa_family=AF_NETLINK, pid=2889, groups=00000000}, [12]) = 0

#输出了第一句 echo
12:30:59.418215 sendto(3, “242613203r>R”, 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20

#检查www.baidu.com的域名指向
12:30:59.418559 open(“/etc/host.conf”, O_RDONLY) = 3

12:30:59.418826 open(“/etc/resolv.conf”, O_RDONLY) = 3

12:30:59.419021 open(“/etc/hosts”, O_RDONLY|O_CLOEXEC) = 3

#获得DNS服务器为 202.102.224.68,建立通信查询域名
12:30:59.419743 connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr(“202.102.224.68”)}, 16) = 0

#获得域名解析 指向 61.135.169.105
12:30:59.574172 connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr(“61.135.169.105”)}, 16) = 0

#发出http请求啦
12:30:59.709654 sendto(3, “GET / HTTP/1.1rnUser-Agent: PHP/”…, 76, MSG_NOSIGNAL, NULL, 0) = 76
12:30:59.709713 poll([{fd=3, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1, 0) = 0 (Timeout)
12:30:59.709759 select(4, [3], [3], [], {15, 0}) = 1 (out [3], left {14, 999998})
…大量 poll select
12:31:01.615348 recvfrom(3, “><script>var bdUser = null;var w”…, 3816, 0, NULL, NULL) = 3816

#休眠3秒
12:31:01.615462 close(3)                = 0
12:31:01.615620 nanosleep({3, 0}, 0x7ffff6f95f00) = 0
#写入文件
12:31:04.615796 lstat(“/tmp”, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=32768, …}) = 0
12:31:04.615853 lstat(“/tmp/test.php.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0
12:31:04.615906 open(“/tmp/test.php.txt”, O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
12:31:04.615972 fstat(3, {st_mode=S_IFREG|0644, st_size=0, …}) = 0
12:31:04.616011 lseek(3, 0, SEEK_CUR)   = 0
12:31:04.616040 write(3, “test”, 4)     = 4
12:31:04.616082 close(3)                = 0
12:31:04.616198 close(2)                = 0
12:31:04.616228 close(1)                = 0
12:31:04.616252 munmap(0x7f1ffff81000, 4096) = 0
12:31:04.616279 close(0)                = 0
12:31:04.616302 munmap(0x7f1ffff82000, 4096) = 0
12:31:04.616428 munmap(0x7f1ff8b39000, 2526280) = 0
12:31:04.616475 munmap(0x7f1ff8860000, 2985232) = 0
12:31:04.616508 munmap(0x7f1ff84eb000, 3624424) = 0
12:31:04.616556 munmap(0x3770a00000, 2162768) = 0
12:31:04.616587 munmap(0x7f1ff82de000, 2150272) = 0
12:31:04.616626 munmap(0x7f1ff8da2000, 2124096) = 0
12:31:04.616671 munmap(0x7f1ff8fa9000, 2154224) = 0
12:31:04.617215 munmap(0x7f1ff91b7000, 2205048) = 0
12:31:04.617618 exit_group(0)           = ?

五 参考阅读

1 Spying on Apache and PHP with Strace
5 simple ways to troubleshoot using Strace
strace(1) – Linux man page
Using Strace to Trace Problems 
7 Strace Examples to Debug the Execution of a Program in Linux
strace命令用法
Linux System Call Table
Fun with strace and the GDB Debugger
Exploring System Internals with lsof and strace 

转载请注明:爱开源 » 关于strace

您必须 登录 才能发表评论!