比如,有个在运行的some_server服务,第一步,查看pid:
pidof some_server17553
得到其pid 17553然后就可以用strace跟踪其执行:
strace -p 17553
完成跟踪时,按ctrl + C 结束strace即可 。
strace有一些选项可以调整其行为,我们这里介绍下其中几个比较常用的,然后通过示例讲解其实际应用效果 。
strace常用选项:
从一个示例命令来看:
strace -tt -T -v -f -e trace=file -o /data/log/strace.log -s 1024 -p 23489
-tt 在每行输出的前面,显示毫秒级别的时间实例:跟踪Nginx, 看其启动时都访问了哪些文件
-T 显示每次系统调用所花费的时间
-v 对于某些相关调用,把完整的环境变量,文件stat结构等打出来 。
-f 跟踪目标进程,以及目标进程创建的所有子进程
-e 控制要跟踪的事件和跟踪行为,比如指定要跟踪的系统调用名称
-o 把strace的输出单独写到指定的文件
-s 当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节
-p 指定要跟踪的进程pid, 要同时跟踪多个pid, 重复多次-p选项即可 。
strace -tt -T -f -e trace=file -o /data/log/strace.log -s 1024 ./nginx
部分输出:输出中,第一列显示的是进程的pid, 接着是毫秒级别的时间,这个是-tt 选项的效果 。
【Linux诊断、调试利器strace命令详解】每一行的最后一列,显示了该调用所花的时间,是-T选项的结果 。
这里的输出只显示和文件访问有关的内容,这是因为我们通过-e trace=file 选项指定了 。
strace问题定位案例1、定位进程异常退出
问题:机器上有个叫做run.sh的常驻脚本,运行一分钟后会死掉 。需要查出死因 。
定位:进程还在运行时,通过ps命令获取其pid, 假设我们得到的pid是24298
strace -o strace.log -tt -p 24298
查看strace.log, 我们在最后2行看到如下内容:22:47:42.803937 wait4(-1,<unfinished ...>22:47:43.228422 +++ killed by SIGKILL +++
这里可以看出,进程是被其他进程用KILL信号杀死的 。实际上,通过分析,我们发现机器上别的服务有个监控脚本,它监控一个也叫做run.sh的进程,当发现run.sh进程数大于2时,就会把它杀死重启 。结果导致我们这个run.sh脚本被误杀 。
进程被杀退出时,strace会输出killed by SIGX(SIGX代表发送给进程的信号)等,那么,进程自己退出时会输出什么呢?
这里有个叫做test_exit的程序,其代码如下:
#include <stdio.h>#include <stdlib.h>int main(int argc, char **argv) {exit(1);}
我们strace看下它退出时strace上能看到什么痕迹 。strace -tt -e trace=process -f ./test_exit
说明: -e trace=process 表示只跟踪和进程管理相关的系统调用 。输出:
23:07:24.672849 execve("./test_exit", ["./test_exit"], [/* 35 vars */]) = 023:07:24.674665 arch_prctl(ARCH_SET_FS, 0x7f1c0eca7740) = 023:07:24.675108 exit_group(1)= ?23:07:24.675259 +++ exited with 1 +++
可以看出,进程自己退出时(调用exit函数,或者从main函数返回), 最终调用的是exit_group系统调用,并且strace会输出exited with X(X为退出码) 。可能有人会疑惑,代码里面明明调用的是exit, 怎么显示为exit_group?
这是因为这里的exit函数不是系统调用,而是glibc库提供的一个函数,exit函数的调用最终会转化为exit_group系统调用,它会退出当前进程的所有线程 。实际上,有一个叫做_exit()的系统调用(注意exit前面的下划线), 线程退出时最终会调用它 。2、定位共享内存异常
有个服务启动时报错:
shmget 267264 30097568: Invalid argumentCan not get shm...exit!
错误日志大概告诉我们是获取共享内存出错,通过strace看下:strace -tt -f -e trace=ipc ./a_mon_svr../conf/a_mon_svr.conf
输出:22:46:36.351798 shmget(0x5feb, 12000, 0666) = 022:46:36.351939 shmat(0, 0, 0)= ?Process 21406 attached22:46:36.355439 shmget(0x41400, 30097568, 0666) = -1 EINVAL (Invalid argument)shmget 267264 30097568: Invalid argumentCan not get shm...exit!
这里,我们通过-e trace=ipc 选项,让strace只跟踪和进程通信相关的系统调用 。从strace输出,我们知道是shmget系统调用出错了,errno是EINVAL 。同样,查询下shmget手册页,搜索EINVAL的错误码的说明:
EINVAL A new segment was to be created and size < SHMMIN or size > SHMMAX, or no new segment was to be created, a segment with given key existed, but size is greater than the size of that segment
推荐阅读
- 整理了60个Python小例子,拿来即用
- 中班下学期期末评语怎么写?
- 十个字内的生日短句有哪些?
- 空调不凉怎么办?
- 动物|日本再次推迟送回人气大熊猫香香:太受欢迎、今年底才能回家
- 关于早安的暖心短句有哪些?
- 关于桃花最出名的诗句有哪些?
- 怎么用简单的一句话发朋友圈?
- 宝宝满月的祝福语怎么说?给宝宝满月祝福语大全
- 用动作描写害怕的句子有哪些?