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 ファイルに、最新の 2 回のシャットダウンまたはリブートが報告されます。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 が省略されていることで判断できます。省略されている場合、1 つの 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 が報告された場合は問題ありません。ただし、SYSTEM_BOOT 行が 2 行続けて報告された場合、または SYSTEM_BOOT 行が 1 行しか報告されない場合は、システムが正常にシャットダウンされていません。
正常なシャットダウン:
~]# 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'
もう 1 つの正常ではないシャットダウン:
SYSTEM_BOOT レコードが 1 つしか存在しない理由は、クラッシュ前にシステムが長時間稼働していたため、前回のリブートの監査ログがローテーションで削除され、システムがブートされた直後の結果のみが存在するためと考えられます。
~]# 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
著者からの注記: Red Hat サポートでお客様のために RHEL 7 の問題をトラブルシューティングした経験 (この記事を執筆した 2016 年までの数年間) から判断すると、この方法は他の方法よりも信頼性がやや低くなります。 何か問題が発生すると、journald のインデックス化が非常に悪くなり、journalctl -b -1 コマンドでエラーしか返されなくなる可能性が確実にありました。RHEL 7 および RHEL 8 の後のバージョンでこの点が改善されたかどうかはわかりません。
Comments