最近,有一台Linux服务器出现了不可控的局面,由于umount磁盘操作的失效,导致相关进程都陷入了D状态里,一般情况下最好的解决办法就是重启大法了。
- 进程陷入D状态无外乎就是因为外部原因造成的,例如等待磁盘的IO、网络的IO……
- 即便你使用kill -9也是无济于事的……因为进程已经陷进去了,无法响应你的SIGKILL。
理所当然的,我果断采取了reboot -f的操作,让人意想不到的是,连reboot自身也陷进去了,失去响应。
- reboot -f的区别在于直接通知init重启信号,而跳过一系列的killall、umount操作
下面这是当时保存的现场画面。
当时的情景如下:
- 使用systemctl关闭docker服务(docker是在vdb上的)
- systemd(init)连带卡死
- 尝试remount vdb卡死
- reboot -f因systemd连带卡死
通过systemctl查看joblist,基本都因为systemd的原因全部处于waiting状态,导致systemd一直处于cpu的消耗状态。
JOB UNIT TYPE STATE
4044 session-295.scope start waiting
3924 session-275.scope start waiting
3702 session-238.scope start waiting
6779 session-750.scope start waiting
4020 session-291.scope start waiting
6917 session-773.scope start waiting
6347 session-678.scope start waiting
7199 session-820.scope start waiting
5795 session-586.scope start waiting
......
如果人在现场,很简单,按下reset按钮就好。可人不在现场,那还怎么强制重启这台服务器呢?
- systemd(init)虽然是1号进程,但是在它之上还有操作系统的最底层界面——内核。
- 就好比中控台坏掉了,但是我们还可以直接接线至主机,直接进行操控。
那么我的目的是重启,想办法通知内核就是最直接的办法。
linux内核有一个功能,叫System request或者称之为SysRq,它的功能就如主机箱上的按钮面板一样,是内核层面的最终操控办法。
首先,SysRq的开关在/proc/sys/kernel/sysrq中,默认情况下是限制功能的16,要使用所有功能需要置为1。
0 - disable sysrq completely
1 - enable all functions of sysrq
>bitmask of allowed sysrq functions (see below for detailed function description):
2 - enable control of console logging level
4 - enable control of keyboard (SAK, unraw)
8 - enable debugging dumps of processes etc.
16 - enable sync command
32 - enable remount read-only
64 - enable signalling of processes (term, kill, oom-kill)
128 - allow reboot/poweroff
256 - allow nicing of all RT tasks
- 需要临时开启,置为1即可:echo 1 > /proc/sys/kernel/sysrq
- 需要长期开启则写入配置文件:sysctl -w kernel.sysrq=1
然后,发送重启指令b到SysRq触发器上,将直接触发内核的重启。
echo b > /proc/sysrq-trigger
(这个重启将直接调用核心的reboot指令,所有进程将没有任何保存数据的机会,内存中的数据将立即全部丢失)
最后,耐心等待系统的重新启动即可。