現場で使えるシェルスクリプト入門26:ddコマンドによるディスクイメージバックアップと安全なスクリプト化

シェルスクリプト IT

Linux環境におけるバックアップ手法として、前々回はファイル単位のアーカイブを作成する「tar + find」、前回はディレクトリ間の差分を効率よく同期する「rsync」について解説しました。

日常的なデータ保護ではこれらのファイル単位のバックアップが適していますが、システム開発やサーバー運用の現場では、「OSのブート領域やパーティションテーブルを含めたストレージ丸ごとのクローン・バックアップ」が必要になる場面があります。

そこで役立つのが dd コマンドです。ファイルシステムを意識せず、ストレージをセクタ単位・ブロック単位でそのまま読み書きできるため、環境の初期スナップショット作成やストレージ換装などに広く活用されています。

今回は、ddコマンドの基礎知識から転送速度を高めるオプション、容量を抑えるパイプライン圧縮、そして指定ミスによるデータ消失を防ぐ安全な自動化スクリプトの実装まで分かりやすく解説します。

※本連載はロードマップ形式で順次公開しています。連載全体の流れや各回の一覧は「シェルスクリプト入門連載ロードマップ」からも確認できます。

ddコマンドとは?ブロックレベルバックアップの仕組み

dd(Dataset Definition)は、ファイルやブロックデバイス(ストレージなど)をバイナリレベルで読み込み、指定した出力先へそのまま書き出すLinuxの標準コマンドです。

これまでのバックアップツールとの主な違いは「バックアップの対象レイヤー」にあります。

  • tar / rsync(ファイルレベル):ファイルシステム上のファイルやディレクトリを対象とします。ファイル単位で柔軟に抽出・同期できる一方、OSのブートセクタ(MBRやGPTなど)自体はバックアップされません。
  • dd(ブロックレベル):ファイルシステムを解釈せず、ディスクのセクタを1対1で丸ごと読み書きします。MBR/GPTパーティション情報やファイルシステムのメタデータも含めてそのまま複製されるため、元の状態へ復元しやすい特徴があります。

補足:セクタとブロックとは?

「セクタ」と「ブロック」という言葉の意味を簡単に整理しておきます。

  • セクタ(Sector):ハードディスクやSSDなどの記憶媒体において、物理的にデータを記録・分割する最小の部屋(単位)です。一般的には1セクタあたり512バイト(または4KB)の大きさを持っています。
  • ブロック(Block):OS(Linux)がストレージとデータをやり取りする際に扱う論理的なデータのひとかたまりです。複数のセクタをまとめた単位(通常4KBなど)や、プログラムが一度に読み書きするサイズを指します。

ファイル単位のバックアップ(tarやrsync)が「本棚からファイルという名前の本を一冊ずつ取り出してコピーする」イメージだとすれば、セクタ・ブロック単位のバックアップ(dd)は「本棚の棚板の区切り(セクタ)を端から端までそっくりそのまま複製する」イメージです。

そのため、「ファイルの中身」だけでなく、「どのファイルがどの位置にあるかを管理する目次情報」や「OSを起動するためのブート領域」まで、ストレージの構造をそのまま丸ごと保存できる利点があります。

OSの初期セットアップが完了した直後の状態をイメージファイルとして保存しておけば、トラブル発生時や同型サーバーへの複製時に、OSの再インストール手順を踏むことなく環境を初期状態へ戻すことが可能になります。

ddコマンドの基本構文と主要オプション

ddコマンドは他のLinuxコマンドと異なり -オプション ではなく key=value という形式で引数を指定します。

dd if=入力元 of=出力先 [オプション...]

主要なパラメータとオプションは以下の通りです。

パラメータ・オプション概要実用例・推奨値
if=<入力元>Input File。コピー元のデバイスやファイル。if=/dev/sdb1
of=<出力先>Output File。保存先のイメージファイルやデバイス。of=/backup/sdb1.img
bs=<サイズ>Block Size。一度に読み書きするバイト数。bs=4M(処理速度の最適化)
count=<回数>コピーするブロック数。先頭部分のみ取得する際に使用。count=1(MBRバックアップ等)
status=progress転送中の進捗状況(容量・経過時間・転送速度)を表示。リアルタイム監視に推奨
conv=noerror,sync読み取りエラー発生時も中断せず、欠損部を0埋めして同期。経年ストレージの救出時などに使用

