シェルスクリプトでバックアップの整合性を自動検証する設計|sha256sumとgzip -tで破損を検知する実践パターン

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)シェルスクリプト > シェルスクリプトでバックアップの整合性を自動検証する設計|sha256sumとgzip -tで破損を検知する実践パターン
「バックアップは取っていたのに、いざ復旧しようとしたらファイルが壊れていて使えなかった。」
サーバー運用の現場でこの話を聞くたびに背筋が冷たくなります。定期的にrsyncやtarでバックアップを取っていても、ディスクエラー・転送中の破損・ファイルシステムの不整合などで、気づかないままアーカイブが壊れていることはあります。

この記事では、バックアップが本当に正常かを確認するシェルスクリプトの設計を解説します。sha256sumによるチェックサム照合gzip -t / tar -tzfによるアーカイブ構造の検証を組み合わせ、trap ERRで障害を即通知する自動検証スクリプトの実装パターンを紹介します。
RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済みです。

この記事のポイント

・sha256sum -c でチェックサムを照合し、バックアップファイルのビット破損を自動検知できる
・tar -tzf でgzip圧縮とtarアーカイブ構造を1コマンドで走査し、読み出し不能な破損を発見できる
・trap ERR を設定すると検証失敗時に自動通知が走り、無言の障害を防げる
・バックアップ直後にチェックサム生成→翌日に照合というパターンが設計の基本形


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

バックアップが「取れているつもり」になっていないか

「バックアップは毎晩自動で取っています」と言うシステム管理者に「最後に復元テストをしたのはいつですか?」と聞くと、「……したことがありません」と返ってくることが多いです。

バックアップファイルが壊れる原因は思った以上に多様です。

・HDD/SSDの不良セクタによるサイレントビット破損
・ネットワーク転送中のパケット損失(rsync転送後に破損)
・バックアップ実行中のディスクフル(アーカイブが途中で切れる)
・cronジョブの途中終了(シグナル受信でtarが中断)
・マウントポイントの未設定(バックアップ先が空のローカルディレクトリに書かれてしまう)

ls -la /backup/data.tar.gz を実行してファイルが存在してもサイズが大きくても、中身が壊れていれば障害時には何の役にも立ちません。バックアップの価値はリストアできて初めて証明されます。

手動での復元テストは工数がかかりますが、「検証専用シェルスクリプト」を整備してcronで定期実行することで、壊れたバックアップを無人で早期発見できます。

バックアップ検証の2つのアプローチ

バックアップ検証には性格の異なる2つのアプローチがあります。用途に合わせて組み合わせて使うのが設計のポイントです。

アプローチ 確認できること コマンド例
チェックサム照合 バックアップ直後から変化がないかを確認(ビット破損検知) sha256sum -c ファイル.sha256
アーカイブ構造検証 アーカイブを展開せずに構造の整合性を確認(読み出し不能の発見) tar -tzf archive.tar.gz > /dev/null

チェックサム照合はバックアップ時点のハッシュ値と現在のファイルのハッシュ値を比較します。ネットワーク転送後の破損や保存期間中のサイレント破損を発見できます。ただし、バックアップを取った時点ですでに壊れていた場合は見抜けません。

アーカイブ構造検証はtarのブロック構造やgzip圧縮の整合性を実際に走査して確認します。「展開しようとしたら途中でエラー」という問題を、本番リストア前に発見できます。

2つを組み合わせることで、「バックアップ直後から変化していない」かつ「アーカイブとして読み出せる」という2段階の保証が得られます。

sha256sumチェックサムで整合性を検証する

1. バックアップ直後にチェックサムファイルを生成する

バックアップスクリプトの最後でチェックサムファイルを生成します。これがあとの照合の基準になります。

#!/bin/bash # backup_with_checksum.sh — バックアップ実行+チェックサム生成 BACKUP_DIR="/backup/daily" TARGET="/var/lib/myapp/data" DATE=$(date +%Y%m%d) ARCHIVE="${BACKUP_DIR}/data_${DATE}.tar.gz" mkdir -p "${BACKUP_DIR}" tar -czf "${ARCHIVE}" "${TARGET}" # チェックサムファイルを生成(アーカイブと同じディレクトリに置く) sha256sum "${ARCHIVE}" > "${ARCHIVE}.sha256" echo "バックアップ完了: ${ARCHIVE}" echo "チェックサム: $(cat "${ARCHIVE}.sha256")"

生成されたチェックサムファイルの中身はこのような形式です。

$ cat /backup/daily/data_20260825.tar.gz.sha256 a3f8c1d9e2b074563...(64桁のSHA-256ハッシュ) /backup/daily/data_20260825.tar.gz

設計の注意点:
・チェックサムファイルはアーカイブと別のストレージにコピーしておくのが理想です。同じディスクに入れておくとディスク障害時に両方失います。
sha256sum はファイルパスもハッシュに含めるため、照合時にカレントディレクトリや絶対パスの違いに注意が必要です(後述)。

