GHOST系统之家 - Windows系统光盘下载网站!
当前位置:GHOST系统之家>系统问题 > 使用strace命令定位和诊断故障的实例分享

使用strace命令定位和诊断故障的实例分享

来源:Ghost系统之家浏览:时间:2023-04-11 08:01:46

通过Strace定位故障原因
这是一个Nginx错误日志:

connect() failed (110: Connection timed out) while connecting to upstream
connect() failed (111: Connection refused) while connecting to upstream
看上去是Upstream出了问题,在本例中Upstream就是PHP(版本:5.2.5)。可惜监控不完善,我搞不清楚到底是哪出了问题,无奈之下只好不断重启PHP来缓解故障。

如果每次都手动重启服务无疑是个苦差事,幸运的是可以通过CRON设置每分钟执行:

复制代码代码如下:
#/bin/bash/p

LOAD=$(awk '{print $1}' /proc/loadavg)

if [ $(echo "$LOAD > 100" | bc) = 1 ]; then
/etc/init.d/php-fpm restart
fi

可惜这只是一个权宜之计,要想彻底解决就必须找出故障的真正原因是什么。

<>

闲言碎语不要讲,轮到Strace出场了,统计一下各个系统调用的耗时情况:

复制代码代码如下:
shell strace -c -p $(pgrep -n php-cgi)
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 30.53    0.023554         132       179           brk
 14.71    0.011350         140        81           mlock
 12.70    0.009798          15       658        16 recvfrom
  8.96    0.006910           7       927           read
  6.61    0.005097          43       119           accept
  5.57    0.004294           4       977           poll
  3.13    0.002415           7       359           write
  2.82    0.002177           7       311           sendto
  2.64    0.002033           2      1201         1 stat
  2.27    0.001750           1      2312           gettimeofday
  2.11    0.001626           1      1428           rt_sigaction
  1.55    0.001199           2       730           fstat
  1.29    0.000998          10       100       100 connect
  1.03    0.000792           4       178           shutdown
  1.00    0.000773           2       492           open
  0.93    0.000720           1       711           close
  0.49    0.000381           2       238           chdir
  0.35    0.000271           3        87           select
  0.29    0.000224           1       357           setitimer
  0.21    0.000159           2        81           munlock
  0.17    0.000133           2        88           getsockopt
  0.14    0.000110           1       149           lseek
  0.14    0.000106           1       121           mmap
  0.11    0.000086           1       121           munmap
  0.09    0.000072           0       238           rt_sigprocmask
  0.08    0.000063           4        17           lstat
  0.07    0.000054           0       313           uname
  0.00    0.000000           0        15         1 access
  0.00    0.000000           0       100           socket
  0.00    0.000000           0       101           setsockopt
  0.00    0.000000           0       277           fcntl
------ ----------- ----------- --------- --------- ----------------
100.00    0.077145                 13066       118 total
看上去「brk」非常可疑,它竟然耗费了三成的时间,保险起见,单独确认一下:

复制代码代码如下:
shell strace -T -e brk -p $(pgrep -n php-cgi)
brk(0x1f18000) = 0x1f18000 0.024025
brk(0x1f58000) = 0x1f58000 0.015503
brk(0x1f98000) = 0x1f98000 0.013037
brk(0x1fd8000) = 0x1fd8000 0.000056
brk(0x2018000) = 0x2018000 0.012635
说明:在Strace中和操作花费时间相关的选项有两个,分别是「-r」和「-T」,它们的差别是「-r」表示相对时间,而「-T」表示绝对时间。简单统计可以用「-r」,但是需要注意的是在多任务背景下,CPU随时可能会被切换出去做别的事情,所以相对时间不一定准确,此时最好使用「-T」,在行尾可以看到操作时间,可以发现确实很慢。

>><><><><><>

在继续定位故障原因前,我们先通过「man brk」来查询一下它的含义:

brk() sets the end of the data segment to the value specified by end_data_segment, when that value is reasonable, the system does have enough memory and the process does not exceed its max data size (see setrlimit(2)).

简单点说就是内存不够用时通过它来申请新内存(data segment),可是为什么呢?

