19 September 2016

rsync 差分バックアップ

rsyncを使って、差分バックアップを行う

基本構文

/home/user/data1/home/user/data2の2つのディレクトリ内のファイルを、/media/user/strage/にバックアップする

初回のフルバックアップは、001というサブディレクトリ内に格納する

rsync -av /home/user/data1 /home/user/data2 /media/user/strage/001/

2回めからの差分バックアップは、002, 003, ... 00n というサブディレクトリに格納する。 前回のバックアップ格納ディレクトリを--link-destスイッチで指定する

rsync -av --link-dest=/media/user/strage/001/ /home/user/data1 /home/user/data2 /media/user/strage/00n/

2回め以降のディレクトリ内には、変更のあった差分ファイルのみではなく、その他の変更のないファイルは前回のディレクトリ内の各ファイルへ「ハードリンク」を作った形で全て格納されている。

バックアップ時のファイル転送(コピー)や、バックアップ格納ディスク内で消費される「容量」は、変更のあったファイルのみであるため、「差分バックアップ」といえる。

※ 重要 : ハードリンクを作るため、バックアップ格納ディスクは Ext ファイルシステムでフォーマットされている必要がある。

deleteスイッチ : バックアップ対象内のファイルが削除された場合の挙動

rsyncに--deleteスイッチを指定していないため、バックアップ元で削除されたファイルは、バックアップ先ではどうなるのか…

・バックアップ元で削除されたファイルは、差分が作られない
・削除される以前に作られた過去のバックアップ格納ディレクトリ内のファイルは削除されない。

つまり、バックアップ元でファイルが削除されても、過去の差分ディレクトリを探せばファイルを復活できるということですね。

※ 毎回同じバックアップ格納ディレクトリにバックアップを繰り返す場合

次のように、--deleteスイッチを付ければ「擬似差分」バックアップができるが、バックアップ元で削除されたファイルはバックアップ格納先でも削除されてしまうので、復活することが出来ない。

rsync -av --delete /home/user/data1 /home/user/data2 /media/user/strage/毎回同じディレクトリ/

自動バックアップスクリプト

緑着色の部分は「プレビュー」、青着色の部分が「実際のバックアップ処理」を示している。

#!/bin/sh
 
echo "rsync バックアップ スクリプト"
echo " "
echo -n "バックアップ用ストレージが準備出来たら、Enter キーを押してください :"
read user_input
  
# バックアップ対象のディレクトリ(末尾は文字で終わる, 複数指定可, スペースで区切る)
backup_source_dir="/home/user/data1 /home/user/data2 /home/user/Documents /home/user/Dropbox"
 
# バックアップ先 (末尾は / で終わること)
backup_dest_dir="/media/user/BACKUP_USB/backup/"
 
# 今回バックアップ先のサブディレクトリ名(日時文字列)
time=`date +%Y%m%d-%H%M`
 
# 除外パターン
exclude_pattern="--exclude='\$RECYCLE*/' --exclude='.Trash*/' --exclude='*.bak' --exclude='System\ Volume\ Information*/'"
 
# その他のrsyncスイッチ
extra_switch="--modify-window=2 --stats"
 
# 前回のバックアップサブディレクトリ名
#prev_time=$(ls -1t $backup_dest_dir | head -1)
#prev_dest_dir="$backup_dest_dir$prev_time"
prev_dest_dir=$(find $backup_dest_dir -maxdepth 1 -name '[0-9]*' -print | sort -r | head -1)
 
# 1 秒待つ
sleep 1
 
echo " "
echo "=== 設定 ==="
echo "バックアップ元"
echo " \033[0;33m$backup_source_dir\033[m"
echo "バックアップ格納先"
echo " \033[0;33m$backup_dest_dir$time\033[m"
echo "前回のバックアップ格納先 (差分機能時に利用)"
echo " \033[0;36m$prev_dest_dir\033[m"
 
echo " "
echo "=== 機能選択 ==="
echo -n " f: フルバックアップ, d: 差分バックアップ  [f/d] ? :"
read user_input
 
if [ "$user_input" != 'f' -a "$user_input" != 'd' ]; then
  echo "想定外の入力のため、中止しました"
  exit
fi
 
echo " "
echo "=== プレビュー選択 ==="
echo -n "実際のファイル操作前に、プレビューしますか [y/n] ? :"
read user_input_preview
 
if [ "$user_input_preview" != 'y' -a "$user_input_preview" != 'n' ]; then
  echo "想定外の入力のため、中止しました"
  exit
fi
 
# プレビュー
if [ "$user_input_preview" = 'y' ]; then
 
  if [ "$user_input" = 'f' ]; then
    cmd_str="rsync -avn $extra_switch $exclude_pattern $backup_source_dir $backup_dest_dir$time"
  elif [ "$user_input" = 'd' ]; then
    cmd_str="rsync -avn $extra_switch --link-dest=$prev_dest_dir $exclude_pattern $backup_source_dir $backup_dest_dir$time"
  fi
 
  echo " "
  echo "=== プレビュー開始 ==="
  echo "\033[0;32m$cmd_str\033[m"
  echo " "
  eval $cmd_str
  echo "=== プレビュー終了 ==="
 
fi
 
if [ $user_input = 'f' ]; then
  cmd_str="rsync -av $extra_switch $exclude_pattern $backup_source_dir $backup_dest_dir$time"
elif [ $user_input = 'd' ]; then
  cmd_str="rsync -av $extra_switch --link-dest=$prev_dest_dir $exclude_pattern $backup_source_dir $backup_dest_dir$time"
fi
 
echo " "
echo "=== 実行前確認 ==="
echo "\033[0;32m$cmd_str\033[m"
echo " "
echo -n "このコマンドを実行してよいですか [y/n] ? :"
read user_input
 
if [ -z $user_input ]; then
  echo "中止しました"
  exit
elif [ $user_input = 'y' ]; then
  eval $cmd_str
else
  echo "中止しました"
  exit
fi
 
echo -n "処理完了。何かキーを押してください [Enter] :"
read user_input

このスクリプトを、1週間に1回「自動起動するアプリケーション」から呼び出す場合、次のようなスクリプトを作成すれば良い

#!/bin/sh
 
day_of_week=`date +%w`
 
# 毎週 水曜日にバックアップを行う (%wは0:日曜, 1:月曜, …)
if [ "$day_of_week" = "3" ] ; then
  # 10分 待つ
  # 起動直後のセキュリティスキャンや、デバッグ再起動テスト等を回避するため5分待ちます
  sleep 300
  gnome-terminal -e /usr/local/bin/rsync_autobackup.sh &
fi

青で着色した部分で、Gnome端末(GUI)を使ってスクリプトを実行するようにしている