rsyncによるハードリンク世代バックアップ

ozy's labo.


rsyncによるハードリンク世代バックアップ

本記事では,Linux環境でのrsyncを使った**世代バックアップ(世代管理)**の方法について解説します.
特にハードリンクを活用することで,ディスク容量を節約しつつ,各世代をフルバックアップのように扱う方法を説明します.

前提条件

  • Linux/Unix環境
  • バックアップ元ディレクトリ: /data
  • バックアップ先ディレクトリ: /backup
  • 世代ディレクトリは日付形式: YYYYMMDD
  • ファイルシステム: ext4 (rsync運用で十分)

初回バックアップ

初回バックアップは単純なrsyncコピーで実行します.

#!/bin/bash

SRC="/data/"
DST="/backup/$(date +%Y%m%d)"

# 初回は普通にコピー
rsync -a --delete "$SRC" "$DST"
  • オプション説明
    • -a: アーカイブ(再帰+属性保持)
      • –delete: 元にないファイルを削除
      • 初回は単純コピーでOKです.

2回目以降の世代バックアップ(ハードリンク利用)

ハードリンクを利用すると,前回バックアップと同じファイルはリンク化され,ディスク容量を節約できます.

#!/bin/bash

SRC="/data/"
DST="/backup/$(date +%Y%m%d)"
PREV="$(ls -1 /backup | sort | tail -n1)"  # 直前世代

rsync -a --delete --link-dest="/backup/$PREV" "$SRC" "$DST"
  • –link-dest: 前回世代のディレクトリを指定することで,同一ファイルはハードリンクに
  • 新規・更新ファイルのみコピーされ,古い世代は残ります

世代管理(prune)

古い世代を削除してディスク容量を管理する操作をpruneと呼びます.

# 例: 直近7世代だけ残す
(
    cd $DST_PHYS
    echo "delete older gen, keep gens:$KEEP_GEN"
    printf '%s\n' 20* | sort
    for d in $(printf '%s\n' 20* | sort | head -n -$KEEP_GEN); do
	rm -rI "$d"
    done
)
  • 古い世代だけを明示的に削除することで,安全にディスク容量を回収できます.
  • 注意点: ハードリンクは他の世代で参照されている場合,データ自体は消えません.

ハードリンクの特徴

  • 同じinodeを指す複数のファイル名が存在する
  • リンクカウントが0になったときに初めてディスク上のデータが解放される
  • 世代バックアップでは,個別世代を削除しても他の世代が残っていればデータは消えません
  • 全世代まとめて削除(例: rm -rf /backup)するとデータは全て消えます

運用上のベストプラクティス

  • バックアップ専用のディレクトリを用意
  • 世代削除はまとめてではなく,古い世代だけを明示的に削除
  • cronなどで自動化可能
  • ディスク容量が大きい場合,ext4で十分
  • ログを残すとトラブル時に安心

まとめ

  • rsync + –link-dest で見た目はフルバックアップだが,容量効率は差分バックアップ
  • 古い世代を削除することでディスク容量を制御できる(prune)
  • ハードリンクの性質を理解していれば,安全に世代バックアップを運用可能

注意

インフラ慣れした管理者には言うまでもないですが,rsync はパス最後の / を厳格に判定します.
これは,–link-dest= に対しても同様です.

例えば,

  • src: mnt/storage/wd
  • dst: mnt/crypt/wd/20260315

の様な環境だとします.
この状態で,上記に示してきた様な –link-dest=20260314 みたいな指定を行うとします.
つまり,

rsync -ax --delete --link-dest=20260314 /mnt/storage/wd/ /mnt/crypt/wd/20260315/

ですね.
実はこれは NG です.この場合,rsync は,リンク判定比較先として,/mnt/crypt/wd/20260315/20260314/ を見に行きます.
結果,そこにはファイルがないので,差分ではなく,全部コピーとなってしまいます.
正解は,

rsync -ax --delete --link-dest=/mnt/crypt/wd/20260314/ /mnt/storage/wd/ /mnt/crypt/wd/20260315/

と,link-dest= もフルパス指定する必要があります.


Date: 2026-03-15

Author: ozyukiwo

Created: 2026-03-17 火 14:16

Emacs 26.3 (Org mode 9.1.9)

Validate