2. 検証スクリプトでチェックサムを照合する

sha256sum -c は指定したチェックサムファイルを読み取り、現在のファイルと照合します。

# チェックサムファイルのあるディレクトリに移動してから照合する cd /backup/daily sha256sum -c data_20260825.tar.gz.sha256

以下は実際の実行結果です。正常時と破損時で出力が変わります。

# 正常時 $ sha256sum -c data_20260825.tar.gz.sha256 data_20260825.tar.gz: OK # 破損時(ファイルが途中から変化している) $ sha256sum -c data_20260825.tar.gz.sha256 data_20260825.tar.gz: FAILED sha256sum: WARNING: 1 computed checksum did NOT match

sha256sum -c は照合失敗時に終了コード1を返しますset -e を使ったスクリプトではこのコードを捕捉してtrapを発動させられます。

gzip -tとtar -tzfでアーカイブ構造を検証する

1. gzip -tで圧縮ヘッダーを検証する

gzip -t は.gz / .tar.gzファイルのgzip圧縮部分のヘッダーとフッターを検査します。ファイルを解凍せずに「正しく圧縮されているか」を確認できます。

# gzip圧縮の整合性を確認する(-vで詳細表示) gzip -t /backup/daily/data_20260825.tar.gz echo "終了コード: $?" # 詳細表示付き gzip -tv /backup/daily/data_20260825.tar.gz

# 正常時(-v 付き) $ gzip -tv /backup/daily/data_20260825.tar.gz /backup/daily/data_20260825.tar.gz: OK # 末尾が切れたファイルの場合 $ gzip -tv /backup/daily/data_20260825.tar.gz /backup/daily/data_20260825.tar.gz: gzip: /backup/daily/data_20260825.tar.gz: unexpected end of file

gzip -t は高速ですが、gzip層の外側しか確認しません。gzip圧縮自体は正常でもtar内部のファイルブロックが壊れている場合は検知できません。

2. tar -tzfでアーカイブ全体を走査する

tar -tzf はgzip解凍後にtarアーカイブ全体のブロック構造を走査します。すべてのファイルエントリを読み込むため、途中ブロックが壊れていれば発見できます。

# tar -tzf でアーカイブ全体を走査(/dev/null に捨てることで内容を表示しない) tar -tzf /backup/daily/data_20260825.tar.gz > /dev/null echo "終了コード: $?"

# 正常時 $ tar -tzf /backup/daily/data_20260825.tar.gz > /dev/null $ echo $? 0 # アーカイブ途中でブロックが壊れている場合 $ tar -tzf /backup/daily/data_20260825.tar.gz > /dev/null tar: Unexpected EOF in archive tar: Error is not recoverable: exiting now $ echo $? 2

gzip -tとtar -tzfの使い分け
gzip -t:高速(圧縮ヘッダーのみ)。大量ファイルの一括チェックに向く
tar -tzf:確実(全ブロックを走査)。重要バックアップの精密検証に向く

両方を組み合わせると「圧縮→tar構造」の2層を順に検証できます。
tar コマンドの実用例で基本的なオプションの使い方も確認してください。

自動検証スクリプトの完全実装

1. trapで検証失敗時の通知を設定する

検証スクリプトに trap を仕込んでおくと、sha256sum照合失敗・tar走査失敗のどちらが起きても、同じ通知処理を確実に走らせられます。

# ERRシグナルで任意のコマンドが非ゼロを返した時に発動 trap 'on_error "$LINENO"' ERR on_error() { local line=$1 echo "[ERROR] 検証失敗 (line: ${line}) — ${CURRENT_FILE}" >&2 # mailコマンドで通知(要sendmail/postfix設定) echo "バックアップ検証失敗: ${CURRENT_FILE} (line: ${line})" \ | mail -s "[ALERT] backup verify failed on $(hostname)" admin@example.com exit 1 }

2. 検証スクリプト全体のコード

