Linux 講座 / サーバーのバックアップと状態チェックの自動化構成

サーバー運用では、復旧可能なバックアップと障害を検知できる状態チェックの両方が必要です。バックアップファイルの作成、ファイルの完全性、実際の復元、HTTP応答とディスクの空き容量を個別に検証し、サーバー外から失敗・未実行を検知するルートを用意してください。

この記事では、手動バックアップ・復元検証を通過した手順を、予約実行と結びつけます。バックアップ作成、個別の復元確認、失敗通知をそれぞれ確認して初めて予約作業が成功したと判断できます。

システム設定実習の基準は Ubuntu 26.04 LTS と Rocky Linux 9 系の一般インストール VM です。コンテナ・WSL・別のリリースでは、サービスやパッケージの構成が異なる場合があります。仮想マシン実習環境の作成で、コンソールの復旧とバージョン確認を最初に準備してください。

この実習が保護するデータと限界

対象は、第33講の静的コンテンツのように実行中の変更が制限された一般ファイルです。サービス設定・証明書・DNS・配布手順は別途バックアップ・文書化し、データベースは該当製品の一貫したバックアップ方式を使用します。以下のローカルバックアップは実行構造を学ぶ段階であり、サーバーディスク障害やアカウント侵害に耐える最終的な保管場所ではありません。

一般ユーザー権限で読み込める元ファイルと、自分だけが書き込めるバックアップディレクトリを選択してください。rootが必要なファイルを楽に読むためにスクリプト全体を無条件でrootの定期実行にしないでください。運用バックアップは専用アカウントと許可された経路・暗号化キー管理・保持期間を別途定めます。

引数でパスを受け取るバックアップスクリプトを作る

