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 双重留痕闭环验证。

Linux命令Linux系统UbuntuUbuntu 22.04命令行systemd2026/10/16

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加 --reboot
halt挂起(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.

关键差异解读:

  1. 首行语法只有 [OPTIONS...]——没有 reboot/poweroff 帮助里的 [ARG],实测也与帮助一致:任何位置参数都会被 Too many arguments. 拒绝(3.12 节);
  2. 描述行是 Halt the system.(reboot 是 "Reboot the system.",poweroff 是 "Power off the system."),三个命令共用同一份选项表、同一份 halt(8) 手册;
  3. 动作三选项 --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

💡 要点:

  1. 四个命令全部指向 /bin/systemctl,本质上是同一套代码的不同入口;因此 2.2 节 halt --help 显示的是 halt 专属的短帮助——systemctl 按 argv[0] 识别了身份;
  2. 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

💡 要点:

  1. 判定行是 Starting System Halt...——这是 systemd-halt.service(挂起动作的收尾单元)启动的证据,与 poweroff 的 systemd-poweroff.service(3.4 节对照)在 journal 中可严格区分;挂起路径只有 Starting 没有 Finished 行,因为它是停机序列的最后一个单元,完成回执来不及写入 journal;
  2. wtmp 层面与优雅关机/重启长得一样(有 shutdown system down 结束标记 + 新 boot 记录)——区分「这次停机到底是什么动作」必须看 journal 判定行(Q3 有速查表);
  3. 优雅路径下 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.

💡 要点:

  1. halt -p 是「经典 SysV 习惯」(很多老运维用 halt -p 当关机用),在本环境 systemd 249 上实测有效:journal 走的是 poweroff 收尾序列;
  2. wtmp 层面 halt -p 与 halt 直接执行无法区分(都是 down 记录),journal 判定行是唯一区分点;
  3. 与 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)

💡 要点:

  1. Finished System Reboot. + Reached target System Reboot. 证明 halt --reboot 走了完整的重启序列,效果与 reboot 命令一致(对照 reboot 篇 3.2 节);
  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 节,两者行为一致)。

💡 要点:

  1. Halting. 由 systemctl 自己打印(强制路径不再经过 systemd 停机序列),同族动词还有 Rebooting.(reboot -f)与 Powering off.(poweroff -f),三个动词正好对应三种动作,是验证动作解析结果的直接手段;
  2. -f 的代价清单与 reboot 篇 3.6 节相同:服务无优雅关闭、文件系统缓存未回写、wtmp 无 down 记录且留僵尸 boot 记录;
  3. 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

💡 要点:

  1. 在 systemd 249 上,halt -w 退出码 0、无输出、系统保持运行,但 /var/log/wtmp 一个字节都没变——reboot -w 与 poweroff -w 同样实测无变化(md5 完全一致),三个名义行为相同;
  2. -w 因此成为 halt 家族里唯一绝对非破坏的参数:即使与 -f 组合系统也不会停止,可当参数解析探针用;
  3. 老教程中「-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...

💡 要点:

  1. 原因同 reboot 篇 3.8 节:优雅路径的 wtmp 留痕由停机序列中的 systemd-update-utmp 服务写入,-d 是 systemctl 进程自己的开关,管不到停机序列里的写入者;
  2. -d 对 -f 强制路径也无效——但强制路径本来就什么都不写(3.6 节),无处可拦;
  3. 结论:想「悄悄停机、不留 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...

💡 要点:

  1. halt 没有接受自定义消息正文的位置参数(2.1 节,任何位置参数都会被拒绝),系统广播的固定文案由 logind 在调度时生成,--no-wall 的作用就是连这条固定广播也省去;
  2. 本实测环境无交互登录会话,广播文案差异不作为本文的实测结论;在多用户生产机上,摘掉广播等于用户毫无预警被踢线,维护窗口外请勿使用;
  3. 需要自定义广播内容的停机,用 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)。

💡 要点:

  1. 三连报错暴露了 systemctl 的降级尝试链:先问 systemd-logind(被 polkit 拒绝)→ 再尝试 SysV 兼容的 /run/initctl fifo → 最后直接和 init daemon 通话——三层全被拒后才放弃;
  2. 与 shutdown 的非 root 报错形态不同(shutdown 报 Failed to call ScheduleShutdown in logind, no action will be taken: Access denied,走「调度」方法)——halt 走「立即执行」方法;
  3. 授权普通用户停机的正道是 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.)。

💡 要点:

  1. 三个命令的帮助首行写法不同(halt 无 [ARG]、reboot/poweroff 有 [ARG]),实测接受度与帮助完全对应——halt 严格无位置参数,reboot 独静默接受一个,poweroff 拒绝;
  2. 这个差异是「同一套代码、按 argv[0] 分派后各自再校验」的产物,遇到「帮助相同、行为不同」的情况,以实测为准。

3.13 技术拓展:四命令对比与动作切换矩阵

reboot/halt/poweroff/shutdown 四命令的完整实测对照(本表所有结论均出自本环境实测,细节见各篇对应小节):

维度shutdownreboothaltpoweroff
帮助语法[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.)

💡 要点:

  1. halt 是动作切换的「枢纽」名义:-p 与 --reboot 在 halt 名义下全部实测生效,矩阵中 halt 行三个动作都有 journal 级证据;
  2. 长选项 --halt/--reboot 无条件生效;短选项 -p 只在 halt/poweroff 名义下有意义,在 reboot 名义下被忽略;
  3. 生产建议一句话版:定时/带广播/可取消的重启用 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)

解读:

  1. who -b 从 11:12 更新为 11:14,last -x 里旧 boot 记录闭合为 11:12 - 11:14 (00:01)——本次 halt 的停机与重新启动链路完整;
  2. last -x shutdown 最新一条 11:14 - 11:14 是本次优雅停机写下的 down 记录,有它说明走的是优雅路径(强制路径不会产生 down 记录,见 3.6 节);
  3. 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)》