フルバックアップの転送量が問題になる場面
毎回すべてのデータを転送するフルバックアップは、設定がシンプルな反面、データ量が増えると転送時間や帯域を圧迫します。夜間バッチや定期ジョブのバックアップウィンドウが短い環境では、転送が完了しないケースが生じます。
差分バックアップは「前回のバックアップからの変更分だけを転送する」方式です。初回はフル転送が必要ですが、2回目以降は変更のあったファイルだけをコピーするため、転送量・転送時間ともに大幅に削減できます。Linux でこの仕組みを実現するには rsync が標準的な選択肢です。
rsync で変更分だけ転送する基本
rsync はデフォルトで、ファイルのタイムスタンプとサイズを比較し、変更があったファイルだけを転送します。まず SSH 経由でリモートサーバーへ転送する基本の形を確認します。
rsync -avz --delete /source/ user@backup-server:/destination/
主なオプションの意味
-a(アーカイブモード): パーミッション・オーナー・タイムスタンプ・シンボリックリンクをまとめて保持します。-v: 転送したファイルを一覧表示します。ログ確認やデバッグに役立ちます。-z: 転送時にデータを圧縮します。ネットワーク帯域が細い環境で効果があります。--delete: 送信元で削除されたファイルを、宛先からも削除します。ミラーリングが目的の場合に指定します。
送信元パスの末尾に / を付けると「そのディレクトリの中身」を転送します。付けないと「そのディレクトリ自体」が宛先に作られます。意図しない二重ネストを防ぐため、パスの末尾スラッシュは必ず意識してください。
–link-dest で複数世代を保持する
前述の基本形は「最新状態のミラー」を作るだけで、過去の状態に戻ることができません。誤削除や誤上書きに対応するには複数世代の保持が必要です。
--link-dest を使うと、変更のないファイルはハードリンクで参照し、変更されたファイルだけ実ファイルとしてコピーします。見かけ上は各世代が独立したフルバックアップのように見えながら、ストレージの実使用量は差分分だけで済みます。
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DST="user@backup-server:/backup"
rsync -avz \
--link-dest="${BACKUP_DST}/latest" \
/source/ \
"${BACKUP_DST}/${DATE}/"
ssh user@backup-server \
"ln -sfn /backup/${DATE} /backup/latest"
手順の流れは次のとおりです。
/backup/latestを基準に差分だけ/backup/日時/へコピーします。- コピー完了後、
/backup/latestシンボリックリンクを最新世代に付け替えます。 - 次回実行時は更新された
latestを基準に差分を計算します。
古い世代を削除したいときは /backup/日時/ ディレクトリを rm -rf するだけです。ハードリンクで共有している他世代のファイルには影響しません。
スクリプト化して定期実行する
上記の手順を1つのシェルスクリプトにまとめ、cron や systemd タイマーで定期実行します。ここでは cron の例を示します。
スクリプトを /usr/local/bin/backup-diff.sh として保存し、実行権限を付与します。
#!/bin/bash
set -euo pipefail
SOURCE="/source/"
BACKUP_USER="user"
BACKUP_HOST="backup-server"
BACKUP_BASE="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
DST="${BACKUP_USER}@${BACKUP_HOST}:${BACKUP_BASE}"
rsync -az \
--link-dest="${DST}/latest" \
"${SOURCE}" \
"${DST}/${DATE}/"
ssh "${BACKUP_USER}@${BACKUP_HOST}" \
"ln -sfn ${BACKUP_BASE}/${DATE} ${BACKUP_BASE}/latest"
chmod +x /usr/local/bin/backup-diff.sh
cron に登録するには crontab -e で次の行を追加します。毎日深夜2時に実行する例です。
0 2 * * * /usr/local/bin/backup-diff.sh >> /var/log/backup-diff.log 2>&1
SSH 接続にパスワードが必要な環境では、事前に SSH 公開鍵認証を設定しておく必要があります。ssh-keygen で鍵ペアを生成し、ssh-copy-id でバックアップ先サーバーに登録してください。
転送内容と世代を確認する
実際に転送されるファイルを事前に確認するには、--dry-run(-n)オプションを使います。ファイルは転送されず、対象ファイルの一覧だけが表示されます。
rsync -avzn /source/ user@backup-server:/destination/
バックアップ先に保存されている世代の一覧は次のコマンドで確認できます。
ssh user@backup-server "ls -lt /backup/ | head -20"
各世代のディスク使用量は du コマンドで確認できます。ハードリンクが共有されているため、各ディレクトリの見かけ上のサイズは実際の使用量より大きく表示されます。--apparent-size と実サイズの差が、ハードリンクによって節約できている量の目安になります。
ssh user@backup-server "du -sh /backup/2026*"
よくあるつまずきと対処
–link-dest に存在しないパスを指定すると差分にならない
初回実行時に /backup/latest が存在しないと、rsync はエラーを出さずに全ファイルをフルコピーします。初回実行後に latest シンボリックリンクが正しく作成されているかを必ず確認してください。
ファイルシステムの違いでハードリンクが機能しない--link-dest によるハードリンクは、送信先の同一ファイルシステム内でのみ有効です。/backup/latest と /backup/日時/ が同じパーティション上にある必要があります。異なるマウントポイントをまたぐとハードリンクではなく実ファイルのコピーになります。
タイムスタンプのずれで全ファイルが転送される
送信元と送信先でシステム時刻が大きくずれていると、rsync がすべてのファイルを変更ありと判断して全転送します。chrony や ntpd で時刻同期を維持してください。
世代を積み続けてディスクが枯渇する
世代を増やし続けるとディスクが逼迫します。古い世代を自動削除するスクリプトを組み合わせるか、保持日数を決めて運用してください。一般的には直近7世代や30日分を目安にする方法がよく用いられます。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
