halt 命令详解与参数实测(Ubuntu 22.04)
基于 Ubuntu 22.04(systemd 249)环境对 halt 命令的逐参数实测手册:直接执行走优雅停机(journal 判定行 Starting System Halt...)、-p 切换断电(Powering off./Reached target System Power Off)、--reboot 切换重启、-f 强制 Halting.、-w 实测不写 wtmp、-d 拦不住优雅留痕、--no-wall,以及无位置参数被 Too many arguments. 拒绝、非 root 三连报错与四命令动作切换矩阵,所有破坏性命令均真实执行并以 last -x 与 journal 双重留痕闭环验证。
halt 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 halt 的每一个参数与用法——无参数直接执行(优雅停机,journal 判定行为
Starting System Halt...)、-p切换为断电动作、--reboot切换为重启动作、-f强制执行(回显Halting.)、-w的实测表现(未产生任何 wtmp 记录)、-d拦不住优雅路径留痕、--no-wall,以及 halt 作为四命令家族中「唯一无位置参数」的语法细节、非 root 三连报错,全部命令与回显已在 Ubuntu 22.04(systemd 249)环境实测通过,其中停机类参数均真实执行并记录了主机停止前后的 wtmp 与 journal 双重证据。
一、环境信息
本文所有命令均在以下环境实测,回显逐字照抄:
- 操作系统:Ubuntu 22.04.5 LTS(
PRETTY_NAME="Ubuntu 22.04.5 LTS") - 内核:6.8.0-138-generic,x86_64 架构
- init 系统:systemd 249 (249.11-0ubuntu3.23),
systemctl is-system-running实测返回running - halt 所属软件包:systemd 249.11-0ubuntu3.23
- halt 真实身份:
/usr/sbin/halt -> /bin/systemctl符号链接(3.1 节实测确认) - 系统时区:UTC(
date输出带 UTC 后缀),下文回显中的时间均为系统本地时间 - 执行身份:root
- 演示目录:
/root/demo/halt/
💡 说明:halt 每次真实执行都会让主机停止运行,本文所有破坏性命令都真实执行过,并以停机前后的 wtmp 留痕(
last -x输出)与 journal 优雅停机序列双重证据闭环,因此部分小节的回显是「执行命令 → 主机停止 → 重新启动后查看日志」的完整闭环,读者在自己的测试机上复现时请提前保存工作内容。
二、命令概览
2.1 语法与测试数据
halt 用于停止系统运行。在 halt/reboot/poweroff 三兄弟中,halt 是唯一没有位置参数的——语法(来自实测 halt --help 首行)里连 [ARG] 都没有:
halt [OPTIONS...]
不写任何选项时,默认动作为挂起(等同 --halt):停止全部服务、卸载文件系统、停住 CPU,但不重新引导、也不请求断电。本文测试数据约定:破坏性命令均单独执行、前后用 last -x 留痕对账;非破坏性命令(-w 组合、非法参数、非 root 试探)在确认系统 running 状态下执行。
💡 技术拓展:halt 名义下的动作切换是四命令家族里最丰富的——
命令 默认动作 加 -p加 --reboothalt 挂起(Starting System Halt...) 断电(Reached target System Power Off) 重启(Reached target System Reboot) 三种结局的 journal 判定行全部实测命中,详见 3.4/3.5 节与 3.13 节动作切换矩阵。这也是 halt 与 poweroff 的本质差别:halt 是「停下来」,
halt -p才是「停下来并且断电」。
2.2 --help 全量输出(逐行照抄)
先看完整帮助,是逐参数实测的地图。以下为 halt --help 的完整实测输出:
$ halt --help
halt [OPTIONS...]
Halt the system.
Options:
--help Show this help
--halt Halt the machine
-p --poweroff Switch off the machine
--reboot Reboot the machine
-f --force Force immediate halt/power-off/reboot
-w --wtmp-only Don't halt/power-off/reboot, just write wtmp record
-d --no-wtmp Don't write wtmp record
--no-wall Don't send wall message before halt/power-off/reboot
See the halt(8) man page for details.
关键差异解读:
- 首行语法只有
[OPTIONS...]——没有 reboot/poweroff 帮助里的[ARG],实测也与帮助一致:任何位置参数都会被Too many arguments.拒绝(3.12 节); - 描述行是
Halt the system.(reboot 是 "Reboot the system.",poweroff 是 "Power off the system."),三个命令共用同一份选项表、同一份 halt(8) 手册; - 动作三选项
--halt/-p/--reboot在 halt 名义下全部实测有效(3.3/3.4/3.5 节),这一点与 reboot 名义下-p被忽略的行为(reboot 篇 3.5 节)形成鲜明对比。
2.3 版本信息
Ubuntu 22.04 的 halt 属于 systemd 软件包,实测版本信息如下:
$ systemctl --version
systemd 249 (249.11-0ubuntu3.23)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified
$ dpkg -l systemd | tail -1
ii systemd 249.11-0ubuntu3.23 amd64 system and service manager
systemctl --version 的第一行就是 halt 实际运行的版本(249.11-0ubuntu3.23)。本文各参数行为均为该版本实测结论,升级 systemd 后请以现场实测为准。
三、参数逐项实测
3.1 先确认身份:halt 是 systemctl 的符号链接
systemd 时代的 halt 不是独立二进制,而是 systemctl 的符号链接。systemctl 运行时按 argv[0](程序被调用的名字)判定要执行的动作:
ls -l /usr/sbin/shutdown /usr/sbin/reboot /usr/sbin/halt /usr/sbin/poweroff
实测回显:
$ ls -l /usr/sbin/shutdown /usr/sbin/reboot /usr/sbin/halt /usr/sbin/poweroff
lrwxrwxrwx 1 root root 14 Oct 12 07:44 /usr/sbin/halt -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Oct 12 07:44 /usr/sbin/poweroff -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Oct 12 07:44 /usr/sbin/reboot -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Oct 12 07:44 /usr/sbin/shutdown -> /bin/systemctl
💡 要点:
- 四个命令全部指向
/bin/systemctl,本质上是同一套代码的不同入口;因此 2.2 节halt --help显示的是 halt 专属的短帮助——systemctl 按 argv[0] 识别了身份; dpkg -S /usr/sbin/halt可确认归属(输出systemd: /usr/sbin/halt),排障时可用于区分是 systemd 包还是 SysV 兼容包提供的同名命令。
3.2 无参数直接执行:优雅停机(真实执行)
halt 不带参数走完整的优雅停机流程,最终执行挂起动作(停止系统、不断电、不重新引导)。命令本身没有输出,回车后系统随即开始停机:
halt
执行后主机停止运行。在无可控电源域的运行环境里,系统停止后会被外部重新拉起(效果等同重启,但执行路径可由 journal 严格区分)。恢复后用 last -x 查看留痕(节选头部):
$ last -x | head -6
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 09:54 still running
reboot system boot 6.8.0-138-generi Fri Oct 16 09:54 still running
shutdown system down 6.8.0-138-generi Fri Oct 16 09:54 - 09:54 (00:00)
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 09:54 - 09:54 (00:00)
reboot system boot 6.8.0-138-generi Fri Oct 16 09:54 - 09:54 (00:00)
shutdown system down 6.8.0-138-generi Fri Oct 16 09:54 - 09:54 (00:00)
journal 中本次优雅停机的收尾序列(节选):
Oct 16 09:54:42 b8307d66e0c6 systemd[1]: Stopped Remount Root and Kernel File Systems.
Oct 16 09:54:42 b8307d66e0c6 systemd[1]: Reached target System Shutdown.
Oct 16 09:54:42 b8307d66e0c6 systemd[1]: Reached target Late Shutdown Services.
Oct 16 09:54:42 b8307d66e0c6 systemd[1]: Starting System Halt...
Oct 16 09:54:42 b8307d66e0c6 systemd[1]: Shutting down.
Oct 16 09:54:42 b8307d66e0c6 systemd-journald[23]: Journal stopped
💡 要点:
- 判定行是
Starting System Halt...——这是 systemd-halt.service(挂起动作的收尾单元)启动的证据,与 poweroff 的systemd-poweroff.service(3.4 节对照)在 journal 中可严格区分;挂起路径只有 Starting 没有 Finished 行,因为它是停机序列的最后一个单元,完成回执来不及写入 journal; - wtmp 层面与优雅关机/重启长得一样(有
shutdown system down结束标记 + 新 boot 记录)——区分「这次停机到底是什么动作」必须看 journal 判定行(Q3 有速查表); - 优雅路径下 wtmp 的 down 记录由 systemd-update-utmp 服务写入(journal 序列中的
Stopped Record System Boot/Shutdown in UTMP.),这解释了 3.8 节-d为什么拦不住它。
3.3 --halt:显式指定挂起动作
--halt 是默认动作的显式写法。用 -w 组合做非破坏性的解析验证(-w 的实测行为见 3.7 节:不会停机、也不写记录):
systemctl is-system-running
halt --halt -w
echo "退出码=$?"
systemctl is-system-running
实测回显:
$ systemctl is-system-running
running
$ halt --halt -w
$ echo "退出码=$?"
halt --halt -w 退出码=0
$ systemctl is-system-running
running
-f 强制路径的动词回显可交叉印证动作类型(poweroff --halt -f 打印 Halting.,说明 --halt 长选项在任何名义下都无条件生效,详见 poweroff 篇 3.3 节)。
💡 要点:halt --halt 与无参数 halt 是同一动作的两种写法;在脚本中显式写出 --halt 可读性更好,也避免读者把 halt 误当成「关机断电」。
3.4 -p:切换为断电动作(真实执行)
-p --poweroff 把 halt 的动作切换为关机断电。真实执行:
halt -p
journal 中的结局判定行(时间戳 10:07:32 对应本次 halt -p):
Oct 16 10:07:32 b8307d66e0c6 systemd[1]: systemd-poweroff.service: Deactivated successfully.
Oct 16 10:07:32 b8307d66e0c6 systemd[1]: Finished System Power Off.
Oct 16 10:07:32 b8307d66e0c6 systemd[1]: Reached target System Power Off.
systemd-poweroff.service 与 Reached target System Power Off. 表明动作已切换为断电(对照 3.2 节 halt 直接执行的 Starting System Halt...)。配合 -f 强制路径的动词回显交叉确认:
$ halt -p -f
Powering off.
💡 要点:
halt -p是「经典 SysV 习惯」(很多老运维用halt -p当关机用),在本环境 systemd 249 上实测有效:journal 走的是 poweroff 收尾序列;- wtmp 层面
halt -p与halt直接执行无法区分(都是 down 记录),journal 判定行是唯一区分点; - 与 reboot 名义下
-p被忽略(reboot 篇 3.5 节实测reboot -p仍重启)不同,halt 名义下-p真实生效——同一家族、同一参数、不同名义、不同命运,这是四命令家族最值得记住的一个角落。
3.5 --reboot:切换为重启动作(真实执行)
--reboot 把 halt 的动作切换为重启。真实执行:
halt --reboot
journal 中的结局判定行(时间戳 10:04:23 对应本次 halt --reboot):
Oct 16 10:04:23 b8307d66e0c6 systemd[1]: systemd-reboot.service: Deactivated successfully.
Oct 16 10:04:23 b8307d66e0c6 systemd[1]: Finished System Reboot.
Oct 16 10:04:23 b8307d66e0c6 systemd[1]: Reached target System Reboot.
恢复后 wtmp 留痕(节选头部):
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 10:04 still running
reboot system boot 6.8.0-138-generi Fri Oct 16 10:04 still running
shutdown system down 6.8.0-138-generi Fri Oct 16 10:04 - 10:04 (00:00)
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 10:04 - 10:04 (00:00)
reboot system boot 6.8.0-138-generi Fri Oct 16 10:04 - 10:04 (00:00)
shutdown system down 6.8.0-138-generi Fri Oct 16 10:04 - 10:04 (00:00)
💡 要点:
Finished System Reboot.+Reached target System Reboot.证明 halt --reboot 走了完整的重启序列,效果与reboot命令一致(对照 reboot 篇 3.2 节);- 至此 halt 名义下的三个动作(挂起/断电/重启)全部实测命中,动作切换矩阵见 3.13 节。
3.6 -f:强制立即停机(跳过优雅停机)
-f --force 跳过 systemd 的优雅停机流程,由 systemctl 自己直接执行停机系统调用,先打印一行动词再执行:
$ halt -f
Halting.
执行后主机立即停止,不等待服务停止。与 reboot -f 同理(reboot 篇 3.6 节),wtmp 中不产生新的 shutdown system down 记录,且旧 boot 的 reboot system boot 记录会停留在 still running 状态形成「僵尸 boot 记录」(判定方法与示例见 reboot 篇 3.6 节,两者行为一致)。
💡 要点:
Halting.由 systemctl 自己打印(强制路径不再经过 systemd 停机序列),同族动词还有Rebooting.(reboot -f)与Powering off.(poweroff -f),三个动词正好对应三种动作,是验证动作解析结果的直接手段;-f的代价清单与 reboot 篇 3.6 节相同:服务无优雅关闭、文件系统缓存未回写、wtmp 无 down 记录且留僵尸 boot 记录;- halt -f 停机后主机不再自动引导(这是 halt 与 poweroff -f 在物理机上的区别:一个停在断电前的内核停止态、一个直接断电),需要现场干预才能恢复。
3.7 -w:声称「只写 wtmp」,实测什么都没写(真实踩坑#1)
帮助文本声称 -w --wtmp-only 是 "Don't halt/power-off/reboot, just write wtmp record"。前半句实测成立(确实不停机),后半句实测不成立:
$ last -x reboot
reboot system boot 6.8.0-138-generi Thu Oct 15 18:07 still running
wtmp begins Thu Oct 15 18:07:39 2026
$ halt -w
$ echo "退出码=$?"
退出码=0
$ last -x reboot
reboot system boot 6.8.0-138-generi Thu Oct 15 18:07 still running
wtmp begins Thu Oct 15 18:07:39 2026
$ systemctl is-system-running
running
md5 直接对比文件字节(另一次验证):
$ md5sum /var/log/wtmp
46978aa93d26974e9218682781c94ae4 /var/log/wtmp
$ halt -w
$ md5sum /var/log/wtmp
46978aa93d26974e9218682781c94ae4 /var/log/wtmp
💡 要点:
- 在 systemd 249 上,
halt -w退出码 0、无输出、系统保持运行,但/var/log/wtmp一个字节都没变——reboot -w与poweroff -w同样实测无变化(md5 完全一致),三个名义行为相同; -w因此成为 halt 家族里唯一绝对非破坏的参数:即使与-f组合系统也不会停止,可当参数解析探针用;- 老教程中「-w 用于构造 wtmp 记录」的说法在本版本上不成立,写运维文档时不要照抄。
3.8 -d:声称「不写 wtmp」,优雅路径拦不住(真实踩坑#2)
帮助文本声称 -d --no-wtmp 是 "Don't write wtmp record"。真实执行 halt -d 后恢复,查看头部:
$ last -x | head -5
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 10:56 still running
reboot system boot 6.8.0-138-generi Fri Oct 16 10:56 still running
shutdown system down 6.8.0-138-generi Fri Oct 16 10:56 - 10:56 (00:00)
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 10:56 - 10:56 (00:00)
reboot system boot 6.8.0-138-generi Fri Oct 16 10:56 - 10:56 (00:00)
第 3 行的 shutdown system down 10:56 - 10:56 正是本次 halt -d 结束的那个 boot 的留痕——-d 没有拦住它。journal 同时确认动作本身正常:
Oct 16 10:56:46 b8307d66e0c6 systemd[1]: Starting System Halt...
💡 要点:
- 原因同 reboot 篇 3.8 节:优雅路径的 wtmp 留痕由停机序列中的 systemd-update-utmp 服务写入,
-d是 systemctl 进程自己的开关,管不到停机序列里的写入者; -d对-f强制路径也无效——但强制路径本来就什么都不写(3.6 节),无处可拦;- 结论:想「悄悄停机、不留 down 记录」在本版本上做不到,
last -x审计记录是可信的。
3.9 --no-wall:不发广播消息(优雅路径实测)
--no-wall 只控制停机前的 wall 广播,不影响停机动作本身。真实执行:
halt --no-wall
journal 确认动作正常完成(时间戳 10:07:51 对应本次执行):
Oct 16 10:07:51 b8307d66e0c6 systemd[1]: Starting System Halt...
💡 要点:
- halt 没有接受自定义消息正文的位置参数(2.1 节,任何位置参数都会被拒绝),系统广播的固定文案由 logind 在调度时生成,
--no-wall的作用就是连这条固定广播也省去; - 本实测环境无交互登录会话,广播文案差异不作为本文的实测结论;在多用户生产机上,摘掉广播等于用户毫无预警被踢线,维护窗口外请勿使用;
- 需要自定义广播内容的停机,用
shutdown -h +m '消息'(shutdown 篇 3.9 节已实测 wall 广播机制)。
3.10 非 root 执行:logind 拒绝 + 报错三连
普通用户执行 halt 会被拒绝。实测(演示用户 pwuser 通过 useradd -m -s /bin/bash pwuser 创建):
$ su - pwuser -c "halt"
Failed to halt system via logind: Access denied
Failed to open initctl fifo: Permission denied
Failed to talk to init daemon.
$ echo "退出码=$?"
退出码=1
reboot 与 poweroff 在非 root 下的报错形态完全相同,仅第一行动词不同(Failed to reboot system via logind: Access denied / Failed to power off system via logind: Access denied),退出码同为 1。测试后清理演示用户(userdel -r pwuser)。
💡 要点:
- 三连报错暴露了 systemctl 的降级尝试链:先问 systemd-logind(被 polkit 拒绝)→ 再尝试 SysV 兼容的
/run/initctlfifo → 最后直接和 init daemon 通话——三层全被拒后才放弃; - 与 shutdown 的非 root 报错形态不同(shutdown 报
Failed to call ScheduleShutdown in logind, no action will be taken: Access denied,走「调度」方法)——halt 走「立即执行」方法; - 授权普通用户停机的正道是 polkit 规则或
sudo /usr/sbin/halt。
3.11 非法选项:unrecognized option 退出码 1
$ halt --bogus
halt: unrecognized option '--bogus'
$ echo "退出码=$?"
退出码=1
💡 要点:报错前缀是 halt:(argv[0] 名义),退出码 1。结合 3.10 节,非 root 与参数错误都是退出码 1,脚本里要区分二者只能看报错文本。
3.12 位置参数:被 Too many arguments. 拒绝
halt 的帮助语法里没有 [ARG],实测任何位置参数都会被拒绝。用 -w 组合保证非破坏:
$ halt -w bar
Too many arguments.
$ echo "ARG bar 退出码=$?"
ARG bar 退出码=1
对照 reboot 名义下 reboot -w foo 静默接受(退出码 0,见 reboot 篇 3.12 节),poweroff 同样拒绝(poweroff -w baz → Too many arguments.)。
💡 要点:
- 三个命令的帮助首行写法不同(halt 无
[ARG]、reboot/poweroff 有[ARG]),实测接受度与帮助完全对应——halt 严格无位置参数,reboot 独静默接受一个,poweroff 拒绝; - 这个差异是「同一套代码、按 argv[0] 分派后各自再校验」的产物,遇到「帮助相同、行为不同」的情况,以实测为准。
3.13 技术拓展:四命令对比与动作切换矩阵
reboot/halt/poweroff/shutdown 四命令的完整实测对照(本表所有结论均出自本环境实测,细节见各篇对应小节):
| 维度 | shutdown | reboot | halt | poweroff |
|---|---|---|---|---|
| 帮助语法 | [OPTIONS...] [TIME] [WALL...] | [OPTIONS...] [ARG] | [OPTIONS...] | [OPTIONS...] [ARG] |
| 默认动作 | 关机断电(延时 1 分钟) | 重启 | 挂起 | 关机断电 |
| 延时/定时 | ✓ now/+m/hh:mm | ✗ | ✗ | ✗ |
| 自定义广播消息 | ✓ [WALL...] | ✗ | ✗ | ✗ |
-c 取消计划 | ✓ | ✗ | ✗ | ✗ |
-k 假广播 | ✓ | ✗ | ✗ | ✗ |
-f 强制动词回显 | ✗(无此参数) | Rebooting. | Halting. | Powering off. |
-w 只写 wtmp | ✗(无此参数) | 有参数,实测未写任何记录 | 同左 | 同左 |
-d 不写 wtmp | ✗(无此参数) | 有参数,优雅路径拦不住 | 同左 | 同左 |
--no-wall | ✓ | ✓ | ✓ | ✓ |
| 非 root 报错第一行 | Failed to call ScheduleShutdown in logind... | Failed to reboot system via logind... | Failed to halt system via logind... | Failed to power off system via logind... |
| 优雅路径 journal 结局 | Reached target System Power Off.(默认)/Reached target System Reboot.(-r)/Starting System Halt...(-H) | Reached target System Reboot. | Starting System Halt... | Reached target System Power Off. |
动作切换矩阵(名义 × 选项,括号内为 journal/动词回显证据):
| 名义 \ 选项 | (无选项) | --halt | -p | --reboot |
|---|---|---|---|---|
reboot | 重启(Reached target System Reboot) | 挂起(Starting System Halt...) | 仍重启(-p 被忽略,Rebooting.) | 重启(-w 组合解析验证 rc=0) |
halt | 挂起(Starting System Halt...) | 挂起(同默认) | 断电(Reached target System Power Off) | 重启(Reached target System Reboot) |
poweroff | 断电(Reached target System Power Off) | 挂起(Starting System Halt...) | 断电(同默认,Powering off.) | 重启(强制路径动词 Rebooting.) |
💡 要点:
- halt 是动作切换的「枢纽」名义:
-p与--reboot在 halt 名义下全部实测生效,矩阵中 halt 行三个动作都有 journal 级证据; - 长选项
--halt/--reboot无条件生效;短选项-p只在 halt/poweroff 名义下有意义,在 reboot 名义下被忽略; - 生产建议一句话版:定时/带广播/可取消的重启用
shutdown -r,立即重启用reboot,关机用poweroff,halt留给真正需要「停在那里」的物理机场景。
四、实战示例
4.1 停机后用 wtmp 对账(审计闭环)
停机维护后第一时间对账。停机前先记下当前 boot 时间:
who -b
halt
实测回显(停机前,who -b 显示当时 boot 时间为 11:12):
system boot Oct 16 11:12
--- 执行 halt ---
恢复后执行:
who -b
last -x | head -5
last -x shutdown | head -2
实测回显:
$ who -b
system boot Oct 16 11:14
$ last -x | head -5
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 11:14 still running
reboot system boot 6.8.0-138-generi Fri Oct 16 11:14 still running
shutdown system down 6.8.0-138-generi Fri Oct 16 11:14 - 11:14 (00:00)
runlevel (to lvl 5) 6.8.0-138-generi Fri Oct 16 11:12 - 11:14 (00:01)
reboot system boot 6.8.0-138-generi Fri Oct 16 11:12 - 11:14 (00:01)
$ last -x shutdown | head -2
shutdown system down 6.8.0-138-generi Fri Oct 16 11:14 - 11:14 (00:00)
shutdown system down 6.8.0-138-generi Fri Oct 16 11:12 - 11:12 (00:00)
解读:
who -b从 11:12 更新为 11:14,last -x里旧 boot 记录闭合为11:12 - 11:14 (00:01)——本次 halt 的停机与重新启动链路完整;last -x shutdown最新一条11:14 - 11:14是本次优雅停机写下的 down 记录,有它说明走的是优雅路径(强制路径不会产生 down 记录,见 3.6 节);- journal 侧可用判定行确认动作类型:本次执行对应的 journal 收尾行是
Starting System Halt...(挂起)。
4.2 需要断电时:halt -p 还是 poweroff
两者在本环境的 journal 判定行相同(都是 Reached target System Power Off.),结局一致。选择建议:日常关机语义用 poweroff(名字即意图,不依赖参数);习惯 SysV 风格的脚本里 halt -p 亦实测有效。若需要「停住但不断电」(如更换硬件前让主机停在安全状态),用不带参数的 halt——注意这只在能物理接触主机的场景有意义。
4.3 系统无响应时的强制停机
优雅路径无响应时,halt -f 是最后手段:
$ halt -f
Halting.
执行后主机立即停止。代价清单见 3.6 节:服务无优雅关闭、wtmp 无 down 记录且旧 boot 记录留僵尸态。恢复后建议立即检查文件系统日志与 fsck 计划。
4.4 脚本中安全停机的前置检查
#!/bin/bash
# 前置检查 1:系统处于可停机状态
state=$(systemctl is-system-running)
if [ "$state" != "running" ]; then
echo "系统状态异常($state),拒绝停机" >&2
exit 1
fi
# 前置检查 2:权限试探(借用 -w 组合,非破坏)
halt -w
if [ $? -ne 0 ]; then
echo "停机权限不足(非 root 或 polkit 拒绝)" >&2
exit 1
fi
halt
实测依据:systemctl is-system-running 在本环境返回 running(一、环境信息);halt -w 非破坏(3.7 节)且权限不足/参数错误均为退出码 1(3.10/3.11 节)。
五、注意事项与常见问题
Q1:halt 执行完,系统是「停在那里」还是关机了?
看运行环境。halt 的语义是挂起:停服务、停 CPU,但不请求断电。在能控制电源的物理机上,halt 后主机保持通电、风扇照转,需要现场按电源键;在本实测环境这类无可控电源域的托管运行环境里,系统停止后由外部重新拉起,最终表现与关机无异——但 journal 判定行(Starting System Halt...)能证明走的确实是挂起路径(3.2 节)。想「停下来并且断电」请用 halt -p 或 poweroff。
Q2:halt 与 shutdown -H now 有什么区别?
结局完全相同:journal 都收尾于 Starting System Halt...(两者实测命中同一判定行)。区别在入口能力:shutdown 支持 [TIME] 延时、自定义广播消息、-c 取消、会写 /run/nologin 拦截后续登录;halt 一概没有,回车即停。多人使用的生产机选 shutdown -H,单人现场维护用 halt。
Q3:wtmp 里 halt 的 down 记录和 reboot/poweroff 长得一模一样,怎么区分动作?
wtmp 只记录「发生过优雅停机」,不记录动作类型;区分动作必须看 journal 收尾判定行:
| journal 收尾行 | 结论 |
|---|---|
Finished System Reboot. + Reached target System Reboot. | 优雅重启 |
Starting System Halt...(无 Finished 行) | 优雅挂起 |
Finished System Power Off. + Reached target System Power Off. | 优雅断电 |
只有 Shutting down. 前无上述任何行 | 强制路径(-f),无优雅序列 |
Q4:为什么 halt -w 没有生成 wtmp 记录?
实测(last -x 前后对比 + /var/log/wtmp md5 前后一致)确认 249 上该参数什么都没写。-w 的价值仅剩「绝对非破坏」:配合任何选项都不会停机(含 -f),可当参数解析探针使用(4.4 节)。老教程中「-w 用于构造 wtmp 记录」的说法在本版本上不成立。
Q5:halt -p 执行后为什么 wtmp 记录与 halt 一样?
因为 wtmp 的 down 记录只由优雅停机序列写入(systemd-update-utmp 服务),不区分最终动作是挂起还是断电。halt 与 halt -p 在 wtmp 层面不可区分,journal 判定行(Starting System Halt... 对 Reached target System Power Off.)才是区分点。审计脚本如需区分动作类型,请采集 journal 而非 wtmp。
六、参考链接
- halt/reboot/poweroff 共用手册:
man halt(man 8 halt;本实测环境未安装 man 手册页,可在装有 man-db 的系统上查看) - systemctl 手册:
man systemctl(man 1 systemctl) - reboot(2) 系统调用:https://man7.org/linux/man-pages/man2/reboot.2.html
- systemd 官方文档(systemctl / systemd-halt.service / systemd-poweroff.service):https://www.freedesktop.org/wiki/Software/systemd/
- Ubuntu systemd 软件包页(249.11-0ubuntu3.23 源码与变更记录):https://launchpad.net/ubuntu/+source/systemd
- 同族姊妹篇:《shutdown 命令详解与参数实测(Ubuntu 22.04)》《reboot 命令详解与参数实测(Ubuntu 22.04)》《poweroff 命令详解与参数实测(Ubuntu 22.04)》