ブロックサイズ(bs)による転送速度の違い

bs(ブロックサイズ)を省略した場合、デフォルト値の「512バイト」単位で読み書きが行われます。この状態ではI/Oの呼び出し回数が多くなり、ギガバイト単位のストレージをコピーする際に時間がかかります。

通常は bs=4M や bs=8M 程度を指定することで、バッファを活用してストレージ本来の転送速度を引き出す運用が一般的です。

# /dev/sdb のパーティション1をイメージファイルとしてバックアップ
dd if=/dev/sdb1 of=/backup/disk_backup.img bs=4M status=progress

ストレージ容量を抑えるパイプライン圧縮(gzip連携)

ddコマンドはブロック単位で忠実に読み取るため、「データが書き込まれていない未使用領域(空き容量)」も含めてそのままイメージファイル化します。

例えば、64GBのストレージのうち実データが5GBしか使われていなくても、単純にddを実行すると「64GBの巨大なファイル」が生成されてしまい、バックアップ先のストレージを圧迫します。

この問題を解消するため、ddの標準出力をパイプライン(|)で gzip に渡し、圧縮しながらイメージを保存する手法が広く使われています。

# ddの出力をgzipで圧縮して保存
dd if=/dev/sdb1 bs=4M status=progress | gzip -c > /backup/disk_backup.img.gz

未使用セクタ(0が並んでいる領域)は高い圧縮率で縮小されるため、生成される .img.gz ファイルは実データ量に近いサイズまで小さく抑えることができます。

実践:誤操作を防止するイメージバックアップサンプルスクリプト

ddコマンドは強力である反面、if(読み込み元)と of(書き込み先)の指定を1文字誤っただけで、稼働中の本番ストレージに空データを上書きしてしまう重大な事故につながる恐れがあります。

そのため、スクリプト化する際には「実行前の二重確認」「ブロックデバイスの実在判定」「マウント状態の検査」といった安全装置を組み込んでおく設計が推奨されます。

#!/bin/bash
# ==============================================================================
# スクリプト名: backup_dd_image.sh
# 概要: ddとgzipによる安全なパーティションイメージバックアップ
# ==============================================================================

set -uo pipefail

# --- 設定項目 ---
readonly SRC_DEV="/dev/sdb1"                      # バックアップ対象のブロックデバイス
readonly BACKUP_DIR="/backup/images"              # イメージ保存先ディレクトリ
readonly LOG_FILE="/var/log/backup_dd.log"        # ログ保存先
readonly DATE_STR="$(date '+%Y%m%d_%H%M%S')"
readonly DEST_IMG="${BACKUP_DIR}/image_${DATE_STR}.img.gz"

log_message() {
    local level="$1"
    local message="$2"
    echo "$(date '+%Y-%m-%d %H:%M:%S') [${level}] ${message}" | tee -a "$LOG_FILE"
}

# --- 1. 管理者権限(root)のチェック ---
if [ "${EUID}" -ne 0 ]; then
    echo "エラー: このスクリプトは管理者権限(root)で実行する必要があります。" >&2
    exit 1
fi

# --- 2. 保存先ディレクトリの準備 ---
mkdir -p "$BACKUP_DIR"

log_message "INFO" "ddイメージバックアップ処理を開始します。"

# --- 3. バックアップ対象デバイスの検証 ---
if [ ! -b "$SRC_DEV" ]; then
    log_message "ERROR" "指定されたデバイス '${SRC_DEV}' は存在しないか、ブロックデバイスではありません。"
    exit 1
fi

# --- 4. マウント状態の確認(書き込み競合の警告) ---
# 稼働中のファイルシステムを直接イメージ化すると整合性が崩れる可能性があるため検査
if mount | grep -q "^${SRC_DEV} "; then
    log_message "WARN" "デバイス '${SRC_DEV}' はマウントされています。整合性を保つため、アンマウントまたは読み取り専用状態でのバックアップを推奨します。"