#!/bin/bash # verify_backup.sh — バックアップ整合性自動検証スクリプト # 使い方: ./verify_backup.sh /backup/daily set -euo pipefail BACKUP_DIR="${1:?使い方: $0 バックアップディレクトリ}" LOG_FILE="/var/log/backup_verify.log" NOTIFY_TO="admin@example.com" CURRENT_FILE="" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "${LOG_FILE}" } on_error() { local line=$1 log "ERROR: 検証失敗 (line: ${line}) — ファイル: ${CURRENT_FILE}" echo "バックアップ検証失敗: ${CURRENT_FILE} (line: ${line}) on $(hostname)" \ | mail -s "[ALERT] backup verify failed" "${NOTIFY_TO}" 2>/dev/null || true } trap 'on_error "$LINENO"' ERR log "検証開始: ${BACKUP_DIR}" # バックアップディレクトリの存在確認 if [[ ! -d "${BACKUP_DIR}" ]]; then log "ERROR: ディレクトリが存在しません: ${BACKUP_DIR}" exit 1 fi FAILED=0 SUCCESS=0 # .sha256 ファイルを基点に対応するアーカイブを検証する for SHA_FILE in "${BACKUP_DIR}"/*.sha256; do [[ -e "${SHA_FILE}" ]] || { log "WARN: .sha256ファイルが見つかりません"; break; } ARCHIVE="${SHA_FILE%.sha256}" CURRENT_FILE="${ARCHIVE}" if [[ ! -f "${ARCHIVE}" ]]; then log "ERROR: アーカイブが存在しません: ${ARCHIVE}" FAILED=$((FAILED + 1)) continue fi log "--- 検証中: $(basename "${ARCHIVE}") ---" # Step 1: sha256sum チェックサム照合 log " [1/2] sha256sum照合..." cd "$(dirname "${ARCHIVE}")" if sha256sum -c "$(basename "${SHA_FILE}")" > /dev/null 2>&1; then log " sha256sum: OK" else log " ERROR: sha256sum照合失敗" FAILED=$((FAILED + 1)) continue fi # Step 2: tar アーカイブ構造の走査 log " [2/2] tar構造走査..." if tar -tzf "${ARCHIVE}" > /dev/null 2>&1; then log " tar -tzf: OK" else log " ERROR: tarアーカイブ破損" FAILED=$((FAILED + 1)) continue fi log " 結果: 正常" SUCCESS=$((SUCCESS + 1)) done log "検証完了: 正常=${SUCCESS} / 失敗=${FAILED}" if [[ "${FAILED}" -gt 0 ]]; then echo "バックアップ検証結果: 失敗${FAILED}件 on $(hostname) — ${BACKUP_DIR}" \ | mail -s "[ALERT] backup verify: ${FAILED} failed" "${NOTIFY_TO}" 2>/dev/null || true exit 1 fi exit 0

このスクリプトをcronに登録するとき、バックアップ実行の翌朝に検証が走るよう時刻をずらします。

# バックアップ実行: 毎日 02:00 0 2 * * * /usr/local/bin/backup_with_checksum.sh # 検証実行: 毎日 06:00(バックアップ完了後に余裕を持って実行) 0 6 * * * /usr/local/bin/verify_backup.sh /backup/daily

バックアップ検証を含むシェルスクリプトの設計力を体系的に身につけたい方は、シェルスクリプト実践講座(Linux Master Pro)もご覧ください。現場で使える設計パターンを体系的に学べます。

トラブルシュート・よくあるエラー

sha256sum: 照合がFAILEDになるがファイルは壊れていない

sha256sumはファイルパスも含めてチェックサムファイルに記録します。チェックサム生成時と照合時でカレントディレクトリや絶対パスが違うと照合に失敗します。

解決方法: チェックサムファイルのあるディレクトリに cd してから sha256sum -c を実行する。またはスクリプト内で生成時・照合時のどちらもファイル名のみ(パスなし)を使うようにする。

# 生成時:ディレクトリに移動してからファイル名だけで生成 cd /backup/daily sha256sum data_20260825.tar.gz > data_20260825.tar.gz.sha256 # 照合時:同じディレクトリで実行 cd /backup/daily sha256sum -c data_20260825.tar.gz.sha256

tar -tzf が途中でエラーになるがgzip -tはOKと言う

gzip圧縮は正常でも、tar内部のブロック構造が壊れているケースです。gzip -tが通っても tar -tzf が失敗する場合は、アーカイブ内部に実際の問題があります。バックアップスクリプトが途中でkillされたか、書き込み中にディスクフルになったかを調査してください。

検証スクリプトがERRトラップを通らずに終了する

set -e を設定していても、if文やwhile文の条件式内では終了コードが非ゼロでもtrapが発動しません。条件式の外でコマンドを実行してから終了コードを変数に受け取るパターンで回避します。

# NG: if文の条件でset -eのtrapが発動しない if sha256sum -c "${SHA_FILE}"; then ... fi # OK: 別途実行してから結果を判定する sha256sum -c "${SHA_FILE}" # ここで失敗するとtrap ERRが発動する

本記事のまとめ

バックアップ整合性検証の設計をまとめます。

やりたいこと コマンド・設計
バックアップ時にチェックサムを生成する sha256sum archive.tar.gz > archive.tar.gz.sha256
チェックサムを照合して破損を検知する sha256sum -c archive.tar.gz.sha256
gzip圧縮の整合性を確認する gzip -t archive.tar.gz
tarアーカイブ全体を走査して検証する tar -tzf archive.tar.gz > /dev/null
検証失敗時に自動通知を送る trap 'on_error "$LINENO"' ERR でエラーハンドラを登録
照合時のパス不一致を防ぐ チェックサムファイルのディレクトリに cd してから照合する

バックアップの本当の価値は「リストアできる」ことで初めて証明されます。sha256sum照合とtar構造検証を自動化してcronで定期実行するだけで、「取れているつもり」のバックアップリスクを大幅に下げられます。検証スクリプトを整備することは、障害対応時間の短縮にもつながります。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
シェルスクリプト講座を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。