RaspberryPi4B で ウォッチドッグタイマーを使う

目的

サーバとして使用しているラズパイが何らかの原因でフリーズした場合、自動的に再起動させてサービスの停止時間を短くするために、ウォッチドッグタイマーを使用する。

使用OS

Ubuntu22.04.1 LTS 64bit

設定

以下のようにファイルを編集または新規作成する。

/boot/firmware/config.txt
末尾に次の一文を追加

dtparam=watchdog=on

/etc/modprobe.d/ に bcm2835-wdt.conf と言うファイルを新規に作成し、内容を以下とする。

options bcm2835_wdt heartbeat=60 nowayout=0

heartbeat に 60 を設定しているけど、ここは自環境や要望に応じて変更してくださいな。
うちはそんなにシビアな設定にしてもあまり意味がないので、ちょっと長めにしています。

続いて、/etc/systemd/system.conf を編集。
RuntimeWatchdogSecという項目が#でコメントアウトされているので#を消し、Heartbeatを打つ間隔を指定する。
当然、上で設定した数字(うちは60)よりも小さい値にしておく必要がある。

RuntimeWatchdogSec=10

設定確認

設定が済んだら、ラズパイを再起動。

再起動したところで、ちゃんとウォッチドッグタイマーが機能しているか、Hearbeatがちゃんと打たれているか確認。

$ sudo dmesg | grep watchdog
[    0.998035] bcm2835-wdt bcm2835-wdt: Broadcom BCM2835 watchdog timer
[    6.037421] systemd[1]: Using hardware watchdog 'Broadcom BCM2835 Watchdog timer', version 0, device /dev/watchdog
[    6.037461] systemd[1]: Set hardware watchdog to 10s.

ラズパイを意図的に落として確認

OKな用であれば、プロセス無限作成=通称「フォークボム」と言うらしい、を行って、意図的にラズパイを落としてみる。
ラズパイが落ちて、設定秒数経過後に再起動されれば、OKということに。

フォクボムは下記で落とせる。
最初の1文字目がスペースだと言うことに気づかず、一発目は失敗した・・・

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

同時にPINGも打って見ていると・・・
途中からタイムアウトが発生。SSHでつなげていたターミナルも切断された。
ということで、このあたりでリソースが枯渇してラズパイからの反応はなくなったと思われる。

192.168.1.200 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.200 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.200 からの応答: バイト数 =32 時間 =2ms TTL=64
192.168.1.200 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.200 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.200 からの応答: バイト数 =32 時間 =4ms TTL=64
192.168.1.200 からの応答: バイト数 =32 時間 =1ms TTL=64
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。

Heartbeatが途切れてから少しすると(うちの場合は60秒)、PING応答が復活し、このタイミングでラズパイが再起動したと思われる。

SSHでの再接続も無事確認でき、再起動が完了。

これで、何かやらかしても自動的に再起動してくれる・・・はず。
尚、再起動がいつ行われたかは下記コマンドで確認できる。

$ last reboot

完了

この記事を書いててふと思った。

このHeartbeat、外部に打てるのかしら・・・って。
最近はUSB-HDD(SSD)からもBootできるのでSDカードよりもそっちの方がいいと思うんだけど、それでもSDカードにしたいこともあって、SDカードが死んだときにはいくら再起動しても無駄なわけで、HAみたいな構成が採れたら面白いのかな、と。

・・・まぁ、そんなクリティカルなところには別のデバイス使えって話か・・・

この記事にコメントしてみる