poweroff 命令详解与参数实测(Ubuntu 22.04)

基于 Ubuntu 22.04(systemd 249)环境对 poweroff 命令的逐参数实测手册:直接执行优雅关机断电(journal 判定行 Reached target System Power Off)、--halt 切换挂起、--reboot 切换重启(强制路径动词 Rebooting.)、-p 默认动作的显式写法、-f 强制 Powering off.、-w 实测不写 wtmp、-d 拦不住优雅留痕、--no-wall,以及 who -b 分钟级分辨率在同分钟两次停机时的盲区、非 root 三连报错与 [ARG] 位置参数拒绝行为,所有破坏性命令均真实执行并以 last -x 与 journal 双重留痕闭环验证。

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

poweroff 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 poweroff 的每一个参数与用法——无参数直接执行(优雅关机断电,journal 判定行为 Finished System Power Off. + Reached target System Power Off.)、--halt 切换为挂起动作、--reboot 切换为重启动作、-p 默认动作的显式写法、-f 强制执行(回显 Powering off.)、-w 的实测表现(未产生任何 wtmp 记录)、-d 拦不住优雅路径留痕、--no-wall,以及帮助里带 [ARG] 但位置参数被 Too many arguments. 拒绝、非 root 三连报错、who -b 分钟级分辨率在同分钟两次停机时的盲区,全部命令与回显已在 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
  • poweroff 所属软件包:systemd 249.11-0ubuntu3.23
  • poweroff 真实身份:/usr/sbin/poweroff -> /bin/systemctl 符号链接(3.1 节实测确认)
  • 系统时区:UTC(date 输出带 UTC 后缀),下文回显中的时间均为系统本地时间
  • 执行身份:root
  • 演示目录:/root/demo/poweroff/

💡 说明:poweroff 每次真实执行都会让主机停止运行,本文所有破坏性命令都真实执行过,并以停机前后的 wtmp 留痕(last -x 输出)与 journal 优雅停机序列双重证据闭环,因此部分小节的回显是「执行命令 → 主机停止 → 重新启动后查看日志」的完整闭环,读者在自己的测试机上复现时请提前保存工作内容。

二、命令概览

2.1 语法与测试数据

poweroff 用于关机并请求断电。语法(来自实测 poweroff --help 首行):

poweroff [OPTIONS...] [ARG]

帮助里有 [ARG] 位置参数——但实测任何位置参数都会被 Too many arguments. 拒绝(3.12 节),与 reboot 的「静默接受一个」(reboot 篇 3.12 节)不同。不写任何选项时,默认动作为关机断电。本文测试数据约定:破坏性命令均单独执行、前后用 last -x 留痕对账;非破坏性命令(-w 组合、非法参数、非 root 试探)在确认系统 running 状态下执行。

💡 技术拓展:poweroff 名义下的动作切换——

命令默认动作加 --halt加 --reboot
poweroff断电(Reached target System Power Off)挂起(Starting System Halt...)重启(强制路径动词 Rebooting.)

与 halt 不同,poweroff 名义下「切走」默认动作要靠长选项;短选项 -p 在这里只是默认动作的显式写法(3.4 节)。三种结局的 journal 判定行详见 3.3/3.5 节与 3.13 节动作切换矩阵。

2.2 --help 全量输出(逐行照抄)

先看完整帮助,是逐参数实测的地图。以下为 poweroff --help 的完整实测输出:

$ poweroff --help
poweroff [OPTIONS...] [ARG]

Power off 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. 首行语法带 [ARG],但实测位置参数会被 Too many arguments. 拒绝(3.12 节)——帮助文本与行为不一致的又一个实例;
  2. 描述行是 Power off the system.(reboot 是 "Reboot the system.",halt 是 "Halt the system."),三个命令共用同一份选项表、同一份 halt(8) 手册;
  3. -p --poweroff 的描述是 "Switch off the machine"——在 poweroff 名义下它与默认动作等价(3.4 节)。

2.3 版本信息

Ubuntu 22.04 的 poweroff 属于 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 的第一行就是 poweroff 实际运行的版本(249.11-0ubuntu3.23)。本文各参数行为均为该版本实测结论,升级 systemd 后请以现场实测为准。

