有时候,有很多问题只有在线上或者预发环境才能发现,而线上又不能调试代码,所以线
上问题定位就只能看日志、系统状态和dump线程,介绍一些常用的工具,介绍一些常用命令定位线上问题。
top
在Linux命令行下使用TOP命令查看每个进程的情况,显示如下。
- 交互命令数字1查看每个CPU的性能数据
- 查看某个进程所有线程的信息1top -H -p pid
strace & pstack
strace就是这样一款工具。通过它,我们可以跟踪程序执行过程中产生的系统调用及接收到的信号,帮助我们分析程序或命令执行中遇到的异常情况。
1. 一个简单的例子
|
|
2.strace跟踪输出
使用以下命令,我们将使用strace对以上程序进行跟踪,并将结果重定向至main.strace文件:
接下来我们来看main.strace文件的内容:
strace跟踪程序与系统交互时产生的系统调用,以上每一行就对应一个系统调用,格式为:
系统调用的名称( 参数… ) = 返回值 错误标志和描述
|
|
3. 输出分析
呼呼!看完这么多系统调用函数,是不是有点摸不着北?让我们从整体入手,回到主题strace上来。
从上面输出可以发现,真正能与源码对应上的只有open这一个系统调用(Line25),其他系统调用几乎都用于进行进程初始化工作:装载被执行程序、载入libc函数库、设置内存映射等。
源码中的if语句或其他代码在相应strace输出中并没有体现,因为它们并没有唤起系统调用。strace只关心程序与系统之间产生的交互,因而strace不适用于程序逻辑代码的排错和分析。
4. 常用选项
- 跟踪子进程 -f
- 记录系统调用时间
strace还可以记录程序与系统交互时,各个系统调用发生时的时间信息,有r、t、tt、ttt、T等几个选项,它们记录时间的方式为:
-T: 记录各个系统调用花费的时间,精确到微秒
-r: 以第一个系统调用(通常为execve)计时,精确到微秒
-t: 时:分:秒
-tt: 时:分:秒 . 微秒
-ttt: 计算机纪元以来的秒数 . 微秒
比较常用的为T选项,因为其提供了每个系统调用花费时间。而其他选项的时间记录既包含系统调用时间,又算上用户级代码执行用时,参考意义就小一些。对部分时间选项我们可以组合起来使用,例如:
最左边一列为-r选项对应的时间输出,最右边一列为-T选项对应的输出。
- 跟踪正在运行的进程 strace -p PID
5. 使用strace处理程序挂死实例
挂死程序源码
|
|
可向该程序传送user和system参数,以上代码使用死循环模拟用户态挂死,调用sleep模拟内核态程序挂死。
strace跟踪输出
用户态挂死跟踪输出:
12345……mprotect(0x8049000, 4096, PROT_READ) = 0mprotect(0xb59000, 4096, PROT_READ) = 0munmap(0xb77bf000, 80682) = 0getpid() = 14539内核态挂死跟踪输出:
123456789……mprotect(0x8049000, 4096, PROT_READ) = 0mprotect(0xddf000, 4096, PROT_READ) = 0munmap(0xb7855000, 80682) = 0getpid() = 14543rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0nanosleep({500, 0},
输出分析
用户态挂死情况下,strace在getpid()一行输出之后没有其他系统调用输出;进程在内核态挂死,最后一行的系统调用nanosleep不能完整显示,这里nanosleep没有返回值表示该调用尚未完成。
因而我们可以得出以下结论:使用strace跟踪挂死程序,如果最后一行系统调用显示完整,程序在逻辑代码处挂死;如果最后一行系统调用显示不完整,程序在该系统调用处挂死。
其它命令
- 查看网络流量 /proc/net/dev
- 查看连接数 /proc/net/snmp
- 查看内存信息 /proc/meminfo