如何在 RHEL 7 或 RHEL 8 中区分崩溃和正常重启
如何在 RHEL 7 或 RHEL 8 中区分系统崩溃和正常重启或关闭?本文概述了 4 种方法:
- 使用 last -x 检查 wtmp
- 使用 ausearch 检查 auditd 日志
- 需要配置:创建一个自定义服务单元
- 需要配置:使用 journalctl 检查之前在持久 systemd 日志中的引导
(1)使用 last -x 检查 wtmp
使用简单的 last -Fxn2 shutdown reboot
命令,系统 wtmp 文件会报告两个最新的关闭或重启。reboot 表示系统正在启动,shutdown 表示系统正在关闭。
正常关闭 会显示为 reboot 行,后跟 shutdown 行,如下例中所示:
~]# last -Fxn2 shutdown reboot reboot system boot 4.18.0-80.el8.x8 Mon Aug 31 06:33:11 2020 still running shutdown system down 4.18.0-80.el8.x8 Mon Aug 31 06:33:01 2020 - Mon Aug 31 06:33:11 2020 (00:00)
注:来自 last
的事件按时间降序打印,最近的在顶部。
非正常关闭 可以通过忽略 shutdown 来推断。相反,将有一个 reboot 行(如果 wtmp 文件在崩溃前被已被截断/轮转),或连续有 2 个 reboot 行,如下例所示:
~]# last -Fxn2 shutdown reboot reboot system boot 4.18.0-147.5.1.e Tue Sep 1 07:16:25 2020 still running reboot system boot 4.18.0-147.5.1.e Mon Aug 3 07:10:56 2020 still running
(2)使用 ausearch 检查 auditd 日志
auditd 非常棒,可以通过检查 ausearch -m
查看它记录的所有不同的事件。针对当前的问题,它记录了系统关闭和系统启动,如上所示。ausearch -i -m system_boot,system_shutdown | tail -4
命令将报告 2 个最近的关闭或启动。如果这报告了一个 SYSTEM_SHUTDOWN,后跟一个 SYSTEM_BOOT,则一切良好;但是,如果它连续报告 2 个 SYSTEM_BOOT 行,或只有一个 SYSTEM_BOOT 行,则系统不会正常关闭。
正常关闭 :
~]# ausearch -i -m system_boot,system_shutdown | tail -4 type=SYSTEM_SHUTDOWN msg=audit(08/31/2020 06:33:01.571:595) : pid=27156 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success' type=SYSTEM_BOOT msg=audit(08/31/2020 06:33:12.838:9) : pid=828 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success'
注:正如时间戳表明的那样,来自 ausearch
的事件按时间升序打印,且最早的在顶部。
非正常关闭:
~]# ausearch -i -m system_boot,system_shutdown | tail -4 type=SYSTEM_BOOT msg=audit(09/20/2016 01:10:32.392:7) : pid=657 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success' type=SYSTEM_BOOT msg=audit(09/20/2016 01:11:41.134:7) : pid=656 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success'
另一个非正常关闭:
只存在一个 SYSTEM_BOOT 记录可以解释为系统在崩溃前已运行了很长时间,之前重启的审计日志已被轮转了 ...因此唯一的结果是来自系统刚刚启动时的情况。
~]# ausearch -i -m system_boot,system_shutdown | tail -4 type=SYSTEM_BOOT msg=audit(09/01/2020 07:16:27.069:10) : pid=1057 uid=root auid=unset ses=unset subj=system_u:system_r:init_t:s0 msg=' comm=systemd-update-utmp exe=/usr/lib/systemd/systemd-update-utmp hostname=? addr=? terminal=? res=success'
(3)创建一个自定义服务单元
备注:如果您现在正在尝试诊断潜在的崩溃,这不会有帮助。您首先需要设置它。
这个方法非常棒,因为它允许完全控制。以下是如何做的一个示例:
-
创建一个仅在关闭时运行的服务
(可选)自定义服务名称和 graceful_shutdown 文件。)~]# cat /etc/systemd/system/set_gracefulshutdown.service [Unit] Description=Set flag for graceful shutdown DefaultDependencies=no RefuseManualStart=true Before=shutdown.target [Service] Type=oneshot ExecStart=/bin/touch /root/graceful_shutdown [Install] WantedBy=shutdown.target ~]# systemctl daemon-reload ~]# systemctl enable set_gracefulshutdown
-
创建一个服务,它仅在启动时运行,并且仅在上述服务创建的 graceful_shutdown 文件存在时运行
(可选)自定义服务名称,并确保 graceful_shutdown 文件与上述服务匹配。)~]# cat /etc/systemd/system/check_graceful.service [Unit] Description=Check if previous system shutdown was graceful ConditionPathExists=/root/graceful_shutdown RefuseManualStart=true RefuseManualStop=true [Service] Type=oneshot RemainAfterExit=true ExecStart=/bin/rm /root/graceful_shutdown [Install] WantedBy=multi-user.target ~]# systemctl daemon-reload ~]# systemctl enable check_graceful
-
每当正常重启后,
systemctl is-active check_graceful
都可以确认之前的重启是否正常。
输出示例:~]# systemctl is-active check_graceful && echo GOOD || echo BAD active GOOD ~]# systemctl status check_graceful ● check_graceful.service - Check if system booted after a graceful shutdown Loaded: loaded (/etc/systemd/system/check_graceful.service; enabled; vendor preset: disabled) Active: active (exited) since Tue 2016-09-20 01:10:32 EDT; 20s ago Process: 669 ExecStart=/bin/rm /root/graceful_shutdown (code=exited, status=0/SUCCESS) Main PID: 669 (code=exited, status=0/SUCCESS) CGroup: /system.slice/check_graceful.service Sep 20 01:10:32 a72.example.com systemd[1]: Starting Check if system booted after a graceful shutdown... Sep 20 01:10:32 a72.example.com systemd[1]: Started Check if system booted after a graceful shutdown.
-
崩溃或非正常关闭后,将看到以下内容:
~]# systemctl is-active check_graceful && echo GOOD || echo BAD inactive BAD ~]# systemctl status check_graceful ● check_graceful.service - Check if system booted after a graceful shutdown Loaded: loaded (/etc/systemd/system/check_graceful.service; enabled; vendor preset: disabled) Active: inactive (dead) Condition: start condition failed at Tue 2016-09-20 01:11:41 EDT; 16s ago ConditionPathExists=/root/graceful_shutdown was not met Sep 20 01:11:41 a72.example.com systemd[1]: Started Check if system booted after a graceful shutdown.
(4)使用 journalctl 检查之前在持久 systemd 日志中的引导
备注:如果您现在尝试诊断潜在的崩溃,除非之前已将 systemd 配置为将日志持久保留到磁盘,否则不会有帮助。
-
配置
systemd-journald
来将日志持久保留在磁盘上
更新/etc/systemd/journald.conf
或按照如下所示自己创建目录# Create standard log dir and fix ownership/perms ~]# mkdir /var/log/journal; systemd-tmpfiles --create --prefix /var/log/journal 2>/dev/null # Next: tell systemd to flush the current journal to disk ~]# systemctl -s SIGUSR1 kill systemd-journald # OPTIONAL: reboot not required other than to give the following commands more than one boot to inspect ~]# reboot
-
(可选)使用
journalctl --list-boots
得到按时间升序的启动的列表
0
表示自系统启动以来的当前运行时日志 ;-1
表示涵盖之前启动的日志 ;-2
表示在此之前的启动,等等
例如:~]# journalctl --list-boots -2 e1dbd8f133f643d1a816605d96f3ca07 Fri 2020-03-27 22:31:25 UTC—Thu 2020-05-14 01:02:51 UTC -1 1969253689e842deaea06ca32f4650c7 Thu 2020-05-14 01:10:00 UTC—Thu 2020-06-04 08:29:42 UTC 0 26a4a2ff48594778850d917a7e2ad195 Tue 2020-09-01 07:16:20 UTC—Tue 2020-09-01 19:11:20 UTC
-
使用
journalctl -b -1 -n
查看上一次启动的最后 10 行
以下示例输出显示上一个系统重启是正常的~]# journalctl -b -1 -n Sep 20 01:21:19 a72.example.com systemd[1]: Stopped Create Static Device Nodes in /dev. Sep 20 01:21:19 a72.example.com systemd[1]: Stopping Create Static Device Nodes in /dev... Sep 20 01:21:19 a72.example.com systemd[1]: Reached target Shutdown. Sep 20 01:21:19 a72.example.com systemd[1]: Starting Shutdown. Sep 20 01:21:19 a72.example.com systemd[1]: Reached target Final Step. Sep 20 01:21:19 a72.example.com systemd[1]: Starting Final Step. Sep 20 01:21:19 a72.example.com systemd[1]: Starting Reboot... Sep 20 01:21:19 a72.example.com systemd[1]: Shutting down. Sep 20 01:21:19 a72.example.com systemd-shutdown[1]: Sending SIGTERM to remaining processes... Sep 20 01:21:19 a72.example.com systemd-journal[483]: Journal stopped
来自作者的备注:根据我在红帽支持过程中为客户解决 RHEL 7 问题的经验(在我写这篇文章的 2016 年之前的几年里),这种方法比其他方法更不可靠。 当不好的事情发生时,journald 中的索引肯定会变得非常糟糕,以至于 journalctl -b -1
命令只能给出一个错误。我不确定这是否已在之后的 RHEL 7 和 RHEL 8 版本中得到了改进。
Comments