Linux服务器排障利器strace

系统 Linux
strace是一个有用的小工具,它可以通过跟踪系统调用来让你知道一个程序在后台所做的事情。Strace是一个基础的调试工具,在大多数Linux系统上默认已经安装;但是即便你不是在跟踪一个问题的时候它也是一个极好的软件。它能告诉你很多关于一个Linux程序怎样工作的信息。

strace是一个有用的小工具,它可以通过跟踪系统调用来让你知道一个程序在后台所做的事情。Strace是一个基础的调试工具,在大多数Linux系统上默认已经安装;但是即便你不是在跟踪一个问题的时候它也是一个极好的软件。它能告诉你很多关于一个Linux程序怎样工作的信息。

一个系统调用就是一个从应用程序到内核的消息。现代计算机系统中的用户程序都是运行在一个沙箱里面:它们不允许直接与计算机交互(因此你不能像以前那样往寄存器里面塞一些数据来完成某些工作)。取而代之的是,每当程序需要与系统交互的时候,他就发送一个请求(系统调用)到内核。Strace就是用来跟踪这些消息的。因此请记住,如果你有一会儿看不到任何strace的输出,这也并不代表你的程序发生了阻塞。很有可能是程序在自己的沙箱里面做某些事情,而这些事情并不需要与系统的其它部分发生通信。

用法

Strace程序固然能做这些事情,但它总是直接将所有的东西输出到标准错误文件(也就是屏幕)。就像你将看到的那样,它会产生大量的输出;因此通常来说你最好用-o选项来设置一个输出文件:

strace -o outputfile.txt program

有一些编辑器(如vim)能够对strace的输出进行语法高亮显示。这意味着文件的不同部分,以及每一行的不同部分都会用不同的颜色来显示。这个功能相当有用,我强烈建议你使用一个这样的编辑器来查看strace的输出。

命令输出解释

试一试strace -o strace.out ls –l,然后用你喜欢的编辑器打开strace.out,并且启用语法高亮。

在深入探索细节之前,先来看看每一行的基本结构。Strace记录了程序所发出的每一次系统调用,并且各自显示在单独的一行中。系统调用的名字出现在每一行的起始,参数出现在括号里面,返回值则在等号后面,是一行的终结。命令ls –l的头几行输出基本上是如下这个样子:

execve("/bin/ls", ["ls", "-l"], [/* 21 vars */])      = 0
brk(0)                                                = 0x619000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b412f2b9000
uname({sys="Linux", node="juliet.example.com", ...})  = 0

第一行显示的是一个execve的系统调用,其参数如下:

  1. 当前可执行程序的位置 (/bin/ls)
  2. 一个从命令行传递过来的参数数组 (ls与-l)
  3. 一个指向21个环境变量的指针,也是传递给该程序的。

返回值为0,表示执行成功。这就是所有系统调用都相同的基本结构。

所有在后台的内幕

接下来的几行跟内存管理有关。Brk改变数据段的大小,而mmap用来返回一个进程可用的内存位置。(如需要更多信息,请尝试man 2 mmap。)

再下面一行是uname系统调用,用来显示系统的详细信息。Uname所返回的是一个指针,它指向存储这些信息的一个数据结构。系统调用经常会返回指针:这是一个内存引用,告诉你到哪里去寻找这些信息。如果你是一台计算机,这非常有用,但如果你是一个人就未必了;因此为了方便起见,每当__strace__看到一个指针的时候,它就自动帮你进行查找,然后返回(一部分)指针指向的内容。这正是上面在uname系统调用那里所发生的事情。

如果你继续查看strace的输出,你就会看到很多access和open的调用。Access查找一个文件(如果没找到就返回-1和一个错误码),然后检查当前程序是否有访问权限。Open试图打开一个文件,如果成功的话就会将其连接到一个文件句柄(从3开始,因为0-2被用于STDIN、STDOUT和STDERR)并返回这个句柄。然后,fstat会获取连接到该句柄的文件的有关信息,句柄通过第一个参数传递而来,就像这样(注意第二个参数是一个指针!):

fstat(3, {st_mode=S_IFREG|0644, st_size=53482, ...}) = 0

在另一个mmap调用以后,文件将会被关闭。在ls的输出中,你会看到这个序列在库文件上面重复许多遍。而在那以后,对于每一个列出的文件还有lstat、lgetxattr和getxattr等调用。这都是对每个文件获取信息用的。最后,每个文件都会按这种方式写到输出文件:

stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3661, ...}) = 0
write(1, "-rw-------  1 juliet juliet 10"..., 72) = 72

编号为1和2的文件句柄 (STDOUT和STDERR)将会关闭,于是一切都完成了。

结论

这只是一个关于阅读strace输出的非常快速的介绍。要深入理解的话,最好的建议是去查看每个系统调用的手册页(man 2 <系统调用名>),并且尝试着在各种程序中使用strace跟踪输出。在各种语言的‘Hello, World’程序上使用strace是一件非常有趣的事情。你还可以检查某个已经在运行的程序,然后用strace的-p PID选项来实时连接到其中的某一个。祝你在使用strace深入解剖你的程序时其乐无穷!

【编辑推荐】

  1. 快速诊断Linux服务器故障的三大法宝
  2. 十大X86服务器常见故障——硬件篇
  3. 十大x86服务器常见故障——系统篇
责任编辑:yangsai 来源: 互联网
相关推荐

2014-12-01 11:25:11

sysdigLinux

2010-08-27 10:18:24

DHCP服务

2010-08-05 14:29:54

NFS服务

2010-03-17 15:35:47

2009-07-27 10:03:02

分层模型网络故障

2020-09-02 12:45:52

Linux排障运维

2020-10-24 15:31:10

Linux服务器工具

2013-07-25 09:56:22

OSPF路由选择路由故障OSPF

2011-03-10 10:31:55

Linux服务器管理软SUSE Manage

2018-07-27 06:21:46

数据中心运维管理网络设备

2013-12-03 16:28:06

2010-07-15 11:16:04

负载均衡

2012-03-01 10:07:23

ARM服务器x86处理器服务器

2010-09-08 14:56:06

nmon

2011-03-28 16:37:38

2010-08-20 09:45:40

IOS升级排障

2010-07-09 09:43:21

企业IT架构服务器管理

2015-05-29 13:22:10

Linux挂载运维

2014-08-06 11:25:00

LinuxSVN服务器

2022-05-05 09:27:31

Linux服务器优化
点赞
收藏

51CTO技术栈公众号