您现在的位置是:首页 > 文章详情

处理一次系统假死工作纪实

日期:2020-08-19点击:439

本文转载自微信公众号「相遇Linux」,作者JeffXie 。转载本文请联系相遇Linux公众号。 

最近碰到客户反馈一个问题,系统hang了,ssh登录不上,但是可以ping通,通过串口登录进去之后,敲有些命令会卡住,查看cpu负载内存都很正常,手动触发kdump之后看不出死锁/softlockup/hardlockup等异常状态.而且重要的是已经影响到客户几十亿的业务了。

我能拿到的只有客户提供的vmcore,为了生活而奔波的人儿赶紧分析起来:

系统(SUSE 11SP1)

#crash ./vmcore ./vmlinux-2.6.32.59-0.19-default

./vmlinux-2.6.32.59-0.19-default.gz

crash>foreach IN bt > inbt

任意找到一个IN(可中断睡眠)的进程 12813 查看堆栈:

 
  1. crash>  bt 12813 
  2.  
  3. PID:12813  TASK: ffff880262eda140  CPU: 8  COMMAND: "sshd" 
  4.  #0 [ffff880f98e1ba58] schedule atffffffff8139d2a4 
  5.  #1 [ffff880f98e1bb10] schedule_timeout atffffffff8139d935 
  6.  #2 [ffff880f98e1bba0] unix_wait_for_peer atffffffff81376e27 
  7.  #3 [ffff880f98e1bc00] unix_dgram_sendmsg atffffffff813785c2 
  8.  #4 [ffff880f98e1bcb0] sock_sendmsg atffffffff812e8ddc 
  9.  #5 [ffff880f98e1be50] sys_sendto atffffffff812e9318 
  10.  #6 [ffff880f98e1bf80] system_call_fastpath atffffffff81002f7b 

汇编unix_dgram_sendmsg()

 
  1. crash>dis unix_dgram_sendmsg 
  2. ... 
  3. 2410xffffffff813785b7 <unix_dgram_sendmsg+1143>:   mov   %r13,%rsi 
  4. 2420xffffffff813785ba <unix_dgram_sendmsg+1146>:   mov   %rbp,%rdi  (key1) 
  5.  rdi代表unix_wait_for_peer函数的第一个参数 
  6. 2430xffffffff813785bd <unix_dgram_sendmsg+1149>:   callq 0xffffffff81376da0 <unix_wait_for_peer> 

进程12813 unix_wait_for_peer() 函数的堆栈数据:

 
  1. crash>rd -SS ffff880f98e1bba0 -e ffff880f98e1bc00 
  2. ffff880f98e1bba0:  unix_wait_for_peer+135 0000000000000001 
  3. ffff880f98e1bbb0:  [ffff880262eda140:task_struct]autoremove_wake_function 
  4. ffff880f98e1bbc0:  ffff88021ea8bbc0 ffff880238315bc0 
  5. ffff880f98e1bbd0:  memcpy_fromiovec+87 [ffff880238514980:UNIX] 
  6. ffff880f98e1bbe0:  [ffff880238514c30:UNIX] [ffff880238514980:UNIX] 
  7. ffff880f98e1bbf0:  [ffff880ff708b630:UNIX] 7fffffffffffffff 

汇编unix_wait_for_peer()

 
  1. crash>dis unix_wait_for_peer 
  2. 0xffffffff81376da0<unix_wait_for_peer>:       sub    $0x58,%rsp 
  3. 0xffffffff81376da4<unix_wait_for_peer+4>:     mov    $0x1,%edx 
  4. 0xffffffff81376da9<unix_wait_for_peer+9>:     mov    %r13,0x50(%rsp) 
  5. 0xffffffff81376dae<unix_wait_for_peer+14>:    lea    0x2b8(%rdi),%r13 
  6. 0xffffffff81376db5<unix_wait_for_peer+21>:    mov    %rbx,0x38(%rsp) 
  7. 0xffffffff81376dba<unix_wait_for_peer+26>:    mov    %gs:0xa580,%rax 
  8. 0xffffffff81376dc3<unix_wait_for_peer+35>:    mov    %rax,0x8(%rsp) 
  9. 0xffffffff81376dc8<unix_wait_for_peer+40>:    lea    0x18(%rsp),%rax 
  10. 0xffffffff81376dcd<unix_wait_for_peer+45>:    mov    %rbp,0x40(%rsp) (key2) 

rbp压入堆栈(0x58-0x40)处,正好是unix_wait_for_peer堆栈中ffff880f98e1bbe8处,即( [ffff880238514980:UNIX])

 
  1. 0xffffffff81376dd2<unix_wait_for_peer+50>:    mov    %rdi,%rbx 
  2. 0xffffffff81376dd5<unix_wait_for_peer+53>:    mov    %rsi,%rbp 
  3. 0xffffffff81376dd8<unix_wait_for_peer+56>:    mov    %r13,%rdi 

查看unix_wait_for_peer()函数源码:

 
  1. 1005static long unix_wait_for_peer(struct sock *other, long timeo) (key3) 
  2. 1006{ 
  3. 1007         struct unix_sock *u = unix_sk(other); 
  4. 1008         int sched; 
  5. 1009         DEFINE_WAIT(wait); 
  6. 1011   prepare_to_wait_exclusive(&u->peer_wait, &wait,TASK_INTERRUPTIBLE); 
  7. .. 
  8. 1019         if (sched) 
  9. 1020                 timeo =schedule_timeout(timeo); 
  10. 1021 
  11. 1022         finish_wait(&u->peer_wait,&wait); 
  12. 1023         return timeo; 
  13. 1024} 

