RHEL服务器在执行shutdown或reboot命令后,屏幕最后停在类似“Watching system buttons”或者“A stop job is running for...”的界面上,甚至直接显示systemd-shutdown的字样后彻底没了动静,只能靠长按电源键强制断电。这类关机卡死问题看似随机出现,其实背后都有明确的触发原因。本文围绕systemd-shutdown的工作机制展开,帮你把这个问题彻底搞清楚。

一、先弄懂systemd的关机流程
要排查卡死问题,首先要知道正常关机时系统到底做了什么。当用户执行shutdown命令后,systemd会按依赖关系反向停止所有systemd单元,先停普通服务,再停socket和target,最后卸载文件系统、断开存储设备。当主流程结束后,systemd会启动一个极简的替换进程systemd-shutdown,它运行在内存盘之外,负责做最后的收尾工作:向所有剩余进程发送SIGTERM和SIGKILL、卸载所有文件系统、关闭swap、分离DM设备(如LVM、加密卷),最后调用reboot系统调用完成重启或关机。
关键点在于systemd-shutdown执行时PID为1,此时日志系统、udev等基础设施都已经停止,所以它无法再往journald写日志,只能把信息直接打印到控制台。如果你在屏幕上看到类似下面这样的输出,说明系统已经进入最后的收尾阶段:
Unmounted /boot. Unounted /run. [ OK ] Reached target Shutdown. systemd-shutdown[1]: Sending SIGTERM to remaining processes... systemd-shutdown[1]: Waiting for processes: top, sleep
上面最后两行是最有价值的线索。“Waiting for processes”后面列出的进程就是卡住关机的元凶。systemd-shutdown会等待这些进程退出,如果它们对SIGKILL都无动于衷(通常是因为进程处于不可中断的D状态,正在等待某个永远不会返回的IO操作),系统就会永远停在这里。这就是屏幕上卡死的直接原因。
二、定位卡死的具体原因
1. 从控制台输出和日志入手
如果机器还能通过串口或iLO、IDRAC等带外管理口捕获控制台输出,先把卡死时的完整屏幕信息保存下来。同时在上一次启动后检查日志:
journalctl -b -1 -e journalctl -b -1 | grep -iE "timeout|stop job|killed"
重点关注两类记录:一是被超时杀掉的stop job,日志中会出现“Killed with signal SIGKILL”字样;二是关机阶段各服务的停止耗时。如果journalctl -b -1查不到内容,说明日志还没来得及落盘系统就卡死了,可以在内核启动参数里加上systemd.debug-shutdown=1,让systemd-shutdown在最后阶段输出详细调试信息到控制台。
2. 常见的几类触发场景
第一类是NFS或CIFS等网络文件系统挂载点。网络服务先于挂载点被停止,卸载NFS时客户端会尝试向已经失联的服务端发起请求,进程进入D状态,谁也杀不动。如果业务里用到了autofs或NFS,这是首要怀疑对象。
第二类是存储相关的驱动或多路径软件。某些厂商的HBA驱动、 multipath在收到停止请求时如果有IO残留,会阻塞卸载流程。RHEL7升级到RHEL8/9的过程中,这类驱动兼容问题也时有发生。
第三类是服务停止超时累积。默认情况下每个服务的停止超时是90秒,如果多个服务接连超时,用户看到的表象是“关机特别慢”,等耐心耗尽强制断电,就可能造成文件系统损坏,进而引发更严重的启动问题。
三、针对性解决方案
1. 处理网络文件系统卡死
对于NFS挂载点,最稳妥的做法是强制关机时不等待网络卸载。编辑/etc/systemd/system.conf,确保以下参数生效,并单独处理NFS:
# /etc/systemd/system.conf DefaultTimeoutStopSec=15s # 对NFS挂载单独设置软超时,挂载选项加上 soft,timeo=50,retrans=2 mount -t nfs -o soft,timeo=50,retrans=2 server:/export/data /mnt/data
另外可以创建一个关机前执行的service,在网络停止之前主动umount -l -f所有NFS挂载点。懒卸载(-l)会立即把挂载点从挂载表里摘除,阻塞的IO留待以后处理,这样后续流程就不会被卡住。
2. 调整超时和加快速关机
如果定位到的是普通服务超时,除了全局缩短DefaultTimeoutStopSec,还可以针对单个服务写drop-in配置:
mkdir -p /etc/systemd/system/httpd.service.d cat > /etc/systemd/system/httpd.service.d/timeout.conf << 'EOF' [Service] TimeoutStopSec=10s EOF systemctl daemon-reload
想让关机阶段更彻底,还可以在内核参数中启用快速关机:
# /etc/default/grub 的 GRUB_CMDLINE_LINUX 中追加 systemd.shutdown-timeout=30s # 重新生成grub配置 grub2-mkconfig -o /boot/grub2/grub.cfg
3. 强制断电后的善后处理
多次强制断电后,建议开机后手动检查文件系统。ext4/xfs通常能靠日志恢复,但LVM元数据或RAID一致性需要额外确认,可以用xfs_repair -n做只读检查,用lvs命令确认所有逻辑卷状态为a开头(available)。如果有lv报告为partial,说明物理卷上有数据不一致,必须先处理存储层再做其他操作。
四、预防性配置建议
排查解决问题之后,建议固化几条运维规范。第一,所有NFS挂载一律使用soft模式或配置独立的umount服务,不要依赖关机流程自动处理。第二,部署带外管理(iDRAC、iLO、IPMI),确保卡死时能远程抓取控制台和执行硬复位,这一点在机房远端托管场景尤其重要。第三,定期做一次重启演练,很多卡死问题平时不关机根本暴露不出来,等到打补丁必须重启时才炸出来,风险就大了。
还可以写一个简单的巡检脚本,统计每个服务的停止耗时,把历史数据留存下来,一旦某天某个服务的停止时间突然变长,就能提前介入:
#!/bin/bash
# 统计各服务上次停止耗时(毫秒)
systemctl list-units --type=service --all --no-legend | \
awk '{print $1}' | while read svc; do
t=$(systemctl show -p InactiveExitTimestampMonotonic "$svc" 2>/dev/null)
echo "$svc $t"
done总的来说,systemd-shutdown卡死绝大多数情况都卡在D状态进程和无法卸载的文件系统上。只要掌握了“看控制台输出、查上一次启动日志、逐个排除网络存储和服务超时”这套流程,这类故障基本都能在半小时内定位到根因。养成规范配置的习惯之后,问题复发的概率会大大降低。
systemd-shutdownRHEL关机卡死systemd故障排查修改时间:2026-09-05 06:40:40