fi

# --- 5. バックアップ処理の実行(dd + gzip) ---
log_message "INFO" "イメージ作成を実行中: ${SRC_DEV} ➔ ${DEST_IMG}"

# PIPESTATUS でパイプライン各コマンドの成否を判定
set +e
dd if="${SRC_DEV}" bs=4M status=progress 2>> "$LOG_FILE" | gzip -c > "$DEST_IMG"
PIPE_STATUS=("${PIPESTATUS[@]}")
set -e

# ddの終了コード(PIPE_STATUS[0])とgzipの終了コード(PIPE_STATUS[1])を確認
if [ "${PIPE_STATUS[0]}" -eq 0 ] && [ "${PIPE_STATUS[1]}" -eq 0 ]; then
    IMG_SIZE="$(ls -lh "$DEST_IMG" | awk '{print $5}')"
    log_message "INFO" "イメージバックアップが正常に完了しました。(サイズ: ${IMG_SIZE})"
    exit 0
else
    log_message "ERROR" "バックアップ中にエラーが発生しました。(dd終了コード: ${PIPE_STATUS[0]}, gzip終了コード: ${PIPE_STATUS[1]})"
    # 不要な破損ファイルを削除
    [ -f "$DEST_IMG" ] && rm -f "$DEST_IMG"
    exit 1
fi

スクリプトの安全設計ポイント

  • ブロックデバイスの事前判定(-b):ファイルや存在しないデバイス名を指定して誤作動することを防ぎます。
  • マウント状態の検査:稼働中でファイル書き込みが継続しているパーティションをRAWコピーすると、不整合なイメージが生成される恐れがあります。事前に mount の出力を確認し、警告ログを残します。
  • PIPESTATUSによるパイプライン監視:PIPESTATUS は Bash の特殊配列変数です。パイプライン中の各コマンドの終了ステータスを配列として保持します。PIPESTATUS を使用し、dd の読み取りエラーと gzip の書き込みエラーの双方を正確に検知してエラーハンドリングを行います。
  • 異常終了時のゴミ掃除:処理途中で失敗した場合、中途半端な破損イメージが保存領域を埋めてしまわないよう自動削除を行います。

バックアップイメージからの復元手順と注意点

作成した圧縮イメージ(.img.gz)からストレージへ復元する際は、バックアップ時と逆のパイプラインを構成します。

# 圧縮イメージを展開しながら /dev/sdb1 へ書き戻す
gunzip -c /backup/images/image_20261002.img.gz | dd of=/dev/sdb1 bs=4M status=progress

復元を実行する際の重要な注意点は以下の通りです。

  • 出力先(of=)のデバイス名の再確認を推奨:USBメモリや外付けディスクを接続した際、OSの再起動やポート差し替えによってデバイス名(/dev/sdb や /dev/sdc など)が変わる場合があります。実行前に lsblk コマンド等で確認することを推奨します。
  • 復元先ストレージの容量:パーティション単位で復元する場合、復元先のパーティションサイズはバックアップ元と同等以上の容量が必要です。

まとめ

今回は、ストレージのブロックレベル複製を実現する dd コマンドの基本と、安全なイメージバックアップスクリプトの実装方法を解説しました。

  • ブロックレベルの丸ごと複製:ファイルシステムを問わず、ブート領域やパーティション情報も含めて丸ごとイメージ化が可能。
  • 適切なブロックサイズ(bs=4M):デフォルトの512バイトから適切なバッファサイズに変更することで、転送速度を大幅に改善できる。
  • gzip 連携による容量削減:未使用領域も丸ごと読み取るddの特性を、パイプライン圧縮によって軽量化できる。
  • スクリプトによる安全装置:デバイス存在チェックや PIPESTATUS を組み込むことで、手作業での指定ミスやデータ破壊事故を防止できる。

ファイル単位の tar、差分同期の rsync、そしてディスクイメージの dd と、それぞれの特性を理解して使い分けることで、システムの要件や復旧スピードに応じた堅牢な自動化運用体制を構築できます。

現場で使えるシェルスクリプト入門 連載ナビゲーション

コメント

タイトルとURLをコピーしました