mkdir -p "$HOME/bin"
cat > "$HOME/bin/course-backup.sh" <<'EOF'
#!/usr/bin/env bash
set -u
set -o pipefail
umask 077
if (( $# != 2 )); then
  printf "Usage: %s SOURCE_DIRECTORY BACKUP_DIRECTORY\n" "$0" >&2
  exit 2
fi
source_dir=$(realpath -e -- "$1") || exit 1
backup_dir=$(realpath -e -- "$2") || exit 1
[[ -d "$source_dir" && -d "$backup_dir" ]] || exit 1
case "$backup_dir/" in
  "$source_dir/"*) printf "Backup must be outside source\n" >&2; exit 1 ;;
esac
work=$(mktemp -d "$backup_dir/backup.XXXXXXXX") || exit 1
if ! tar -czf "$work/data.tar.gz" -C "$source_dir" .; then
  printf "Archive failed: %s\n" "$work" >&2; exit 1
fi
if ! tar -tzf "$work/data.tar.gz" > /dev/null; then
  printf "Archive listing failed\n" >&2; exit 1
fi
if ! (cd "$work" && sha256sum data.tar.gz > data.tar.gz.sha256); then
  printf "Checksum creation failed\n" >&2; exit 1
fi
if ! date --iso-8601=seconds > "$work/created-at.txt"; then exit 1; fi
printf "complete\n" > "$work/COMPLETE" || exit 1
printf "Backup ready: %s\n" "$work"
EOF
bash -n "$HOME/bin/course-backup.sh"

スクリプトは実行ごとに固有のディレクトリを作成して名前の衝突を避けます。最後の COMPLETE 表示がある資料のみを完了したバックアップと見なします。失敗したディレクトリが残っている場合は原因を確認し、復旧時点のリストには含めません。作成時刻は記録しますが、古いバックアップを自動で削除することはありません。

実行・整合性・復元をそれぞれテストする

lab=$(mktemp -d "$HOME/linux-ops-lab.XXXXXX")
mkdir "$lab/site" "$lab/backups" "$lab/restored"
printf "site version 1\n" > "$lab/site/index.html"
bash "$HOME/bin/course-backup.sh" "$lab/site" "$lab/backups"
find "$lab/backups" -maxdepth 2 -type f -print

出力された Backup ready: パスを実際の変数に入れ、以下のように確認します。ACTUAL_BACKUP_DIRECTORY は今回の実行で出力されたディレクトリに置き換えます。チェックサムの検証とtar リストの成功は復元可能なアプリケーションを保証するものではないため、内容を比較し、実際のウェブサービスの使用も別途テストする必要があります。

backup=ACTUAL_BACKUP_DIRECTORY
test -f "$backup/COMPLETE"
(cd "$backup" && sha256sum -c data.tar.gz.sha256)
tar -xzf "$backup/data.tar.gz" -C "$lab/restored"
diff -r "$lab/site" "$lab/restored"

正常な結果は COMPLETE が存在し、チェックサムは OK、diff に差異がないことです。復元は空のディレクトリで行い、権限・所有者・必要なラベルも確認します。リモートストレージに移動した後も、チェックサムと復元テストを繰り返してください。空き容量が不足した場合、任意に古いコピーをすべて削除せず、必要な復旧時点を保持するポリシーを適用します。

HTTP 応答と空き容量確認スクリプト

curl·df·awkが必要です。URLと最小空きKiBを引数として受け取り、HTTP 200〜299を正常と見なします。サービスがリダイレクトを意図する場合やログインページを返す場合は、判断基準を調整する必要があります。この例では、応答本文の正確性やデータベースの状態、すべての機能を検査するわけではありません。

cat > "$HOME/bin/course-health.sh" <<'EOF'
#!/usr/bin/env bash
set -u
set -o pipefail
if (( $# != 3 )); then
  printf "Usage: %s URL MIN_FREE_KIB STORAGE_PATH\n" "$0" >&2; exit 2
fi
url=$1
minimum=$2
path=$3
[[ "$minimum" =~ ^[0-9]+$ ]] || exit 2
if ! status=$(curl -sS -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 15 "$url"); then
  printf "HTTP transport failed\n" >&2; exit 1
fi
[[ "$status" =~ ^2[0-9][0-9]$ ]] || { printf "HTTP status=%s\n" "$status" >&2; exit 1; }
available=$(df -Pk -- "$path" | awk 'NR==2 {print $4}') || exit 1
[[ "$available" =~ ^[0-9]+$ ]] || exit 1
(( 10#$available >= 10#$minimum )) || { printf "Low storage: %s KiB\n" "$available" >&2; exit 1; }
printf "OK http=%s free_kib=%s\n" "$status" "$available"
EOF
bash -n "$HOME/bin/course-health.sh"
bash "$HOME/bin/course-health.sh" http://127.0.0.1/ 102400 "$HOME"

最小102400 KiBは約100 MiBの実習用しきい値であり、運用推奨値ではありません。増加速度・復旧作業スペースを考慮して設定し、iノードは別途確認してください。名前ベースのNginxサイトは、実際のドメインURLまたは適切なHost設定で点検する必要があり、基本サイトの200を目標サイトの成功と誤認しません。

タイマー接続と外部障害検出

第29回のユーザーservice·timer構造を再利用しますが、ExecStartを/bin/bash %h/bin/course-backup.sh 実際のソースパス 実際のバックアップパスに指定します。パスに空白がある場合は、systemdコマンドラインの文法に従って各引数を引用し、まず同じコマンドを手動で実行します。スケジュールはバックアップの変更量・復旧目標に合わせて設定し、状態チェックは別ユニットとして分離します。

タイマーの次回実行とサービス終了状態、最後のCOMPLETE生成時刻を個別に確認します。同じサーバー内での点検は、サーバー全体が停止すると一緒に停止するため、サーバー外のモニターが実際のURLと最後のバックアップ時刻を確認する必要があります。メール・メッセンジャー通知は受信経路と障害発生時刻も試験し、警報が発生した際に誰が何を復旧するかを決定します。

失敗条件のテストと実習の片付け

存在しない元のパスでバックアップが失敗するか、存在しない HTTP パスでチェックが失敗するか、過度に大きな余裕スペースの閾値で失敗するか、一つずつ条件を確認して元の値を復元します。完了マークのないバックアップを成功として報告しないかも確認してください。実習タイマーを先に停止・解除し、その後スクリプトと新しい作業フォルダだけを整理します。

公式ドキュメント