暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

strace工具分析调试mem-agent启动故障一例

IT那活儿 2021-03-31
699
strace概述

  strace是一个可用于诊断、调试和分析的Linux用户空间跟踪器。我们用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。

在日常运维中,strace作为一种动态跟踪工具,能够帮助运维高效地定位进程和服务故障。可以使用strace分析程序hang住或者程序崩溃的原因,其跟踪程序执行过程中产生的系统调用及接收到的信号,帮助我们分析程序或命令执行中遇到的异常情况,使用strace跟踪挂死程序,如果最后一行系统调用显示完整,程序在逻辑代码处挂死;如果最后一行系统调用显示不完整,程序在该系统调用处挂死。

strace参数

-c 统计每一系统调用的所执行的时间,次数和出错的次数等.

-d 输出strace关于标准错误的调试信息.

-f 跟踪由fork调用所产生的子进程.

-ff 如果提供-ofilename,则所有进程的跟踪结果输出到相应的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]...

qualifier只能是trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的qualifier是trace.感叹号是否定符号.例如:

-eopen等价于 -etrace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号all 和none.

注意有些shell使用!来执行历史记录里的命令,所以要使用\\.

-e trace=set

只跟踪指定的系统调用.例如:-etrace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.

-e trace=file

只跟踪有关文件操作的系统调用.

-e trace=process

只跟踪有关进程控制的系统调用.

-e trace=network

跟踪与网络有关的所有系统调用.

-e strace=signal

跟踪所有与系统信号有关的系统调用

-e trace=ipc

跟踪所有与进程通讯有关的系统调用

-e abbrev=set

设定strace输出的系统调用的结果集.-v等与abbrev=none.默认为abbrev=all.

-e raw=set

将指 定的系统调用的参数以十六进制显示.

-e signal=set

指定跟踪的系统信号.默认为all.如signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.

-e read=set

输出从指定文件中读出的数据.例如:

-e read=3,5

-e write=set

输出写入到指定文件中的数据.

-o filename

将strace的输出写入文件filename

-p pid

跟踪指定的进程pid.

-s strsize

指定输出的字符串的最大长度.默认为32.文件名一直全部输出.

-u username

以username的UID和GID执行被跟踪的命令

命令实例

通用的完整用法:

strace -o output.txt -T -tt -e trace=all -p 29626