三、参数逐项实测

3.1 先确认身份:poweroff 是 systemctl 的符号链接

systemd 时代的 poweroff 不是独立二进制,而是 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 节 poweroff --help 显示的是 poweroff 专属的短帮助——systemctl 按 argv[0] 识别了身份;
  2. dpkg -S /usr/sbin/poweroff 可确认归属(输出 systemd: /usr/sbin/poweroff),排障时可用于区分是 systemd 包还是 SysV 兼容包提供的同名命令。

3.2 无参数直接执行:优雅关机断电(真实执行)

poweroff 不带参数走完整的优雅停机流程,最终执行断电动作(停止系统并请求切断电源)。命令本身没有输出,回车后系统随即开始停机:

poweroff

执行后主机停止运行。在无可控电源域的运行环境里,系统停止后会被外部重新拉起(效果等同重启,但执行路径可由 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:48 b8307d66e0c6 systemd[1]: Stopped Remount Root and Kernel File Systems.
Oct 16 09:54:48 b8307d66e0c6 systemd[1]: Reached target System Shutdown.
Oct 16 09:54:48 b8307d66e0c6 systemd[1]: Reached target Late Shutdown Services.
Oct 16 09:54:48 b8307d66e0c6 systemd[1]: systemd-poweroff.service: Deactivated successfully.
Oct 16 09:54:48 b8307d66e0c6 systemd[1]: Finished System Power Off.
Oct 16 09:54:48 b8307d66e0c6 systemd[1]: Reached target System Power Off.
Oct 16 09:54:48 b8307d66e0c6 systemd[1]: Shutting down.
Oct 16 09:54:48 b8307d66e0c6 systemd-journald[23]: Journal stopped

💡 要点:

  1. 判定行是 systemd-poweroff.service: Deactivated successfully. → Finished System Power Off. → Reached target System Power Off.——断电动作有完整的收尾三连,与 halt 的 Starting System Halt...(只有 Starting、无 Finished 行,见 halt 篇 3.2 节)在 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 把 poweroff 的动作从断电切换为挂起。真实执行:

poweroff --halt

journal 中的结局判定行(时间戳 10:07:25 对应本次 poweroff --halt):

Oct 16 10:07:25 b8307d66e0c6 systemd[1]: Starting System Halt...

Starting System Halt...(挂起收尾单元 systemd-halt.service 启动)证明动作已从断电切换为挂起。配合 -f 强制路径的动词回显交叉确认:

$ poweroff --halt -f
Halting.

💡 要点:

  1. poweroff --halt 的结局与 halt 直接执行完全一致(journal 同为 Starting System Halt...),说明动作由解析层决定、与入口名义无关;
  2. -f 组合打印的动词是 Halting. 而不是 Powering off.——强制路径的动词按解析后的动作打印,是验证动作切换最直接的手段;
  3. 想表达「停住但不断电」,写 halt 或 poweroff --halt 都行,但前者名字与动作一致、可读性更好。

3.4 -p:默认动作的显式写法

-p --poweroff 在 poweroff 名义下只是默认动作(断电)的显式形式。用 -f 组合的动词回显验证(-p 不改变解析结果,动词与默认动作一致):

$ poweroff -p -f
Powering off.

💡 要点:

  1. poweroff -p 与 poweroff 是同一动作的两种写法,journal 结局同为 Reached target System Power Off.(3.2 节);
  2. 与 halt 名义下 -p 真实切换动作(halt 篇 3.4 节)不同——同一个 -p,在 halt 是「切换器」、在 poweroff 是「回声」;
  3. 与 reboot 名义下 -p 被忽略(reboot 篇 3.5 节实测 reboot -p 仍重启)也不同——同一家族、同一参数、三种命运,完整地图见 3.13 节动作切换矩阵。

3.5 --reboot:切换为重启动作

--reboot 把 poweroff 的动作切换为重启。本节用 -f 强制路径验证动作切换(强制路径的动词回显由 systemctl 按解析后动作打印,是最直接的证据):

$ poweroff --reboot -f
Rebooting.

用 -w 组合做非破坏性的解析验证(-w 的实测行为见 3.7 节:不会停机、也不写记录):

$ systemctl is-system-running
running
$ poweroff --reboot -w
$ echo "退出码=$?"
poweroff --reboot -w 退出码=0
$ systemctl is-system-running
running

💡 要点:

  1. 动词 Rebooting. 证明 --reboot 在 poweroff 名义下真实生效,动作已切换为重启;
  2. 长选项 --reboot 无条件生效(对照短选项 -p 的名义依赖),这与 reboot --halt(reboot 篇 3.4 节)、halt --reboot(halt 篇 3.5 节)的实测结论一致;
  3. 优雅路径的 journal 证据见 halt --reboot(halt 篇 3.5 节,Reached target System Reboot.)——两者共用同一份动作解析代码,解析结果相同;本节以强制路径动词 + -w 解析验证双重留痕。

3.6 -f:强制立即断电(跳过优雅停机)

-f --force 跳过 systemd 的优雅停机流程,由 systemctl 自己直接执行停机系统调用,先打印一行动词再执行:

$ poweroff -f
Powering off.

执行后主机立即断电,不等待服务停止。真实执行前后用 last -x 对账(破坏前头 3 行 → 执行 → 恢复后头 5 行):

--- 破坏前 last -x 头 3 行 ---
runlevel (to lvl 5)   6.8.0-138-generi Fri Oct 16 10:08   still running
reboot   system boot  6.8.0-138-generi Fri Oct 16 10:08   still running
shutdown system down  6.8.0-138-generi Fri Oct 16 10:07 - 10:08  (00:00)
--- 执行 poweroff -f ---
Powering off.
--- 恢复后 last -x 头 5 行 ---
runlevel (to lvl 5)   6.8.0-138-generi Fri Oct 16 10:08   still running
reboot   system boot  6.8.0-138-generi Fri Oct 16 10:08   still running
runlevel (to lvl 5)   6.8.0-138-generi Fri Oct 16 10:08 - 10:08  (00:00)
reboot   system boot  6.8.0-138-generi Fri Oct 16 10:08   still running
shutdown system down  6.8.0-138-generi Fri Oct 16 10:07 - 10:08  (00:00)

💡 要点:

  1. Powering off. 由 systemctl 自己打印(强制路径不再经过 systemd 停机序列),同族动词还有 Rebooting.(reboot -f)与 Halting.(halt -f / poweroff --halt -f),三个动词正好对应三种动作,是验证动作解析结果的直接手段;
  2. 恢复后头部没有本次停机的 shutdown system down 记录(最新的 down 记录 10:07 - 10:08 属于上一个 boot),且第 4 行旧 boot 的 reboot system boot 10:08 停留在 still running 状态——这就是「僵尸 boot 记录」:强制路径不写 down 标记,旧 boot 记录永远闭合不上(与 reboot -f 行为一致,reboot 篇 3.6 节);
  3. -f 的代价清单与 reboot 篇 3.6 节相同:服务无优雅关闭、文件系统缓存未回写、wtmp 无 down 记录且留僵尸 boot 记录。

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
$ poweroff -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
$ poweroff -w
$ md5sum /var/log/wtmp
46978aa93d26974e9218682781c94ae4  /var/log/wtmp

💡 要点:

  1. 在 systemd 249 上,poweroff -w 退出码 0、无输出、系统保持运行,但 /var/log/wtmp 一个字节都没变——reboot -w 与 halt -w 同样实测无变化(md5 完全一致),三个名义行为相同;
  2. -w 因此成为家族里唯一绝对非破坏的参数:即使与 -f 组合系统也不会停止,可当参数解析探针用;
  3. 老教程中「-w 用于构造 wtmp 记录」的说法在本版本上不成立,写运维文档时不要照抄。

3.8 -d:声称「不写 wtmp」,优雅路径拦不住(真实踩坑#2)

帮助文本声称 -d --no-wtmp 是 "Don't write wtmp record"。真实执行 poweroff -d 后恢复,查看头部:

$ last -x | head -5
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 09:57 - 10:04  (00:06)
reboot   system boot  6.8.0-138-generi Fri Oct 16 09:57 - 10:04  (00:06)

第 3 行的 shutdown system down 10:04 - 10:04 正是本次 poweroff -d 结束的那个 boot 的留痕——-d 没有拦住它。journal 同时确认动作本身正常(时间戳 10:04:11 对应本次执行):

Oct 16 10:04:11 b8307d66e0c6 systemd[1]: systemd-poweroff.service: Deactivated successfully.
Oct 16 10:04:11 b8307d66e0c6 systemd[1]: Finished System Power Off.
Oct 16 10:04:11 b8307d66e0c6 systemd[1]: Reached target System Power Off.

💡 要点:

  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 广播,不影响停机动作本身。真实执行:

poweroff --no-wall

journal 确认动作正常完成(时间戳 10:07:57 对应本次执行):

Oct 16 10:07:57 b8307d66e0c6 systemd[1]: systemd-poweroff.service: Deactivated successfully.
Oct 16 10:07:57 b8307d66e0c6 systemd[1]: Finished System Power Off.
Oct 16 10:07:57 b8307d66e0c6 systemd[1]: Reached target System Power Off.

💡 要点:

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

3.10 非 root 执行:logind 拒绝 + 报错三连

普通用户执行 poweroff 会被拒绝。实测(演示用户 pwuser 通过 useradd -m -s /bin/bash pwuser 创建):

$ su - pwuser -c "poweroff"
Failed to power off system via logind: Access denied
Failed to open initctl fifo: Permission denied
Failed to talk to init daemon.
$ echo "退出码=$?"
退出码=1

reboot 与 halt 在非 root 下的报错形态完全相同,仅第一行动词不同(Failed to reboot system via logind: Access denied / Failed to halt 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,走「调度」方法)——poweroff 走「立即执行」方法;
  3. 授权普通用户关机的正道是 polkit 规则或 sudo poweroff。

3.11 非法选项:unrecognized option 退出码 1

$ poweroff --bogus
poweroff: unrecognized option '--bogus'
$ echo "退出码=$?"
退出码=1

💡 要点:报错前缀是 poweroff:(argv[0] 名义),退出码 1。结合 3.10 节,非 root 与参数错误都是退出码 1,脚本里要区分二者只能看报错文本。

3.12 位置参数:帮助里有 [ARG],实测被 Too many arguments. 拒绝

poweroff 的帮助语法里有 [ARG],但实测任何位置参数都会被拒绝。用 -w 组合保证非破坏:

$ poweroff -w baz
Too many arguments.
$ echo "ARG baz 退出码=$?"
ARG baz 退出码=1

对照 reboot 名义下 reboot -w foo 静默接受(退出码 0,见 reboot 篇 3.12 节),halt 同样拒绝(halt -w bar → Too many arguments.,halt 篇 3.12 节)。

💡 要点:

  1. 三个命令的帮助首行写法不同(halt 无 [ARG]、reboot/poweroff 有 [ARG]),实测接受度却与帮助不完全对应——reboot 独静默接受一个,halt/poweroff 都拒绝;poweroff 是「帮助写了 [ARG]、行为却拒绝」的那一个;
  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. poweroff 是四命令中「名字与默认动作严格对应」的一个:不带参数即断电,无需任何参数修正语义;
  2. 长选项 --halt/--reboot 无条件生效;短选项 -p 只在 halt/poweroff 名义下有意义——在 halt 是切换器、在 poweroff 是回声、在 reboot 被忽略;
  3. 生产建议一句话版:定时/带广播/可取消的关机用 shutdown -P,立即关机用 poweroff,重启用 reboot,halt 留给真正需要「停在那里」的物理机场景。

四、实战示例

4.1 关机后用 wtmp 对账(审计闭环)

关机维护后第一时间对账。关机前先记下当前 boot 时间:

who -b
poweroff

实测回显(关机前,who -b 显示当时 boot 时间为 11:14):

         system boot  Oct 16 11:14
--- 执行 poweroff ---

恢复后执行:

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:14 - 11:14  (00:00)
reboot   system boot  6.8.0-138-generi Fri Oct 16 11:14 - 11:14  (00:00)
$ 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:14 - 11:14  (00:00)

解读:

  1. 两次 who -b 显示的 boot 时间都是 11:14——本次 poweroff 与上一次停机落在同一分钟,who -b 只有分钟级分辨率,看不出变化(这是它的盲区,Q5 详述);
  2. last -x 里旧 boot 记录闭合为 11:14 - 11:14 (00:00)、新 boot 记录 still running——本次 poweroff 的停机与重新启动链路完整;
  3. last -x shutdown 头两条都是 11:14 - 11:14:第一条是本次优雅关机写下的 down 记录(走优雅路径才有,强制路径不会产生,见 3.6 节),第二条是紧邻的上一次停机留下的——同一分钟内的两次停机在 wtmp 里无法按时间区分;
  4. 区分手段在 journal:本次执行对应的收尾判定行是 Finished System Power Off. + Reached target System Power Off.(断电,11:14:50 窗口),上一次是 Starting System Halt...(挂起,11:14:44 窗口)。

4.2 立即关机的三种写法:poweroff、shutdown -P now、halt -p

三者在本环境的 journal 结局相同(都是 Reached target System Power Off.)。选择建议:立即关机直接 poweroff(名字即意图,不依赖参数组合的记忆);需要延时、广播消息或可取消时用 shutdown -P +m(shutdown 篇已实测全链路);halt -p 是 SysV 时代的习惯写法,实测同样有效(halt 篇 3.4 节)但语义要靠参数拼接,团队协作脚本里不如 poweroff 直白。

4.3 系统无响应时的强制断电

优雅路径无响应时,poweroff -f 是最后手段:

$ poweroff -f
Powering off.

执行后主机立即断电。代价清单见 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 组合,非破坏)
poweroff -w
if [ $? -ne 0 ]; then
    echo "关机权限不足(非 root 或 polkit 拒绝)" >&2
    exit 1
fi
poweroff

实测依据:systemctl is-system-running 在本环境返回 running(一、环境信息);poweroff -w 非破坏(3.7 节)且权限不足/参数错误均为退出码 1(3.10/3.11 节)。

五、注意事项与常见问题

Q1:poweroff 与 halt 到底差在哪?

差在最终动作:poweroff 请求断电(journal 收尾 Reached target System Power Off.),halt 只停住不断电(journal 收尾 Starting System Halt...,halt 篇 3.2 节)。物理机上 halt 后主机保持通电、停在内核停止态,需要现场按电源键;poweroff 后电源直接切断。在本实测环境这类无可控电源域的托管运行环境里,两者停止后都被外部重新拉起、最终表现接近,但 journal 判定行能严格证明走的是哪条路径(Q3 速查表)。

Q2:poweroff 与 shutdown -P now / shutdown -h now 有什么区别?

结局完全相同:journal 都收尾于 Reached target System Power Off.。区别在入口能力:shutdown 支持 [TIME] 延时、自定义广播消息、-c 取消、会写 /run/nologin 拦截后续登录;poweroff 一概没有,回车即停。另外帮助文本注明 shutdown -h 默认等价于 --poweroff(除非被 --halt 覆盖),所以 shutdown -h now 与 shutdown -P now 结局一致。

Q3:wtmp 里 poweroff 的 down 记录和 reboot/halt 长得一模一样,怎么区分动作?

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:为什么 poweroff -w 没有生成 wtmp 记录?

实测(last -x 前后对比 + /var/log/wtmp md5 前后一致)确认 249 上该参数什么都没写。-w 的价值仅剩「绝对非破坏」:配合任何选项都不会停机(含 -f),可当参数解析探针使用(4.4 节)。老教程中「-w 用于构造 wtmp 记录」的说法在本版本上不成立。

Q5:两次停机落在同一分钟,wtmp 对不上怎么办?

who -b/last -x 的时间戳只有分钟级分辨率,同分钟内的两次停机会出现「boot 时间没变、down 记录时间完全相同」的现象(4.1 节实测)。可靠的区分手段是按时间窗检索 journal 判定行(journalctl --since ... --until ... 配合 grep System Reboot|System Halt|System Power Off),秒级时间戳能精确定位每一次停机的动作类型。

六、参考链接

  • 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)》《halt 命令详解与参数实测(Ubuntu 22.04)》