[TOC]
前言简述 在运维的日常工作中,故障处理和问题诊断是个主要的内容,也是必备的技能
0x00 系统诊断 strace 命令 - 可用于诊断、调试和教学的Linux用户空间跟踪器 描述:官方介绍 strace是一个可用于诊断、调试和教学的Linux用户空间跟踪器。我们用它来监控用户空间进程和内核的交互
,比如系统调用、信号传递、进程状态变更等。其底层的实现方式是基于ptrace特性
;
Q:strace究竟能做什么呢?
它作为一种动态跟踪工具,能够帮助运维高效地定位进程和服务故障。它像是一个侦探,通过系统调用的蛛丝马迹,告诉你异常的真相。 它能够打开应用进程的这个黑盒,通过系统调用的线索告诉你进程大概在干嘛。
Q:在进入strace使用的主题之前,我们的先理解什么是系统调用?
按维基百科中的解释,在计算机中,系统调用(英语:system call),又称为系统呼叫,指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。 系统调用提供用户程序与操作系统之间的接口,在Linux系统上应用代码通过glibc库封装的函数
间接使用系统调用。
操作系统的进程空间分为用户空间和内核空间:
1.操作系统内核直接运行在硬件上,提供设备管理、内存管理、任务调度等功能。
2.用户空间通过API请求内核空间的服务来完成其功能——内核提供给用户空间的这些API, 就是系统调用。
Linux内核目前有300多个系统调用,详细的列表以通过syscalls手册页查看,系统调用主要分为几类:
文件和设备访问类 比如open/close/read/write/chmod等
进程管理类 fork/clone/execve/exit/getpid等
信号类 signal/sigaction/kill 等
内存管理 brk/mmap/mlock等
进程间通信IPC shmget/semget * 信号量,共享内存,消息队列等
网络通信 socket/connect/sendto/sendmsg 等
Syntax & Parameter:
[TOC]
前言简述 在运维的日常工作中,故障处理和问题诊断是个主要的内容,也是必备的技能
0x00 系统诊断 strace 命令 - 可用于诊断、调试和教学的Linux用户空间跟踪器 描述:官方介绍 strace是一个可用于诊断、调试和教学的Linux用户空间跟踪器。我们用它来监控用户空间进程和内核的交互
,比如系统调用、信号传递、进程状态变更等。其底层的实现方式是基于ptrace特性
;
Q:strace究竟能做什么呢?
它作为一种动态跟踪工具,能够帮助运维高效地定位进程和服务故障。它像是一个侦探,通过系统调用的蛛丝马迹,告诉你异常的真相。 它能够打开应用进程的这个黑盒,通过系统调用的线索告诉你进程大概在干嘛。
Q:在进入strace使用的主题之前,我们的先理解什么是系统调用?
按维基百科中的解释,在计算机中,系统调用(英语:system call),又称为系统呼叫,指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。 系统调用提供用户程序与操作系统之间的接口,在Linux系统上应用代码通过glibc库封装的函数
间接使用系统调用。
操作系统的进程空间分为用户空间和内核空间:
1.操作系统内核直接运行在硬件上,提供设备管理、内存管理、任务调度等功能。
2.用户空间通过API请求内核空间的服务来完成其功能——内核提供给用户空间的这些API, 就是系统调用。
Linux内核目前有300多个系统调用,详细的列表以通过syscalls手册页查看,系统调用主要分为几类:
文件和设备访问类 比如open/close/read/write/chmod等
进程管理类 fork/clone/execve/exit/getpid等
信号类 signal/sigaction/kill 等
内存管理 brk/mmap/mlock等
进程间通信IPC shmget/semget * 信号量,共享内存,消息队列等
网络通信 socket/connect/sendto/sendmsg 等
Syntax & Parameter:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 yum install -y strace strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ... [ -ofile ] [-ppid ] ... [ -sstrsize ] [ -uusername ] [ -Evar=val ] ... [ -Evar ]... [ command [ arg ... ] ] strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg... ] ] -c 统计每一系统调用的所执行的时间,次数和出错的次数等. -d 输出strace关于标准错误的调试信息. -f 跟踪由fork调用所产生的子进程. -ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. -F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. -h 输出简要的帮助信息. -i 输出系统调用的入口指针. -q 禁止输出关于脱离的消息. -r 打印出相对时间关于,,每一个系统调用. -t 在输出中的每一行前加上时间信息. -tt 在输出中的每一行前加上时间信息,微秒级. -ttt 微秒级输出,以秒了表示时间. -T 显示每一调用所耗的时间. -v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出. -V 输出strace的版本信息. -x 以十六进制形式输出非标准字符串 -xx 所有字符串以十六进制形式输出. -a column 设置返回值的输出位置.默认 为40. -e expr 指定一个表达式,用来控制如何跟踪.格式如下: [qualifier=][!]value1[,value2]... -e trace=all -e trace=file -e trace=process -e trace=network -e trace=signal -e trace=desc -e trace=ipc -e execve -e abbrev= -e raw= -e signal= -e read = -e write= -o filename -p pid -s strsize -u username 它的两种运行模式: - 1.通过它启动要跟踪的进程(可以类似理解为沙箱进行程序运行分析) - 2.跟踪已经在运行的进程(在不中断进程执行的情况下理解它在干嘛)
基础实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $nano hello.cint main() { int a=0; printf ("please input:\n" ); scanf("%d" ,&a); printf ("%9d\n" ,a); return 0; } $gcc hello.c && ./a.out$strace -s 2049 ./a.out
weiyigeek.top-实例0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 strace -tt -T -f -e trace=file -o /data/log /strace.log -s 1024 ./nginx strace -tt -T -v -f -e trace=file -o /data/log /strace.log -s 1024 -p 23489 strace -o output.txt -T -tt -e trace=all -p 28979 [root@terminal-1 ~]$ ./a.out [root@terminal-1 ~]$ strace -s 1024 -p 2225 [root@terminal-1 ~]$ killall ./a.out strace -c -o hello.txt ./a.out cat hello.txt % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 0.00 0.000000 0 2 read 0.00 0.000000 0 2 write 0.00 0.000000 0 2 open 0.00 0.000000 0 2 close 0.00 0.000000 0 4 fstat 0.00 0.000000 0 9 mmap 0.00 0.000000 0 4 mprotect 0.00 0.000000 0 1 munmap 0.00 0.000000 0 1 brk 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 arch_prctl ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000000 30 1 total strace -f -s10 -o text.txt -e execve ./a.out && cat text.txt strace -T -tt -o hello1.txt ./a.out && cat hello1.txt strace -e trace=file killall bt_uinfo_memcached 2>&1 | grep open | tail
weiyigeek.top-实例7系统调用计时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 strace -tt -f -e trace=ipc ./a_mon_svr ../conf/a_mon_svr.conf 从strace输出我们知道是shmget系统调用出错了errno是EINVAL。同样查询下shmget手册页搜索EINVAL的错误码的说明: shmget设置EINVAL错误码的原因为下列之一: * 要创建的共享内存段比 SHMMIN小 (一般是1个字节) * 要创建的共享内存段比 SHMMAX 大 (内核参数kernel.shmmax配置) * 指定key的共享内存段已存在,其大小和调用shmget时传递的值不同。 从strace输出看我们要连的共享内存key 0x41400, 指定的大小是30097568字节,明显与第1、2种情况不匹配。 那只剩下第三种情况使用ipcs看下是否真的是大小不匹配,可以看到已经0x41400这个key已经存在,并且其大小为30095516字节,和我们调用参数中的30097568不匹配于是产生了这个错误。 在我们这个案例里面导致共享内存大小不一致的原因是一组程序中,`其中一个编译为32位另外一个编译为64位`,代码里面使用了long这个变长int数据类型, 把两个程序都编译为64解决了这个问题。
补充示例: 1 2 3 4 sudo strace sysctl -w vm.swappiness = 0 cat /proc/sys/vm/swappiness 0
总结
1.当发现进程或服务异常时我们可以通过strace命令进行快速定位异常原因;
2.其可以让我们熟悉常用系统调用,能够更好地理解和使用strace命令;
3.当目标进程卡死在用户态时strace没有输出,此时我们需要其他的跟踪手段,比如gdb/perf/SystemTap等。
3.1) perf原因kernel支持
3.2) ftrace kernel支持可编程
3.3) systemtap 功能强大RedHat系统支持,对用户态,内核态逻辑都能探查,使用范围更广;
0x01 应用诊断