前回は、見直し後の自動バックアップについて、次回のtimerを1回待ち、systemdの結果・完了ログ・新しいsnapshotの3つで正常復帰を確認しました。
ただし、毎日この3か所を別々のコマンドで確認するのは大変です。今回は3つの証拠を1本のスクリプトへまとめ、緑・黄・赤のどれかを1コマンドで表示するローカル監視を作ります。
判定コマンドはバックアップを開始せず、修復も削除もしません。systemdとjournalを読み、resticは--no-cache --no-lock付きで対象snapshotを読み取ります。確認前後でInvocation IDも照合するため、途中で別のバックアップが始まった場合は緑にしません。
「読み取り専用」はヘルスチェック実行時の性質です。
最初の配置では、jqの導入とroot管理スクリプトの保存を行います。配置後の確認コマンドは、start・restart・reset-failed・backup・forget・prune・unlock・repair・削除・外部送信を実行しません。
この記事の到達点と扱わないこと
到達点は、次の1コマンドで現在の確認結果と終了コードを得ることです。
sudo /u\
sr/local/sbin/ouchi-lab-bac\
kup-health
status=$?
printf 'exit=%s
' "$status"
- GREEN / 0: 同じ自動実行の3証拠がそろい、最後の成功から36時間以内
- YELLOW / 1: 実行中、未実行、36〜60時間の古い成功、終了コード75、または確認中に実行が変化
- RED / 2: 明確な失敗、60時間超過、設定不備、ログ不一致、restic確認不能、時刻やsnapshotの不一致
外部監視サービス、メール、Slack、自動修復、定期実行は今回の対象外です。また、緑は「この自動実行の3証拠が一致した」という意味で、実ファイルを別の場所へ復元できることまでは保証しません。
前提は、9本目のsystemd timer自動化を設定し、12本目の正常復帰確認まで終えていることです。
緑に必要な3つの証拠

Result=success、ExecMainCode=exited、ExecMainStatus=0- 同じ
InvocationIDのjournalに最後の完了メッセージがある - 同じserviceの開始〜終了時刻内に、host・tag・pathが一致するsnapshotがある
serviceが成功していても完了ログがない、古いsnapshotしかない、対象pathが違う場合は緑にしません。3つを同じ実行へ結び付けることで、過去の成功を今回の成功と取り違えにくくします。
判定の優先順位

