标题:[实践OK]运维利器:万能的strace,使用strace追踪多个进程,如何使用strace+pstack利器分析程序性能, 出处:向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除 时间:Wed, 25 May 2016 11:30:28 +0000 作者:jackxiang 地址:http://jackxiang.com/post/8718/ 内容: 背景:运维这个活其实是系统偏重的活,鄙人一直没做过运维,干了不到一个月,感觉发现其实也有点打杂的感觉,但都是围绕系统、权限、分配多机器、调度、维修、协调、沟通,特别是strace在启动一些服务时启动不了,用它就能很好的定位问题在哪儿。 下面这个主要是讲常用 的一个命令,如下: 运维利器:万能的strace:(批注:这个哥们写得好,赞一个:跟踪进程启动,跟踪命令的执行,根据进程号跟踪,启动时都访问了哪些文件。) http://www.yunweipai.com/archives/7334.html?utm_source=tuicool&utm_medium=referral 1)跟踪进程启动,主要是系统调用: strace -tt -f ./some_server ../conf/some_server.conf 2)通过它启动要跟踪的进程: strace ls -lh /var/log/messages 3)在运行的some_server服务: pidof some_server 17553 得到其pid 17553然后就可以用strace跟踪其执行: strace -p 17553 strace常用选项: 从一个示例命令来看: strace -tt -T -v -f -e trace=file -o /data/log/strace.log -s 1024 -p 23489 -tt 在每行输出的前面,显示毫秒级别的时间 -T 显示每次系统调用所花费的时间 -v 对于某些相关调用,把完整的环境变量,文件stat结构等打出来。 -f 跟踪目标进程,以及目标进程创建的所有子进程 -e 控制要跟踪的事件和跟踪行为,比如指定要跟踪的系统调用名称 -o 把strace的输出单独写到指定的文件 -s 当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节 -p 指定要跟踪的进程pid, 要同时跟踪多个pid, 重复多次-p选项即可。 实例:跟踪nginx, 看其启动时都访问了哪些文件 strace -tt -T -f -e trace=file -o /data/log/strace.log -s 1024 ./nginx 附录: 使用strace追踪多个进程: http://www.ttlsa.com/tools/use-strace-to-track-multiple-processes/ 如何使用strace+pstack利器分析程序性能: http://www.cnblogs.com/bangerlee/archive/2012/04/30/2476190.html strace_pstack]# gcc server.c -g -o server strace_pstack]# gcc client.c -g -o client [root@iZ25dcp92ckZ strace_pstack]# ./server listening... hello hello hello hello [root@iZ25dcp92ckZ strace_pstack]# ./client ps -elf | grep server | grep -v grep 0 S root 2327417130 0 80 0 - 1041 hrtime 14:58 pts/1 00:00:00 ./server [root@iZ25dcp92ckZ strace_pstack]# strace -o server.strace -Ttt -p 23274 Process 23274 attached 能看到生成的server.strace 脚本里时间相差1;s不对,nanosleep: 15:07:10.761597 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000009> 15:07:10.761632 nanosleep({1, 0}, 0x7fff08d80360) = 0 <1.000091> 15:07:11.761768 sendto(4, "hello\0", 6, 0, NULL, 0) = 6 <0.000065> 15:07:11.761881 select(8, [3 4], NULL, NULL, {1, 0}) = 1 (in [4], left {0, 761}) <0.999266> 15:07:12.761221 recvfrom(4, "hello", 6, 0, NULL, NULL) = 5 <0.000012> 用pstack脚本找到是哪儿调用了nanosleep系统函数导致慢了1s: [root@iZ25dcp92ckZ strace_pstack]# sh pstack.sh 23274 #0 0x00007f75e5bec480 in __nanosleep_nocancel () from /lib64/libc.so.6 #1 0x00007f75e5bec334 in sleep () from /lib64/libc.so.6 #2 0x0000000000400813 in ha_ha () #3 0x0000000000400aea in main () [root@iZ25dcp92ckZ strace_pstack]# vi pstack.sh #!/bin/sh if test $# -ne 1; then echo "Usage: `basename $0 .sh` " 1>&2 exit 1 fi if test ! -r /proc/$1; then echo "Process $1 not found." 1>&2 exit 1 fi # GDB doesn't allow "thread apply all bt" when the process isn't # threaded; need to peek at the process to determine if that or the # simpler "bt" should be used. backtrace="bt" if test -d /proc/$1/task ; then # Newer kernel; has a task/ directory. if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then backtrace="thread apply all bt" fi elif test -f /proc/$1/maps ; then # Older kernel; go by it loading libpthread. if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then backtrace="thread apply all bt" fi fi GDB=${GDB:-/usr/bin/gdb} if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then readnever=--readnever else readnever= fi # Run GDB, strip out unwanted noise. $GDB --quiet $readnever -nx /proc/$1/exe $1 <&1 | $backtrace EOF /bin/sed -n \ -e 's/^(gdb) //' \ -e '/^#/p' \ -e '/^Thread/p' Generated by Jackxiang's Bo-blog 2.1.1 Release