复制代码代码如下:
shell strace -T -p $(pgrep -n php-cgi) 21 | grep -B 10 brk
stat("/path/to/script.php", {...}) = 0 0.000064
brk(0x1d9a000) = 0x1d9a000 0.000067
brk(0x1dda000) = 0x1dda000 0.001134
brk(0x1e1a000) = 0x1e1a000 0.000065
brk(0x1e5a000) = 0x1e5a000 0.012396
brk(0x1e9a000) = 0x1e9a000 0.000092
通过「grep」我们很方便就能获取相关的上下文,反复运行几次,发现每当请求某些PHP脚本时,就会出现若干条耗时的「brk」,而且这些PHP脚本有一个共同的特点,就是非常大,甚至有几百K,为何会出现这么大的PHP脚本?实际上是程序员为了避免数据库操作,把非常庞大的数组变量通过「var_export」持久化到PHP文件中,然后在程序中通过「include」来获取相应的变量,因为变量太大,所以PHP不得不频繁执行「brk」,不幸的是在本例的环境中,此操作比较慢,从而导致处理请求的时间过长,加之PHP进程数有限,于是乎在Nginx上造成请求拥堵,最终导致高负载故障。

>>&<><><><><><>

下面需要验证一下推断似乎否正确,首先查询一下有哪些地方涉及问题脚本:

复制代码代码如下:
shell find /path -name "*.php" | xargs grep "script.php"
直接把它们都禁用了,看看服务器是否能缓过来,或许大家觉得这太鲁蒙了,但是特殊情况必须做出特殊的决定,不能像个娘们儿似的优柔寡断,没过多久,服务器负载恢复正常,接着再统计一下系统调用的耗时:

复制代码代码如下:
shell strace -c -p $(pgrep -n php-cgi)
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 24.50    0.001521          11       138         2 recvfrom
 16.11    0.001000          33        30           accept
  7.86    0.000488           8        59           sendto
  7.35    0.000456           1       360           rt_sigaction
  6.73    0.000418           2       198           poll
  5.72    0.000355           1       285           stat
  4.54    0.000282           0       573           gettimeofday
  4.41    0.000274           7        42           shutdown
  4.40    0.000273           2       137           open
  3.72    0.000231           1       197           fstat
  2.93    0.000182           1       187           close
  2.56    0.000159           2        90           setitimer
  2.13    0.000132           1       244           read
  1.71    0.000106           4        30           munmap
  1.16    0.000072           1        60           chdir
  1.13    0.000070           4        18           setsockopt
  1.05    0.000065           1       100           write
  1.05    0.000065           1        64           lseek
  0.95    0.000059           1        75           uname
  0.00    0.000000           0        30           mmap
  0.00    0.000000           0        60           rt_sigprocmask
  0.00    0.000000           0         3         2 access
  0.00    0.000000           0         9           select
  0.00    0.000000           0        20           socket
  0.00    0.000000           0        20        20 connect
  0.00    0.000000           0        18           getsockopt
  0.00    0.000000           0        54           fcntl
  0.00    0.000000           0         9           mlock
  0.00    0.000000           0         9           munlock
------ ----------- ----------- --------- --------- ----------------
100.00    0.006208                  3119        24 total
显而易见,「brk」已经不见了,取而代之的是「recvfrom」和「accept」,不过这些操作本来就是很耗时的,所以可以定位「brk」就是故障的原因。

>>

用 strace 诊断问题
早些年,如果你知道有个 strace 命令,就很牛了,而现在大家基本都知道 strace 了,如果你遇到性能问题求助别人,十有八九会建议你用 strace 挂上去看看,不过当你挂上去了,看着满屏翻滚的字符,却十有八九看不出个所以然。本文通过一个简单的案例,向你展示一下在用 strace 诊断问题时的一些套路。
如下真实案例,如有雷同,实属必然!让我们看一台高负载服务器的 top 结果:
使用strace命令定位和诊断故障的实例分享

技巧:运行 top 时,按「1」打开 CPU 列表,按「shift+p」以 CPU 排序。

在本例中大家很容易发现 CPU 主要是被若干个 PHP 进程占用了,同时 PHP 进程占用的比较多的内存,不过系统内存尚有结余,SWAP 也不严重,这并不是问题主因。

不过在 CPU 列表中能看到 CPU 主要消耗在内核态「sy」,而不是用户态「us」,和我们的经验不符。Linux 操作系统有很多用来跟踪程序行为的工具,内核态的函数调用跟踪用「strace」,用户态的函数调用跟踪用「ltrace」,所以这里我们应该用「strace」:

复制代码代码如下:
shell strace -p PID
不过如果直接用 strace 跟踪某个进程的话,那么等待你的往往是满屏翻滚的字符,想从这里看出问题的症结并不是一件容易的事情,好在 strace  可以按操作汇总时间:

复制代码代码如下:
shell strace -cp PID
通过「c」选项用来汇总各个操作的总耗时,运行后的结果大概如下图所示:
使用strace命令定位和诊断故障的实例分享

><>><>

很明显,我们能看到 CPU 主要被 clone 操作消耗了,还可以单独跟踪一下 clone:

