技术指南
Linux 意外重启排障:区分正常关机、内核崩溃与宿主重置
从 boot ID 与上一轮日志出发,区分有序关机、内核 panic/lockup、watchdog reset 与宿主或电源事件,再补齐下一次取证能力。
Linux VPS 突然重启后,先回答“上一轮启动怎样结束”,再追问是谁触发。完整的关机序列、内核 panic/lockup 与持久崩溃记录、硬件 watchdog、云平台控制面事件是不同证据链;只有当前启动时间或一段戛然而止的日志,不能单独证明宿主故障、断电或内核崩溃。
用四条证据链决定调查方向
| 观察 | 当前能支持的判断 | 下一步 |
|---|---|---|
| 上一轮末尾有明确 reboot/shutdown 请求、服务停止与卸载序列 | 更接近正常关机路径,但仍要找发起者 | 对齐管理员操作、自动更新、编排和控制面审计 |
| 上一轮内核日志或 pstore/vmcore 有 panic、Oops、lockup 等记录 | 客体内核故障链成立 | 保全调用栈、内核与模块版本,再按发行版流程分析 |
| 配置了硬件 watchdog,日志或设备状态支持超时复位 | 可能是 PID 1 未喂狗、关机阶段卡死或底层 watchdog 复位 | 区分运行期 watchdog、关机 watchdog 与内核 lockup detector |
| journal 突然中断,且没有持久崩溃或关机证据 | 原因仍未知;日志尾部也可能尚未落盘 | 用精确 UTC 窗口查询供应商维护、reset/power 操作和宿主事件 |
先冻结当前 boot 与上一轮时间窗
umask 077
stamp=$(date --utc +%Y%m%dT%H%M%SZ)
evidence="reboot-incident-$stamp"
install -d -m 0700 "$evidence"
{
date --utc --iso-8601=seconds
printf 'boot_id='
cat /proc/sys/kernel/random/boot_id
uname -a
systemd-detect-virt || true
} | tee "$evidence/current-boot.txt"
journalctl --list-boots --no-pager | tee "$evidence/boots.txt"
last -xF -n 20 | tee "$evidence/wtmp-last.txt"`journalctl --list-boots` 会列出 journal 仍保存的 boot offset、boot ID 和首尾时间;`-1` 通常指上一轮启动。`last -xF` 可用 wtmp 的 reboot、shutdown 和 runlevel 记录做交叉检查,但 util-linux 明确说明 wtmp 文件可能不存在,文件不存在时不会自动创建,因此它不是正常或异常关机的最终证明。
完整保存上一轮 journal,再读最后二百行
sudo journalctl -b -1 --utc -o short-iso-precise --no-pager \
>"$evidence/previous-boot.journal.txt"
sudo journalctl -k -b -1 --utc -o short-iso-precise --no-pager \
>"$evidence/previous-boot.kernel.txt"
sudo journalctl -b -1 -n 200 --utc -o short-iso-precise --no-pager \
| tee "$evidence/previous-boot.tail.txt"
sudo journalctl --verify --no-pager \
| tee "$evidence/journal-verify.txt"如果 `-b -1` 没有结果,先检查 journald 的实际存储模式与保留窗口,不要把“没有日志”写成“正常关机”或“宿主强制重置”。journald 可能只写 `/run/log/journal` 的易失存储;即使使用 `/var/log/journal`,低优先级消息也按同步周期批量落盘,突然复位仍可能丢失最后一段。
从关机序列判断是否有序结束
回读上一轮尾部,按时间查找明确的关机或重启请求、进入 shutdown/reboot target、服务停止、文件系统卸载和最终关机消息,并与管理员、自动更新、配置管理或云控制面的同窗操作对应。完整序列支持“客体执行了有序关机”;它仍不能仅凭一行 reboot 判断是谁发起,也不能证明所有应用数据已经落盘。
检查 panic、lockup、pstore 与 vmcore
sudo systemctl status systemd-pstore.service --no-pager --full || true
sudo find /sys/fs/pstore /var/lib/systemd/pstore \
-maxdepth 1 -type f -printf '%p\n' 2>/dev/null \
| tee "$evidence/pstore-files.txt"
install -d -m 0700 "$evidence/pstore-kernel" "$evidence/pstore-archive"
for spec in kernel:/sys/fs/pstore archive:/var/lib/systemd/pstore; do
label=${spec%%:*}
root=${spec#*:}
for path in "$root"/*; do
test -f "$path" || continue
sudo cp --preserve=mode,timestamps "$path" "$evidence/pstore-$label/"
done
done
test -r /proc/vmcore && printf '%s\n' '/proc/vmcore is available' \
| tee "$evidence/vmcore-status.txt"在保存的内核日志和 pstore 中查看 panic、Oops、soft/hard lockup、Machine Check、I/O 错误及调用栈,并保留前后文。内核 lockup detector 可告警,配置后也可能 panic;`panic_timeout` 又可让 panic 后自动重启。pstore 依赖固件或平台后端,kdump 依赖预留内存和捕获内核,所以两者为空都不能证明内核从未崩溃。
把三种 watchdog 分开
systemd-analyze cat-config systemd/system.conf \
| tee "$evidence/system.conf.txt"
ls -l /dev/watchdog* /sys/class/watchdog 2>/dev/null \
| tee "$evidence/watchdog-inventory.txt"
for path in /sys/class/watchdog/watchdog*/{identity,state,status,timeleft,timeout,bootstatus}; do
test -r "$path" || continue
printf '
[%s]
' "$path"
cat "$path"
done | tee "$evidence/watchdog-state.txt"`RuntimeWatchdogSec=` 是 systemd 让 PID 1 定期喂硬件 watchdog,超时由硬件复位;`RebootWatchdogSec=` 保护关机第二阶段,当前上游默认十分钟。它们只有在硬件与驱动存在时才生效。内核 soft/hard lockup detector 是另一套机制,供应商控制面的宿主 watchdog 又在客体之外;报告中必须写清是哪一层提供了什么证据。
用控制面补齐客体看不到的事件
以 `--list-boots` 给出的上一轮末尾和新 boot 开始时间为 UTC 边界,查询供应商状态、维护记录、实例 activity/audit log、reset/power 动作、迁移、串口或 VNC 控制台输出。记录事件 ID、时间、动作主体和供应商回复。只有控制面或供应商证据才能把“客体日志突然中断”进一步归因到宿主维护、人工 reset 或电源事件;客体自身不能排除所有外部原因。
先恢复业务,再保持变量单一
- 有完整关机链时,先停止误触发的自动化或更新窗口,验证文件系统与状态型服务一致性,再恢复入口。
- 有 panic、lockup、pstore 或 vmcore 时,冻结内核、模块和启动参数版本;在保留旧内核启动项与控制台的前提下按发行版修复或回退。
- 只有 watchdog 线索时,先确认哪一层超时以及超时前的资源或关机阻塞;不要直接把所有 watchdog 关闭后宣布修复。
- 仍无根因且重复发生时,保存独立备份并评估迁移实例或宿主;迁移是降低暴露面的恢复动作,不是根因证明。
为下一次事件补齐持久证据
用 `systemd-analyze cat-config systemd/journald.conf` 查看合并后的 `Storage=` 与保留预算。需要跨重启调查时,在容量、隐私和留存要求允许的前提下配置 persistent journal,并在受控重启后确认上一轮 boot 可读。配置变更并不能追回已经丢失的日志;同步间隔也意味着突发 reset 仍可能失去尾部。
journalctl --list-boots --no-pager
systemd-analyze cat-config systemd/journald.conf
systemd-analyze cat-config systemd/pstore.conf
systemctl status systemd-pstore.service --no-pager --full
cat /proc/cmdline若决定部署 kdump,先按发行版为捕获内核预留内存,确认磁盘与敏感数据边界,并在非生产演练中验证 vmcore 可用;不要在未知生产状态下触发 panic。若启用 pstore,记录后端容量、systemd-pstore 的归档与 Unlink 策略。若启用硬件 watchdog,同时写明超时预算、业务恢复、关机阶段和独立控制台。
用下一次受控重启验收取证链
- 受控重启前后都记录 UTC、boot ID 与操作者;`journalctl --list-boots` 能看到两轮启动。
- 上一轮末尾包含预期的关机序列,新一轮首部时间连续;wtmp 仅作为交叉证据。
- persistent journal、pstore、kdump 与 watchdog 只启用已评审的组件,并分别验证容量、权限、告警和归档。
- 供应商控制面事件可按同一 UTC 窗口导出,自动 reset/rebuild 权限遵循最小授权。
- 业务健康、文件系统与状态型服务一致性检查通过,旧内核、配置和迁移回滚路径仍可用。
回滚观测配置,不删除事故证据
新增 journal、pstore、kdump 或 watchdog 配置导致磁盘、内存、启动或关机风险时,按各自所有者恢复原配置并完成一次受控验证;不要同时撤销多层设置。事故目录、控制面导出和校验值应按留存策略封存,而不是随配置回滚删除。
本文命令在 2026-08-19 按 systemd、util-linux 与 Linux 内核当前上游文档完成语义和语法审阅,没有在读者的 VPS 上触发重启、panic、watchdog 或 kdump。发行版补丁、旧 systemd、journal 保留、固件 pstore、watchdog 驱动、虚拟化平台和供应商控制面会改变可用证据;执行前先确认本机版本、独立控制台、备份与状态型服务恢复要求。