你有没有遇到过这种情况:在终端里输入了sudo shutdown now,屏幕上日志飞快滚动,最后一切归于黑暗,风扇也慢慢停转,你很自然地认为这台 Ubuntu 机器已经关机了。但我在几年的实践中发现,这个结论经常下得太早。有些机器屏幕黑了但其实卡在某个环节里;有些机器跑到机箱前一看,电源指示灯明明还亮着;更麻烦的是远程服务器,你根本看不到它的物理状态,执行完关机命令之后只能在网线另一头干等。“如何查看Ubuntu是否真的关机了”这个问题,看起来像是新手才会问的,实际上不少运维老手也会被它绊一下。这篇文章我会从硬件观察、网络探测、系统日志三个方向,把“判断关机”这件事拆清楚,最后还会分享几个我实际踩过的案例,以及一套可以直接带走的探测脚本。不管你是刚接触 Linux 的学生,还是天天跟服务器打交道的维护者,看完之后至少不会再被“假关机”忽悠住。
1. “关机”为什么值得怀疑:先搞清楚问题的真实场景
1.1 本地电脑上的关机错觉
先说最简单的情况,就是你在自己面前操作一台 Ubuntu 台式机。执行关机命令后,屏幕确实黑掉了,主机似乎也安静了,但这里最容易出现误判。第一个坑是屏幕黑不等于主机断电,显示器进入“无信号”状态和系统真正关闭之间,可能隔着好几秒甚至几十秒;第二个坑是电源灯还亮着,这并不一定意味着系统还在运行,很多主板上那颗灯其实是在模拟“待机电源”,只要有交流电它就是亮的。
我在自己机器上就犯过这个错:屏幕黑下去之后,我下意识伸手去按电源键想强制断电,结果系统明明还在进行最后的文件系统同步,好端端的正常关机被我硬生生弄成了掉电。后来开机时系统出现了文件系统检查,虽然没丢数据,但那次教训让我记住了:本地环境判断关机,至少要同时具备“屏幕无信号”“风扇完全停止”“电源状态灯进入待机或熄灭”这三个现象,缺一个都别急着下结论。
1.2 远程服务器场景下的关机难题
远程维护服务器的时候,情况更棘手。你通过 SSH 登陆上去执行了sudo poweroff,然后 SSH 连接神奇地断开,你可能会觉得这就是关机成功了。但在很多时长不等的维护过程里,我见过下面这些后续:
- SSH 连接断开,但几分钟后又能 ping 通了,说明机器其实重启了,或者根本没关。
- SSH 连接断开,网络层彻底不通,你以为关机成功,结果到了机房一看,机器在 POST 界面停住,原来之前只是内核崩溃后自动重启。
- 执行关机命令后系统进入了一个“僵死”状态,服务全部停了,但机器既没关机也没重启,网络自然也断了,但你如果亲自过去按一下电源键,系统其实还能救回来。
远程环境的本质问题是:你没法用眼睛和耳朵去感知硬件状态,只能依赖网络探测和系统日志。所以后面章节里的排查方法和脚本,重点也会放在远程场景,因为你没法奢望每次都能跑到机房去看灯。
1.3 关机、挂起、休眠三种状态的本质区别
“如何确认真的关机”之前,先得明确“关机”不是什么。Ubuntu 现在的默认行为里,有三种容易混淆的状态:
- 关机(poweroff):系统停止所有服务,卸载文件系统,调用硬件断电指令,内存掉电,所有程序终止。这是唯一一种可以安全拔掉电源线之后重新开机的状态。
- 挂起(suspend):把 CPU 停下来,内存保持通电以保证数据不丢,整机进入极低功耗状态,网络通常会断开,但是电源灯往往还亮着。很多用户按一下电源键,系统默认做的是挂起,不是关机。
- 休眠(hibernate):把内存内容写入磁盘,然后完全断电,看起来像关机,但开机时系统会从磁盘恢复内存镜像。休眠和关机的最大区别是下次开机会恢复到休眠前的工作界面。
这三种状态如果分不清,就很容易出现“我明明关机了,为什么机器还这么烫”“我关机了但重新打开,所有程序都还在”之类的困惑。判断是不是真的关机,本质上就是从电源、网络、日志三个维度去排除“挂起”“休眠”“重启”这几种干扰项。
2. 用“三路检查”确认系统确实进入了关机流程
2.1 第一路:电源与硬件状态观察
物理层面能观察到的信息,优先级最高。这里不是让你只看灯,而是把观察拆成几个小项:
- 电源指示灯:关机和挂起的区别通常就在这里。关机后大多数机器的电源灯会完全熄灭,或者是极慢的呼吸闪烁;挂起状态下电源灯一般是常亮或者规律闪烁。但这里有个反直觉的细节——某些主板在关机后仍然会保留一颗“待机指示灯”,它只代表电源管理芯片还有 +5V standby 供电,和操作系统是否停机没有关系。所以你先要弄清楚你主板上的灯是哪一颗,建议翻一眼说明书,或者做一次实验:正常关机后记住哪个灯亮、哪个灯灭,下次再遇见时就有参照了。
- 风扇:CPU 风扇和电源风扇是判断关机的可靠指标,因为 Linux 系统真正关闭后,主板 PWM 风扇控制信号会消失,风扇应该完全停转。但要注意一种特殊情况:如果机箱风扇是直接接电源而不是接主板风扇接口的,那么它关机后依然会转,因为 12V 供电还通着。这种风扇不能作为判断依据,却常常成为误判来源。
- 机箱震动:这是最朴素的指标,把手指贴在机箱侧板上,关机后几秒到十几秒内应该感觉不到任何由风扇或硬盘引起的震动。如果断电后还有震动,说明某个部件还在工作。
本地场景根据这三项基本就能判断。如果三项都显示“已关机”,你就放心了;只要有一项异常,比如风扇一直转或灯一直亮着,那就说明系统大概率卡在了关机流程里,需要用后面的日志手段去看为什么会卡住。
2.2 第二路:网络探测——远程确认最可靠的手段
远程判断关机,最常用的手段是ping和端口探测。但这里有几个容易被误解的点,我展开详细说一下:
ping探测的是 ICMP 回显请求,它反映的是内核网络协议栈是否在运行。如果长时间 ping 不通,说明目标机器的网络栈没有响应,这通常意味着关机或网络层面断开了。但“ping 不通”这件事本身也可能由防火墙、交换机端口、无线信号问题导致,所以不能把它当成铁证。反过来,ping通了,也不代表系统没有关机——某些机器可能正在重启过程中,或者网络设备还有响应。
端口探测比 ping 更接近“应用层状态”。比如 SSH 默认监听在 22 端口,如果ping不通但 22 端口还能连上,这只能说明机器一定还活着;如果ping不通且 22 端口也连接被拒绝,那基本可以判定目标系统已经不可用。我个人的习惯是两者结合:连续数次ping不通,再尝试一次 TCP 连接 22 端口,如果都失败,再结合其他线索下结论。
要特别提醒一点:不要只看一次结果就断定关机。远程环境里网络抖动太常见了,丢一两个包就下结论,十有八九会误判。合理做法是连续探测多次,比如每隔 5 秒一次,连续 3 到 5 次均无响应才认为“不可达”。
2.3 第三路:系统日志与状态命令的交叉验证
系统日志是唯一能“回顾”关机过程的证据。如果你在执行关机前还能开个终端,或者关机失败后还能进系统,下面这几个命令可以派上大用场:
who -b:显示系统最近一次启动时间。uptime -s:和上面类似,能看到当前这次启动的开始时间。last -x shutdown:查看历史关机记录。它会列出正常关机的行,如果显示shutdown且不是reboot,说明有一次正常关机。last -x reboot:查看历史重启记录。如果你执行的是关机,这里却冒出了一个 reboot,那说明系统在关机流程里发生了重启。journalctl --list-boots:systemd 会为每次启动周期分配一个 boot id,这个命令能列出所有可追溯的启动周期以及对应的时间段。查看最后一个 boot 的结束时间是否突而不是正常关机,能帮你判断上次关机有没有走完整流程。/proc/uptime:第一列是系统从本次启动到现在运行的秒数。如果你怀疑机器刚才重启过,一算时间就能确认。
这些命令的巧妙之处在于,它们不只是告诉你“现在是不是关机了”,还能告诉你“上次是不是正常关机”。比如last -x里没有出现正常的 shutdown 记录,而上一次启动时间又比预期早了一大截,那基本说明上一次是异常掉电。
3. 深入 systemd 关机链路:为什么有些关机“不彻底”
3.1 systemd 的关机目标链在做什么
Ubuntu 16.04 之后就全面使用 systemd 了,现在新一点的 Ubuntu 版本里,执行poweroff、shutdown now、systemctl poweroff最终都会进入同一套处理流程。
从原理上说,systemd 会把系统拉向一个特殊的poweroff.target。在这个目标下,它要经历几个主要阶段:
- 向所有仍在运行的 systemd 单元发送 SIGTERM 终止信号。
- 等待各个服务在
TimeoutStopSec规定的时限内优雅退出,默认值通常被设置为 90 秒,但很多服务自己也定义了自己的超时时间。 - 对于超时仍未停止的进程,systemd 再发送 SIGKILL 强制终止。
- 同步文件系统数据,卸载磁盘和所有挂载点。
- 调用内核的
reboot系统调用,并传入RB_POWER_OFF标志。 - 内核负责向 ACPI 固件发送断电指令,最后由固件切断电源。
这个流程里,任何一个环节出问题都会导致“看起来像关机,实际没切断电源”的假象。最常见的卡点在第一阶段,有些服务收到了 SIGTERM 却不退出,或者某个进程派生了一堆子进程导致 systemd 判定它还在运行,这时候其他服务也跟着等,整个关机时间被拉得很长。
3.2 卡在服务停止阶段的排查方法
遇到机器关机特别慢,或者明明执行了掉电但电源一直不断,你先别急着物理断电阻塞,优先尝试这些手段:
- 在另一个终端(如果还连得上)执行
journalctl -f,实时查看关机时的日志,它会明确告诉你哪个服务在超时等待。 - 检查
/run/systemd/shutdown/scheduled文件,这里面记录了延迟关机的信息和调用者,能帮你确认关机是否正确被调度。 - 如果系统里配置了远程挂载(NFS、CIFS 卷),关机时最典型的问题是挂载点卸载不掉,导致系统一直重试。这通常在
/etc/fstab里能看到,卸载不掉的网络卷会让关机流程卡上很长时间。 - 检查是否有服务的
KillMode被设置为none。这个配置对 systemd 来说是“不要主动杀掉该服务”,如果某个脚本或服务这样设置了又常驻不退,那 systemd 就会一直等它,哪怕它已经没有实际任务了。
我遇到过最夸张的一次,一个自定义服务因为KillMode=none且不停在写日志,导致关机流程整整跑了 20 分钟才最终断电。从那以后我凡是看到KillMode=none就会多长一个心眼。
3.3 ACPI 断电指令传不到硬件时的表现
到了内核调用reboot()之后,按理说固件会立刻切断主电源,但这步也不是百分百可靠的。部分主板和整机产品在 ACPI 电源管理上存在缺陷,内核已经发出了断电指令,固件却没有真正切断主电源,于是系统其实已经“死了”,但机器仍然通电,风扇继续转,指示灯也亮着。
这种状态下你无论怎么等待都不会有变化,因为操作系统已经退出,没有任何程序能再控制硬件。但从外部看起来,你可能觉得“它一定还没关机,因为风扇还在转”。判断这种状态有一种简单技巧:看键盘状态灯。如果 Num Lock 灯和 Caps Lock 灯按下去没有反应,说明系统已经不再处理中断,明显处于死亡状态;再看风扇一直全速转或转速不下降,那基本可以断定是 ACPI 断电失败。这时候你再物理断电,不会造成任何文件系统损伤,因为内核早就把该写盘的内容写完了。
反过来,如果键盘灯按下去还有响应,说明内核还活着,只是卡在了用户态关机流程,这时候物理断电就要格外小心,尽量给它时间自行结束。
4. 我排查过的几个真实案例:从现象到结论的思路
4.1 案例一:远程机器“温度还在走”——其实是数据延迟
有一次我在某机房维护一批 Ubuntu 服务器,执行完关机命令后,所有机器在几分钟内都从网络里消失了,唯独一台机器让同事不安:从那台机器的带外管理界面看,CPU 温度传感器仍然显示 67 摄氏度,而且数值还在轻微波动。
同事的第一反应是“这台机器根本没关机,温度还在变”。我让他先别急着下机柜把机器断电,而是调出带外管理界面里的“系统电源状态”字段,结果写的是“已关机/待机”。这个现象的关键是:带外管理芯片是独立于操作系统的,它有自己的一套传感器采样电路,CPU 插槽旁边的温度传感器只要还在通电就会持续采样,温度数值当然会波动。它跟 Linux 操作系统有没有关机,一点关系都没有。
后来我们约定了一个规则:远程判断是否关机,一律以网络可达性为主、带外电源状态为辅,温度、功耗这类传感器数据只参考,不当作判断依据。这个案例也说明,看起来最客观的硬件数据,放到远程场景里也可能骗人。
4.2 案例二:按了关机键屏幕黑了,但电源灯一直亮
这就是我自己的台式机。某次执行shutdown -h now之后屏幕黑下去,可机箱前面板的电源灯一直常亮,我第一反应是关机失败,准备按电源键强制断电。幸好当时手慢了一点,多观察了十来秒,发现那颗灯从常亮慢慢变成了非常暗的呼吸状态。我打开机箱侧板看了一下,机箱灯从常亮变成呼吸的那一瞬间,CPU 风扇和电源风扇正好同时停转,整机瞬间安静。
后来查资料才知道,该品牌主板在系统关机后会进入“待机电源状态”,前面板那颗灯的呼吸效果由主板直接驱动,和操作系统毫无关系。强制断电反而会打断系统正常的文件系统同步,得不偿失。所以“电源灯亮”这个现象太宽泛了,必须先分清是待机指示灯还是运行状态灯,最好再配合风扇停转来判断。
4.3 案例三:ping 通但 SSH 连不上,到底关了没有
还有一次远程维护一台 Ubuntu 服务器,执行sudo poweroff后过了几分钟,机房那边反馈“网络又通了”,我用笔记本 ping 了一下,确实通了,但 SSH 怎么都连不上。我的第一反应是机器关机失败,又自动开机了。
用另一种思路绕过去之后发现,系统确实是重启了,但每次启动到很早就死掉,连 SSH 服务都没起来,所以 ping 通但 SSH 不通。后来看带外控制台的串口日志,看到内核 panic 信息,原来是关机过程中驱动触发了内核崩溃,导致自动重启失败并卡死在启动早期。这类情况,光靠“ping 通”去判断是否关机,会得出完全相反的结论,必须结合端口探测和启动日志一起看。
5. 确认关机后才发现的问题:开机时间告诉我们的事
5.1 从启动时间判断是否为异常掉电
很多时候我们根本来不及在关机现场做检查,只有在下次开机后才能发现“上次关机其实没有正常完成”。此时最有用的信息是启动时间。
举个例子,如果 journalctl 里显示上次启动是在早上 10:00,而你明明在晚上 19:00 操作过关机,那说明这台机器在这段时间里可能经历了一次异常掉电,或者有人偷偷重启过。如果last -x reboot里没有记录,而last -x shutdown也是空的,通常意味着系统不是正常关机流程结束的,而是直接断电。
5.2 硬件通电记录与系统时钟的差异
另一个隐蔽线索是系统时间和硬件时间之间的偏差。正常关机时,Ubuntu 的 systemd-timesyncd 或充电管理逻辑会把准确的系统时间写回主板 RTC 芯片。如果系统突然断电,RTC 往往还停留在上一次同步的时间点上。
所以下次开机后,如果发现系统时间在开机后校准之前有明显偏差(比如 BIOS 里显示的时间和上次真正关机的时间差了好几个小时),这也能侧面证明上次不是一次干净的关机。虽然现在很多机器都用 NTP 自动校时,掩盖了这种痕迹,但在没有外网时间的纯内网环境里依然很有效。
5.3 一套顺手的最小化关机检查脚本
最后送你一套我一直在用的最小化检查脚本。它运行在“另一台机器”上,用来持续探测目标主机是否已经关机。原理很简单:先ping,如果 ping 不通再试着连 SSH 端口,连续多次都不通则判定关机。
#!/bin/bash # 用法: ./confirm_poweroff.sh <目标IP> [探测次数=12] [间隔秒=5] TARGET="$1" COUNT="${2:-12}" INTERVAL="${3:-5}" FAIL=0 echo "开始探测 $TARGET,每 ${INTERVAL} 秒一次,最多 ${COUNT} 次" for ((i=1; i<=COUNT; i++)); do if ping -c 1 -W 2 "$TARGET" > /dev/null 2>&1; then echo "[$i] 目标仍然可达 (ping 通了)" FAIL=0 else # ping 不通并不一定是关机,再试着连接 22 端口 if timeout 2 bash -c "echo > /dev/tcp/$TARGET/22" 2>/dev/null; then echo "[$i] ping 不通,但 SSH 端口仍开放,系统必然活着" FAIL=0 else echo "[$i] ping 不通,SSH 端口也不可连,可能已关机" FAIL=$((FAIL+1)) if [ "$FAIL" -ge 3 ]; then echo "连续 3 次确认,目标极有可能已经关机" exit 0 fi fi fi sleep "$INTERVAL" done echo "探测结束,未达到连续 3 次失败,目标状态不明确"为什么特意要求“连续 3 次”?因为网络环境里丢一个包太常见了,一次失败说明不了问题。连续多次都失败,才算可靠信号。脚本里的timeout 2是给 TCP 探测限定 2 秒,避免目标主机不可达时端口探测还把流程拖得很慢。你也可以把 22 换成你实际关心的端口,比如 443、3306 等,原理都一样。
我在实际维护里,通常会把脚本跑起来后就去忙别的,等它打出“极有可能已经关机”这一行,再安排后续操作,大大降低了误判率。但要记住,脚本只能给你提供证据,真正的“确定”还是来自多路证据交叉验证,尤其涉及到文件系统安全和需要切断电源的场合,宁可在机房多等一分钟,也别手贱提前断电。
说到底,判断 Ubuntu 是否真的关机了,核心就是一句话:不要相信单一信号。屏幕黑了要再看风扇,电源灯亮着要分清楚是哪颗灯,远程机器 ping 不通了还要尝试端口,端口不通了还要回看日志确认有没有 reboot 记录。这听起来繁琐,但只要你按这套思路养成习惯,假关机带来的烦恼基本就能一次解决干净。