上面的含义是跟踪29626进程的所有系统调用(-etrace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。

实际案例

在给新主机10.230.19.132/133及数据库添加MEM监控时,需要先在主机上安装agent,在132执行./mysqlmonitoragent-3.3.3.1199-linux-x86-64bit-installer.bin时一直卡住不动,既没有报错也没有弹出如下的选择命令:

Language Selection

Please select the installation language

[1] English - English

[2] Japanese - 日本語

Please choose an option [1] :

此时因为没有有效的报错信息和日志,所以考虑使用strace工具进行调试分析具体问题原因:
使用strace工具调试启动并输出日志:
[mysql@onlinec]#strace./mysqlmonitoragent-3.3.3.1199-linux-x86-64bit-installer.bin >/tmp/132.log 2>&1
查看/tmp/132.log文件,查看最后内容:

futex(0x39dbf923c4, FUTEX_WAKE_PRIVATE,2147483647) = 0

open("/etc/resolv.conf", O_RDONLY)     = 7

fstat(7, {st_mode=S_IFREG|0644, st_size=94, ...})= 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4697c5f000

read(7, "# Generated byNetworkManager\nna"..., 4096) = 94

read(7, "", 4096)                      = 0

close(7)                                = 0

munmap(0x7f4697c5f000, 4096)            = 0

open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 7

fstat(7, {st_mode=S_IFREG|0644, st_size=187, ...})= 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4697c5f000

read(7, "27.0.0.1   localhost.localdomai"..., 4096) = 187

read(7, "", 4096)                      = 0

close(7)                                = 0

munmap(0x7f4697c5f000, 4096)            = 0

socket(PF_INET, SOCK_STREAM|SOCK_CLOEXEC,IPPROTO_TCP) = 7

setsockopt(7, SOL_TCP, TCP_NODELAY, [1], 4) = 0

setsockopt(7, SOL_SOCKET, SO_KEEPALIVE, [1], 4) =0

connect(7, {sa_family=AF_INET,sin_port=htons(6010), sin_addr=inet_addr("27.0.0.1")}, 16<unfinished ...>

而133执行./mysqlmonitoragent-3.3.3.1199-linux-x86-64bit-installer.bin是正常的,会正常弹出选择命令,同样观察strace输出日志用以对比132的输出进行分析
[mysql@onlinecs_m]#strace./mysqlmonitoragent-3.3.3.1199-linux-x86-64bit-installer.bin >/tmp/133.log 2>&1
查看/tmp/133.log文件,查看最后内容:

poll([{fd=7, events=POLLIN|POLLOUT}], 1, 5000) = 1([{fd=7, revents=POLLOUT}])

sendto(7,"K\357\1\0\0\1\0\0\0\0\0\0\tlocalhost\tlocalhost"..., 37,MSG_NOSIGNAL, NULL, 0) = 37

poll([{fd=7, events=POLLIN}], 1, 4999)  = 1([{fd=7, revents=POLLIN}])

ioctl(7, FIONREAD, [79])                = 0

recvfrom(7,"I\354\205\203\0\1\0\0\0\1\0\0\tlocalhost\tlocalhost"...,2048, 0, {sa_family=AF_INET, sin_port=htons(53),sin_addr=inet_addr("192.168.2.4")}, [16]) = 79

poll([{fd=7, events=POLLIN}], 1, 4998)  = 1([{fd=7, revents=POLLIN}])

ioctl(7, FIONREAD, [79])                = 0

recvfrom(7,"K\357\205\203\0\1\0\0\0\1\0\0\tlocalhost\tlocalhost"...,65536, 0, {sa_family=AF_INET, sin_port=htons(53),sin_addr=inet_addr("192.168.2.4")}, [16]) = 79

close(7)                                = 0

lstat("/home", {st_mode=S_IFDIR|0755,st_size=4096, ...}) = 0

write(5, "Log started 12/23/2017 at11:28:"..., 257) = 257

write(1, "Language Selection\n",19Language Selection

)    = 19

write(1, "\n", 1

)                       = 1

write(1, "Please select the installationl"..., 40Please select the installation language

) = 40

write(1, "[1] English - English\n",22[1] English - English

) = 22

write(1, "[2] Japanese -\346\227\245\346\234\254\350\252\236\n", 25[2] Japanese - 日本語

) = 25

write(1, "Please choose an option [1] : ",30Please choose an option [1] : ) = 30

read(0,  <unfinished ...>

对比两个日志文件内容,看到133的内容:
recvfrom(7,"I\354\205\203\0\1\0\0\0\1\0\0\tlocalhost\tlocalhost"...,2048, 0, {sa_family=AF_INET, sin_port=htons(53),sin_addr=inet_addr("10.230.19.133")}
而132上的内容是:
connect(7, {sa_family=AF_INET,sin_port=htons(6010), sin_addr=inet_addr("27.0.0.1")}, 16<unfinished ...>
从而判断132的sin_addr=inet_addr("27.0.0.1")有问题,查看132的/etc/hosts中内容发现:
27.0.0.1   localhost.localdomain localhost
重新改为
127.0.0.1   localhost.localdomain localhost后,执行bin文件正常。
总  结

如上例可以看出,日常运维中有些问题在没有错误信息和日志的输出可供分析的情况下很难与产生问题的真正原因关联起来,这时strace作为一种动态跟踪工具,能够帮助运维高效地定位进程和服务故障,通过系统调用的蛛丝马迹,找出异常的真相,节省异常解决的时间。

END

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论