复制代码代码如下:
shell strace -T -e clone -p PID
通过「T」选项可以获取操作实际消耗的时间,通过「e」选项可以跟踪某个操作:
使用strace命令定位和诊断故障的实例分享

><>

很明显,一个 clone 操作需要几百毫秒,至于 clone 的含义,参考 man 文档:

clone() creates a new process, in a manner similar to fork(2). It is actually a library function layered on top of the underlying clone() system call, hereinafter referred to as sys_clone. A description of sys_clone is given towards the end of this page.

Unlike fork(2), these calls allow the child process to share parts of its execution context with the calling process, such as the memory space, the table of file descriptors, and the table of signal handlers. (Note that on this manual page, “calling process” normally corresponds to “parent process”. But see the description of CLONE_PARENT below.)

简单来说,就是创建一个新进程。那么在 PHP 里什么时候会出现此类系统调用呢?查询业务代码看到了 exec 函数,通过如下命令验证它确实会导致 clone 系统调用:

复制代码代码如下:
shell strace -eclone php -r 'exec("ls");'
最后再考大家一个题:如果我们用 strace 跟踪一个进程,输出结果很少,是不是说明进程很空闲?其实试试 ltrace,可能会发现别有洞天。记住有内核态和用户态之分。

>

标签:

推荐系统

  • 微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    语言:中文版系统大小:5.13GB系统类型:Win11

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Win11 64位 Office办公版(免费)优化  1、保留 Edge浏览器。  2、隐藏“操作中心”托盘图标。  3、保留常用组件(微软商店,计算器,图片查看器等)。  5、关闭天气资讯。 

  • Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    语言:中文版系统大小:4.75GB系统类型:Win11

    Ghost Win11 21H2是微软在系统方面技术积累雄厚深耕多年,Ghost Win11 21H2系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Ghost Win11 21H2是微软最新发布的KB5019961补丁升级而来的最新版的21H2系统,以Windows 11 21H2 22000 1219 专业版为基础进行优化,保持原汁原味,系统流畅稳定,保留常用组件

  • windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载,微软win11发布快大半年了,其中做了很多次补丁和修复一些BUG,比之前的版本有一些功能上的调整,目前已经升级到最新版本的镜像系统,并且优化了自动激活,永久使用。windows11中文版镜像国内镜像下载地址微软windows11正式版镜像 介绍:1、对函数算法进行了一定程度的简化和优化

  • 微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载,微软2022年正式推出了win11系统,很多人迫不及待的要体验,本站提供了最新版的微软Windows11正式版系统下载,微软windows11正式版镜像 是一款功能超级强大的装机系统,是微软方面全新推出的装机系统,这款系统可以通过pe直接的完成安装,对此系统感兴趣,想要使用的用户们就快来下载

  • 微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    语言:中文版系统大小:0MB系统类型:Win11

    微软Ghost win11 正式版镜像文件是一款由微软方面推出的优秀全新装机系统,这款系统的新功能非常多,用户们能够在这里体验到最富有人性化的设计等,且全新的柔软界面,看起来非常的舒服~微软Ghost win11 正式版镜像文件介绍:1、与各种硬件设备兼容。 更好地完成用户安装并有效地使用。2、稳定使用蓝屏,系统不再兼容,更能享受无缝的系统服务。3、为

  • 雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    语言:中文版系统大小:4.75GB系统类型:

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载在系统方面技术积累雄厚深耕多年,打造了国内重装系统行业的雨林木风品牌,其系统口碑得到许多人认可,积累了广大的用户群体,雨林木风是一款稳定流畅的系统,一直以来都以用户为中心,是由雨林木风团队推出的Windows11国内镜像版,基于国内用户的习惯,做了系统性能的优化,采用了新的系统

  • 雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    语言:中文版系统大小:5.91GB系统类型:Win7

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO在系统方面技术积累雄厚深耕多年,加固了系统安全策略,雨林木风win7旗舰版系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。win7 32位旗舰装机版 v2019 05能够帮助用户们进行系统的一键安装、快速装机等,系统中的内容全面,能够为广大用户

  • 番茄花园Ghost Win7 x64 SP1稳定装机版2022年7月(64位) 高速下载

    番茄花园Ghost Win7 x64 SP1稳定装机版2022年7月(64位) 高速下载

    语言:中文版系统大小:3.91GB系统类型:Win7

    欢迎使用 番茄花园 Ghost Win7 x64 SP1 2022.07 极速装机版 专业装机版具有更安全、更稳定、更人性化等特点。集成最常用的装机软件,集成最全面的硬件驱动,精心挑选的系统维护工具,加上独有人性化的设计。是电脑城、个人、公司快速装机之首选!拥有此系统