Translated message

A translation of this page exists in English.

RHEL 7 または RHEL 8 でクラッシュと正常なリブートを区別する方法

更新 -

RHEL 7 または RHEL 8 でシステムクラッシュと正常なリブートまたはシャットダウンをどのように区別できますか?この記事では、4 つのアプローチについて概説します。

  1. last -x で wtmp を検査する
  2. ausearch で auditd ログを検査する
  3. 必要な設定: カスタムサービスユニットを作成する
  4. 必要な設定: 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) カスタムサービスユニットの作成

注記: 現時点で潜在的なクラッシュを診断しようとしている場合、これは役に立ちません。まず設定する必要があります。

このアプローチは完全な制御を可能にするので優れています。以下は、これを実行する方法の例になります。

  1. シャットダウン時にのみ実行されるサービスを作成します。
    (オプションでサービス名と 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
    
  2. 上記のサービスによって作成された 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
    
  3. 正常なリブート後であればいつでも、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.
    
  4. クラッシュまたは正常でないシャットダウンが発生すると、次のようになります。

    ~]# 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 を事前に設定していない限り、これは役に立ちません。

  1. 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
    
  2. オプションで 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
    
  3. 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