🐶

Linux でシステムのフリーズを検知して自動的に再起動させる方法

2022/08/17に公開

はじめに

我が家の Raspberry Pi が定期的にフリーズするのですが、原因が全くわかません。

何か対応策はないものかと調べていたら、Linux には Watchdog timer という仕組みがあることがわかりました。

今回は Ubuntu 22.04.1 LTS をインストールした Raspberry Pi で Watchdog timer を有効にして、システムフリーズ時に自動的に再起動するようにしてみます。

基本的には Raspberry Pi & Ubuntu でなくても、Linux をインストールしたマシンなら同じ方法で設定できると思いますので、ぜひ参考にしてみてください。

Watchdog timer の有効化

まずは Watchdog timer を有効にします。

/boot/config.txt に以下の 1 行を追加します。このファイルを今までに作ったことがない場合はファイルを新規作成します。

/boot/config.txt
dtparam=watchdog=on

Heartbeat の設定

Heartbeat は日本語に訳すと心臓の鼓動で、システムが正常に動作しているかどうかの確認を一定間隔ごとに行うものです。後述する設定で、このハートビートが一定期間以上なかった場合は再起動するようにします。

/etc/systemd/system.conf.d/main.conf というファイルを作成し、以下の 1 行を追加します[1][2]/etc/systemd/system.conf.d/ ディレクトリがない場合は作成します。

/etc/systemd/system.conf.d/main.conf
[Manager]
RuntimeWatchdogSec=5

上記の設定で、5 秒ごとに Heartbeat を行います。

再起動のしきい値の設定

先ほど設定した Heartbeat が一定期間以上来なかったら再起動する設定を行います。

/etc/modprobe.d/bcm2835-wdt.conf に以下の 1 行を追加します。ファイルがない場合は新規作成します。

/etc/modprobe.d/bcm2835-wdt.conf
options bcm2835_wdt heartbeat=10 nowayout=0

上記の設定で、10 秒以上 Heartbeat が来なかった場合は再起動するようにします。

再起動

システムを再起動して設定を反映させます。

Shell
sudo reboot

起動しているか確認

ログを見て Watchdog timer が起動しているか確認します。

まずは以下のコマンドを実行します。

Shell
sudo dmesg | grep bcm2835-wdt

以下のような出力があれば OK です。

[    1.949143] bcm2835-wdt bcm2835-wdt: Broadcom BCM2835 watchdog timer

次に以下のコマンドを実行します。

Shell
sudo dmesg | grep systemd | grep watchdog

以下のような出力がされれば OK です。

[    9.389119] systemd[1]: Using hardware watchdog 'Broadcom BCM2835 Watchdog timer', version 0, device /dev/watchdog
[    9.401138] systemd[1]: Set hardware watchdog to 5s.

動作確認

本当にフリーズしたときに再起動するのか試してみます。

フリーズさせる方法はいろいろありますが、代表的な方法として フォーク爆弾 を投下してみます。以下のコマンド[3]を実行します。

Shell
:(){ :|:& };:

実行後、シェルが急激に重くなります。

数分待って、システムが自動的に再起動されれば成功です。

さいごに

これはあくまで応急処置であって、本当はシステムが頻繁にフリーズする原因を突き止めるのが得策です。

でも、システムのフリーズなどという漠然とした問題の原因を突き止めるのは容易ではないですし、それなりに時間もかかります。Watchdog timer は根本原因解決までの代替手段としては有効かなと思います。

あるいは、このような問題がなかったとしても、何が起こるかはわからないので、盤石な構成にしておくという意味で有効にするのはありかなと思います。

参考

脚注
  1. /etc/systemd/system.conf をいじっても良いのですが、/etc/systemd/system.conf.d/*.conf を使用することが推奨されているので今回はこちらを使用します。 ↩︎

  2. ファイル名は任意なので main.conf でなくても大丈夫です。ただし拡張子は .conf としてください。 ↩︎

  3. はじめて見る方はコマンドには見えないかもしれませんが、これは Bash や Zsh で動作するコマンドです。 ↩︎

GitHubで編集を提案

Discussion