| 優先 | 状態 | 色 / 終了コード | 次の行動 |
|---|---|---|---|
| 1 | active・activatingなど実行中 | 黄 / 1 | 操作せず終了を待つ |
| 2 | timer停止、明確な失敗、60時間超過、設定・journal・restic・時刻の確認不能 | 赤 / 2 | 11本目で原因を切り分ける |
| 3 | 未実行、成功が36〜60時間前、終了コード75 | 黄 / 1 | 次回実行予定と競合を確認する |
| 4 | 同じ実行の3証拠が一致 | 緑 / 0 | 確認完了 |
黄は「失敗ではない」ではなく、今は緑と断定できない状態です。赤は明確な失敗だけでなく、必要な証拠を安全に読めない場合も含みます。不明な状態や未知のrestic終了コードを緑へ倒しません。
1. jqと既存設定を確認する
command -v syst\
emctl journ\
alctl restic jq runuser
sudo \
stat -c '%a %U %G %n' /e\
tc/ouchi-lab/restic-bac\
kup.env
5つのコマンドパスがすべて表示され、環境ファイルが600 root rootなら次へ進みます。jqだけ見つからない場合は、Ubuntu公式リポジトリから一度だけ導入します。
sudo \
apt update
sudo \
apt ins\
tall --yes jq
環境ファイルの中身は表示しません。パスワード本体ではなくファイルパスだけを設定していても、チャットやIssueへ貼り付けない運用を続けます。スクリプトも、sourceする前に通常ファイル・600・root所有を再確認します。
2. 読み取り専用ヘルスチェックを配置する
完全版は、記事と同じリポジトリのouchi-lab-backup-health.shです。内容を確認して任意の作業ディレクトリへ保存し、次のコマンドでroot管理の固定パスへ配置します。
sudo \
ins\
tall -o root -g root -m 755 ./ouchi-lab-bac\
kup-health.sh /u\
sr/local/sbin/ouchi-lab-bac\
kup-health
sudo /u\
sr/bin/bash -n /u\
sr/local/sbin/ouchi-lab-bac\
kup-health
sudo \
stat -c '%a %U %G %n' /u\
sr/local/sbin/ouchi-lab-bac\
kup-health
bash -nに出力がなく、最後が755 root rootなら配置完了です。一般ユーザーがroot権限で書き換えられる場所から直接実行しません。
スクリプトはset -eを使いません。確認コマンドの非0終了を一つずつ受け取り、途中終了で判定が欠けないようにしています。resticのJSONはjqで配列件数、time、host、tag、pathを検証します。
3. 1コマンドで確認する
sudo /u\
sr/local/sbin/ouchi-lab-bac\
kup-health
status=$?
printf 'exit=%s
' "$status"
正常時の例です。snapshot IDと経過秒数は環境ごとに変わります。
ouchi-lab-bac\
kup-health: GREEN: 3つの証拠が一致しました: snapshot=12ab34cd age=1800s
exit=0
確認中にserviceが動いていれば黄で止まります。前回の赤や緑を表示せず、現在の実行が終わってから確認し直すよう促します。
ouchi-lab-bac\
kup-health: YELLOW: バックアップが実行中または状態遷移中です
exit=1
resticリポジトリへ到達できない、パスワードファイルが不正、完了ログがない、snapshot時刻が同じ実行内にない場合は赤です。
ouchi-lab-bac\
kup-health: RED: resticスナップショットを確認できません: 終了コード 12
exit=2
resticの終了コード12は現在の公式資料ではパスワード不一致です。ただし将来追加される未知の終了コードも含め、0以外は成功扱いしません。
なぜresticへ –no-cache –no-lockを付けるのか
通常のresticはcacheを利用し、リポジトリのロックも扱います。今回の目的は監視時の書き込みを避けることなので、snapshot一覧に--no-cache --no-lockを付けます。
一方、ロックを使わない読み取り中にバックアップが始まる可能性は残ります。そのため、スクリプトは最初と最後にserviceのActiveStateとInvocationIDを確認し、途中で実行が変わったら黄にします。--no-lockだけで安全と判断しないのがポイントです。
現行の完了ログにはsnapshot IDそのものが含まれません。そのため、今回はhost・tag・pathとserviceの開始〜終了時刻から同じsnapshotを相関判定します。同じhost・tag・pathの別バックアップを並列実行せず、restic backup --timeで時刻を上書きしていない構成が前提です。将来は成功したsnapshot IDをjournalへ記録し、直接照合するとさらに強くできます。
36時間と60時間はresticやsystemdの標準値ではなく、日次timer向けの運用基準です。36時間は1日+12時間の猶予、60時間は約2回分の欠落+12時間の猶予です。timer周期を変えた場合は、この基準も見直します。
このヘルスチェックが越えない境界

このスクリプトは、次の操作を含みません。
systemctl start、restart、reset-failedmount、umount、chmod、chownrestic backup、check、forget、prune、unlock、repair- ファイルやロックの作成・変更・削除
- メール、Slack、Webhook、外部監視への送信
黄や赤が出ても、その場で自動修復しません。黄が実行中なら待ち、75なら次回予定を確認します。赤なら出力を控え、11本目の3系統切り分けへ進みます。
安全に検証する4項目
- 配置時の構文確認が無出力で終了する
- 直近の正常実行後にGREEN / 0になる
- 表示されたsnapshot IDが12本目の確認結果と一致する
- 実行前後で
systemctl list-timersのNEXTとLASTが変化していない
失敗を作るためにSSDを抜く、パスワードファイルを壊す、権限を変える、serviceを多重起動する、といったテストは行いません。黄・赤は実際に発生したときに確認し、原因切り分けへつなげます。
まとめ
毎日の確認は、コマンド数を減らしても証拠を減らしてはいけません。activeなtimer、同じInvocation IDのsystemd結果・完了ログ・対象snapshotを照合し、36時間以内なら緑、36〜60時間または判断保留なら黄、60時間超・失敗・確認不能なら赤にします。
systemdの機械可読なプロパティ取得はsystemctl公式マニュアル、Invocation IDによる絞り込みはUbuntu 26.04のjournalctlマニュアル、別ユーザーでのコマンド実行はrunuserマニュアルで確認しました。resticの終了コードとsnapshot JSONはrestic公式Scripting、--no-cacheと--no-lockはrestic公式マニュアル、JSONの検証はUbuntu 26.04のjqマニュアルを参照しました。公式情報の確認日は2026年8月6日です。
次回は、この読み取り専用ヘルスチェックを1日1回だけsystemd timerで実行し、結果をローカルjournalへ残す方法を扱います。



コメント