根据s(key1)(key2)(key3)可以知道12813进程在等待unix_sock(ffff880238514980)

 
  1. crash>struct unix_sock ffff880238514980 | grep peer_wait -A 10 
  2.  
  3.   peer_wait = { 
  4.     lock = { 
  5.       raw_lock = { 
  6.         slock = 3369322707 
  7.       } 
  8.     }, 
  9.     task_list = { 
  10.       next = 0xffff880173427bc0, 
  11.       prev = 0xffff8801877a7bc0 
  12.     } 
  13.   } 

查询出这个unix_sock是系统中的/dev/log文件(由syslog-ng创建,系统中大量需要记录log的进程需要通过这个unix_sock与syslog-ng通信,可以参考mansyslog-ng 和/etc/syslog-ng/syslog-ng.conf 配置文件)

 
  1. crash>struct unix_sock ffff880238514980 
  2. ... 
  3. dentry= 0xffff880e7634b9c0, 
  4. ... 
  5. crash>struct dentry 0xffff880e7634b9c0 
  6. ... 
  7.  name = 0xffff880e7634ba60 "log" 
  8.  ...  

遍历这个unix_sock的所有等待队列,

说明有645个进程正在等待这个unix_sock(ffff880238514980/dev/log)

 
  1. crash>list __wait_queue.task_list  -s__wait_queue.private -H 0xffff880173427bc0 | grep -i private | wc -l 
  2. 645 

所有等待unix_sock的进程重定向到一个wait_unix_sock_process文件

 
  1. crash>list __wait_queue.task_list  -s__wait_queue.private -H 0xffff880173427bc0 | grep -i private  > wait_unix_sock_process 

查询所有的sshd进程

 
  1. crash>ps | grep sshd 
  2.   7097     1   6  ffff880244cae5c0  IN  0.0   54088   1392 sshd 
  3.   12813  7097   8  ffff880262eda140  IN  0.0   60148   2900 sshd 
  4.   19055  7097   2  ffff880ff74c4200  IN  0.0   60148   2900 sshd 
  5.   21642  7097   1  ffff880262fb4340  IN  0.0   60148   2904 sshd 
  6.   21958  7097   1  ffff880ffab501c0  IN  0.0   60148   2900 sshd 
  7.   22459   7097  6  ffff880ff1ed4100  IN  0.0  121052  10272 sshd 
  8.   22476 22459   0  ffff88022d11a500  IN  0.0  121352   4552 sshd 
  9.   23334  7097   2  ffff880174b04640  IN  0.0   60148   2900 sshd 

sshd进程大部分都在wait_unix_sock_process文件中,所以ssh登录之后会卡住

查看syslog-ng进程堆栈

 
  1. crash>bt 15232 
  2. PID:15232  TASK: ffff8801aba90680  CPU: 6  COMMAND: "syslog-ng" 
  3.  #0 [ffff88021ea8ba58] schedule atffffffff8139d2a4 
  4.  #1 [ffff88021ea8bb10] schedule_timeout atffffffff8139d935 
  5.  #2 [ffff88021ea8bba0] unix_wait_for_peer atffffffff81376e27 
  6.  #3 [ffff88021ea8bc00] unix_dgram_sendmsg atffffffff813785c2 
  7.  #4 [ffff88021ea8bcb0] sock_sendmsg atffffffff812e8ddc 
  8.  #5 [ffff88021ea8be50] sys_sendto atffffffff812e9318 
  9.  #6 [ffff88021ea8bf80] system_call_fastpath atffffffff81002f7b 

查看 unix_wait_for_peer()堆栈数据:

 
  1. crash>rd -SS ffff88021ea8bba0 -e ffff88021ea8bc00 
  2. ffff88021ea8bba0:  unix_wait_for_peer+135 0000000000000001 
  3. ffff88021ea8bbb0:  [ffff8801aba90680:task_struct]autoremove_wake_function 
  4. ffff88021ea8bbc0:  ffff880fce8dfbc0 ffff880f98e1bbc0 
  5. ffff88021ea8bbd0:  memcpy_fromiovec+87 [ffff880238514980:UNIX] 
  6. ffff88021ea8bbe0:  [ffff880238514c30:UNIX][ffff880238514980:UNIX] (key4) 
  7. ffff88021ea8bbf0:  [ffff88104c1c3930:UNIX] 7fffffffffffffff 

由(key4)可知syslog-ng也是在等待ffff880238514980 unix_sock

所以系统中大量的进程,包括sshd cron等其他的645个进程都在等待unix_sock(/dev/log)(/dev/log由syslog-ng创建),syslog-ng卡住在等这个unix_sock之后,系统中大量的进程都会卡住,包括sshd cron进程等. 但是syslog-ng为什么卡住从vmcore根本看不出来,很可能进程在用户层锁住了.

通过查看客户系统中最近安装的软件发现,他们最近安装了两个定制软件,卸载之后系统恢复正常。

 
  1. # /bin/rpm -qa --last 
  2. CARKpam-11.01-1.19                    Tue Jun  9 22:49:22 2020 
  3. CARKaim-11.01-1.5                       Tue Jun  9 22:38:48 2020 
原文链接:http://os.51cto.com/art/202008/624201.htm
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章