rsyncの差分バックアップを自動化したい、日付でフォルダを自動で作る方法を教えてください。

現在、rsyncでFilesフォルダの差分バックアップをとっています。


毎日とっているので、今晩は

$ rsync -av --link-dest=../20140818 /Volumes/Files/ /Volumes/Backup/20140819

でとる予定なのですが、これを自動化したいんです。

Launchdを使うとできるようなのですが、

日付をその日に対応して自動で変更する方法が分かりません。

どなたかご教示いただけませんでしょうか。


---

Mac mini Late 2012

OS X 10.8.5

Mac mini (Late 2012), OS X Mountain Lion (10.8.5)

投稿日 2014/08/18 23:36

返信
返信: 16

2014/08/20 03:20 T22T への返信

上記の通りシェルスクリプトを作り、実験用のフォルダでテストして、成功しました。

T22T様、どうもありがとうございます。

ただ、うまくいく場合といかない場合がありました。以下の通りです。


1.ターミナル入力でrsync → ターミナル入力で差分バックアップ → 成功

2.ターミナル入力でrsync → シェルスクリプトで差分バックアップ → 失敗

3.シェルスクリプトでrsync → ターミナル入力で差分バックアップ → 失敗

4.シェルスクリプトでrsync → シェルスクリプトで差分バックアップ → 成功


これは、そういう仕様なのでしょうか??

今まで行なってきたのは1なので、また一からrsyncするとなるとHDDを増やさないといけません。

何かご存知でしたら教えていただきたいです。

2014/08/21 17:28 T22T への返信

T22T様、ありがとうございます。


2と3の場合、エラーの表示はなく、ただ全てコピー(差分コピーではない)してしまいます。

この『参照先が無ければエラーを出さずに全てをコピー(今回の参照先は --link-dest=../$yesterday ですね)』

rsyncの挙動としては普通なのですが、上記のように成功と失敗が分かれてしまう理由が不明です。


サポートコミュニティの皆様、

なにとぞご指導いただきたく、よろしくお願いいたします。

2014/08/21 20:51 kmiya への返信

度々、失礼致します。 はやり、『参照先が無ければエラーをださずに』とのことですので、参照できていない、パスの指定が間違っている可能性があるのではないでしょうか? つまり、定義した変数を参照できていないのでは(スコープの問題)? と思います。 rsyncのコマンドの実行とバックアップのコマンドの実行が分かれているのですが、具体的にどのような方法で定義した変数を参照しているのかを確かめてみるとよいかもしれないです。  

2014/08/22 02:30 kmiya への返信

以前rsyncでほぼTimeMachineと同様の増分バックアップを実現するシェルスクリプトを作成したのですが,プロバイダを変更したため該当ページが消えてしまったようなので,そのコードを下記に示します。参考になれば幸いです。


#!/bin/bash

#次の行にバックアップ先のボリューム名を直接指定するか,引数にバックアップ先ボリュームをドラッグアンドドロップして指定すること。

dest=/Volumes/backup01



#ディレクトリパスが引数として指定された場合,整形(最後のスラッシュを取る)してバックアップ先のボリューム名にする。

#それ以外の引数はディレクトリを整理する深さを決めるオプションスイッチとみなす。

if [ -d "$1" ]; then

dest=$(echo -n "$1" | sed 's/\/$//')

if [ "$2" ] ; then consoli=$2 ; fi

else

consoli=$1

if [ -d "$2" ]; then

dest=$(echo -n "$2" | sed 's/\/$//')

fi; fi



#このコマンド($0)をcron登録する際,コマンド名を絶対パスにする必要がある。

this=$(pwd)/$0

if [ -x $this ]; then

#コマンド名が相対パスだった場合,以下の手順で絶対パスに変換。(参考url=http://richlab.org/shellscript/ssr_support.html)

this=$(echo -n "$this" | sed 's/\/\{2,\}/\//g')

this=$(echo -n "$this" | sed 's/\/$//')

this0=""

while [ "$this" != "$this0" ]; do

this0="$this"

this=$(echo -n "$this" | sed 's/\/\.\//\//')

this=$(echo -n "$this" | sed 's/\/\.$//')

done

this0=""

while [ "$this" != "$this0" ]; do

this0="$this"

this=$(echo -n "$this" | sed 's/^\/\.\.\//\//')

if [ "$this" != "$this0" ]; then

continue

fi

this=$(echo -n "$this" | sed 's/^\/\.\.$/\//')

if [ "$this" != "$this0" ]; then

break

fi

this=$(echo -n "$this" | sed 's/\/[^\/]\{1,\}\/\.\.\//\//')

if [ "$this" != "$this0" ]; then

continue

fi

this=$(echo -n "$this" | sed 's/\/\([^\/]\{1,\}\)\/\.\.$//')

done

[ -z "$this" ] && this="/"

else

#コマンド名が絶対パスだった場合。

this=$0

fi



#このシェルスクリプトが置かれたディレクトリ(フォルダ)をバックアップ対象とする。

src=$(dirname $this)

user=$dest/$(basename $src)

now=$(date +%Y/%m/%d/%H)

base=$user/$now

log=$user/log/log.txt

start=$(date +%M:%S)



#バックアップ先ボリュームがマウントされているか確認する。

if ! df | grep "$dest\$" > /dev/null ; then echo "$dest not mounted."; exit 1 ; fi

#バックアップ先ボリュームがDOSフォーマットでないか確認する。

if diskutil list $dest | grep "DOS_FAT_32" ; then exit 2 ; fi

#バックアップ済みでないか確認する。この確認は不要かもしれない。

#if [ -d $base ] ; then exit 3 ; fi



#rsync ではバックアップ先の一つ上のフォルダまでは事前に作成しておく必要がある。

if [ ! -d $(dirname $base) ] ; then

mkdir -p $(dirname $base) && chmod -R 750 $(dirname $base) || exit 4

fi



#アクセス権不足でバックアップできないものがあった時のメッセージ。

warn="Some files and/or directories did not backuped."



cd $src

if [ -f $log ]; then

#2回目以降のバックアップなので前回バックアップ済みのものはそこからのハードリンクにする。

lastline=$(tail -n 1 $log)

preb=$user/$(printf "%.13s" "$lastline")

rsync -aE --exclude="*.sparseimage" --exclude="Library/Caches/Safari/" --link-dest=$preb ./ $base || echo $warn

if [ "$consoli" != "-l" -a "$consoli" != "-n" ] ; then

#日が変わったら,前日のバックアップは最後のものだけ残して削除する。TimeMachineは24時間分残すが,そこまで高級では無い。

yesterday=$(dirname $preb)

today=$(dirname $base)

if [ $yesterday != $today ] ; then

tmp=$user/yesterday

[ -d $tmp ] && rm -fR $tmp ||

mv $preb $tmp && rm -fR $yesterday && mv $tmp $yesterday

if [ "$consoli" != "-d" ] ; then

#月が変わったら,前月のバックアップは最後のものだけ残して削除する。TimeMachineは1週間単位だが,そこまで高級では無い。

lastmonth=$(dirname $yesterday)

thismonth=$(dirname $today)

if [ $lastmonth != $thismonth ] ; then

tmp=$user/lastmonth

[ -d $tmp ] && rm -fR $tmp ||

mv $yesterday $tmp && rm -fR $lastmonth && mv $tmp $lastmonth

if [ "$consoli" != "-m" ] ; then

#年が変わったら,前年のバックアップは最後のものだけ残して削除する。TimeMachineは残り容量で調節するが,そこまで高級では無い。

lastyear=$(dirname $lastmonth)

thisyear=$(dirname $thismonth)

if [ $lastyear != $thisyear ] ; then

tmp=$user/lastyear

[ -d $tmp ] && rm -fR $tmp ||

mv $lastmonth $tmp && rm -fR $lastyear && mv $tmp $lastyear

fi; fi; fi; fi; fi; fi

else

#ログファイルが無いので,最初のバックアップ。

#ダブルクリックでこのコマンドを実行できるファイルを作成する。

xname=$user/inc_backup.command

echo "#!/bin/sh" > $xname

echo "x=$this; [ -x \$x ] && \$x $dest -l" >> $xname

mkdir -p $(dirname $log) && chmod -R 750 $user

if [ "$USER" = "$(basename $user)" ] ; then

chown -R $USER $user

if [ ! "$USER" = "root" ] ; then

#このコマンドを起動したユーザのデスクトップにこのコマンドを実行するショートカットアイコンを作成する。

[ -d $HOME/Desktop -a -e $xname ] && ln -s $xname $HOME/Desktop/$(basename $user)_backup

fi

else

[ "$SUDO_USER" = "$(basename $user)" ] && chown -R $SUDO_UID:$SUDO_GID $user

fi

rsync -aE --exclude="*.sparseimage" --exclude="Library/Caches/Safari/" ./ $base || echo $warn

fi



#ログファイルに開始日時と終了時刻とディスク使用量を追記で記録する。

echo "$now:$start;$(date +%T),$(df | grep "$dest\$")" >> $log



#root権限で起動されている場合,終了時刻の1時間後から毎時刻(分が同じときに)このコマンドをroot権限で実行するように登録する。

if [ "$USER" = "root" ] ; then

crontab=$(crontab -lu root 2> /dev/null)

#このコマンドが既に登録されていないか確認する。

if ! echo "$crontab" | grep "$this" > /dev/null; then

crontab=$(echo "$crontab"; echo "$(date +%M) * * * * x=$this; [ -x \$x ] && \$x $dest $consoli")

#未登録の場合,既存のcrontabにこのコマンドを追加したものに登録し直す。

echo "$crontab" | crontab -u root

fi; fi

2014/08/25 22:58 kanekaka への返信

記憶が薄れていて先のスクリプトが何故そのようになっているのかあやふやですが,何か理由があってこのようなコードになっています。


まず,定期的に処理を自動実行させる仕組みとしてUNIXにはcronという仕掛けがあって,それをコントロールするコマンドがcrontabです。

最近のOS Xで有効かどうかは分かりません。OS XではなるべくLaunchdを使うことが望ましいので,あくまでも上記はTiger(OS X 10.4)用と思って下さい。

Launchdを使う予定なら,最後の段落は削除した方がよいでしょう。


また外付けボリュームが常にマウントされているかは保証されないと思いますので,万が一マウントされていない時に自動実行されると,起動ディスクの中に新たにバックアップが作成されてしまうかもしれません。したがってバックアップ先ボリュームの有無の確認が必須と思います。

コマンドの実行結果に応じて処理を変えるために「パイプ」という機能を使っています。


またUNIXにはファイルの有無等いろいろと調べるtestコマンド(大括弧「[ ]」)があります。


毎日必ず実行することを保証できるのであれば前回の実行日をyesterdayに決めつけてもいいかも知れませんが,保証できない場合にどうするかを考えてみて下さい。その解の一つとして私はログファイルを作成して前回の実行時間を記録する方法を選びました。「リダイレクション」という機能を使っています。


とりあえず思い出した範囲です。ご参考まで。


改めて見直したところ,こまめにアクセス権を設定している(chmodコマンド)点も気になります。コマンド実行者によって作成されたバックアップのアクセス権に差が生じていることへの対応だったような気がします。ご参考まで。

2014/08/27 01:27 kanekaka への返信

先のスクリプトの使い方文書が見つかりましたので,転載しておきます。シェルスクリプトの理解の助けになれば幸いです。尚,先の投稿で「パイプ」と書いたのは正確には「パイプライン(|)あるいはリスト(&&, ||, ;)」と呼ばれるようです。詳しくはbashのマニュアルを読んで下さい。大昔にテキトーな用語で覚えた所為で,混乱させてすみません。


はじめに:

 このソフトウェア(pTimeMachine)は10.4(Tiger)以降のMac OS Xのみで使えます。10.3(Panther)以前では使えません。バックアップ先としてMacOS拡張(HFS+)フォーマット等ファイルアクセス権を適切に扱えるボリュームが必要です。増分バックアップ時でもフルバックアップ状態が作成されます。前回バックアップと重複するファイルはハードリンクで作成されるのでディスク消費量は最小限に抑えられます。前回バックアップ時から日付が変わると,前回バックアップ時の1日分はYYYY/MM/DD形式のフォルダ一つに整理されます。最後のYYYY/MM/DD/HHフォルダの分が残ります。同様に1ヶ月分,1年分も順次過去のバックアップはフォルダの階層が浅くなっていきます。


使い方その1(アイコンのダブルクリックにより手動で増分バックアップを実行する。):

 準備のために,最初だけターミナルによる簡単な操作が必要です。バックアップを取りたいフォルダの直下に“pTimeMachine”をコピーします。ターミナルを起動して先ほどコピーして出来上がったファイルをターミナルウィンドウへドラッグアンドドロップします。続けてバックアップ先のボリュームアイコンをターミナルウィンドウへドラッグアンドドロップします。最後にターミナル上でリターンキーを押してコマンドを実行します。最初のバックアップが開始するとともに,デスクトップ上にターミナルコマンドアイコンが作成されます。

 次回以降は,ターミナルコマンドアイコンをダブルクリックするだけで増分バックアップを実行させることができます。

 バックアップ実行中に“Permission denied”というメッセージが出る場合,バックアップ先ボリュームに対する書き込みが禁止されているか,バックアップ対象の中にアクセス権の無いファイルやフォルダが含まれている可能性があります。前者の場合,バックアップ先ボリュームへの書き込みが許可されているかを確認して下さい。後者の場合,OSの管理上ユーザへのアクセスを許可していないものが存在します。このようなファイルはたいていユーザが必要とする書類ファイルではありません。アクセス権のあるファイルだけがバックアップされるものと諦めて下さい。


使い方その2(定期的に自動実行されるようにOSへ登録する。):

 OSのスケジュール機能を利用して定期的に自動実行されるようにすることもできます。管理者ユーザがsudoコマンドで上記コマンドを実行した場合は,TimeMachineと同様に毎時刻(最初のバックアップが終了した時と同じ分の時に)自動的に実行されるようにOSに登録されます。登録を解除するにはcrontabコマンドをsudoコマンドで実行する必要があります。crontabコマンドの使い方を予め学習しておいて下さい。man crontabコマンドを実行すればcrontabコマンドの使い方が表示されます。

 sudoコマンドで実行するということは,root権限で実行されるということです。rootは全てのファイルにアクセス権がありますので完全なバックアップが可能です。しかしながら,例えばpTimeMachineファイルが悪意のあるものやバグを含むものに置き換わった場合,非常に深刻な事態に陥ることも考えられます。管理者のパスワードを入力するという行為は慎重に行って下さい。


オプション(過去のフォルダを整理させない。または整理する深さを指定する。):

 第2引数に“-l”あるいは“-n”を指定すると,過去のフォルダの整理をしないコマンドになります。“-d”を指定すると毎時間のフォルダの整理だけに止めます。“-m”を指定すると日毎のフォルダを整理して月単位にまとめるだけに止めます。


免責事項:

 本ソフトウェアの使用によりディスクやシステムなどに障害が生じたとしても,作者は一切責任を負いません。自己責任の下でご使用ください。また完全なバックアップが行われなかったことにより二次的にファイルを失ったとしても作者を恨まないで下さい。二次的ファイル喪失とは,バックアップされなかったファイルがあったとして,そのことに気付かないままオリジナルのファイルを消去してしまうことを指します。

2015/01/12 17:13 kmiya への返信

返事が遅くなりました。現況をご報告いたします。



Backup.sh

---

#!/bin/sh

today=`date -v -1d +%Y%m%d`

yesterday=`date -v -2d +%Y%m%d`

rsync --progress -av --link-dest=../$yesterday /Volumes/Files/ /Volumes/Backup/$today

---

を、LingonでLaunchdに毎日午前1時実行で登録して使っています。

現在のところ特に問題はなく、ちゃんと毎日差分バックアップが取れています。



なかなか勉強の時間がとれず、T22Tさん、Hiro.Sさん、kanekakaさんに教えていただいたことが理解できないままなのですが、動いているのでとりあえず使っている状況です。本当はいろんな状況に備えるべきなので、使えるものは使いながら勉強していきたいと思います。

教えていただきありがとうございました。

2015/01/12 22:39 kmiya への返信

現状ではファイルの「作成日」と「拡張属性」がコピーされません。


「作成日」はコピーされずに「変更日」と同じ日付になるのですが、これをコピーできるようにするのはちょっと難しくて、rsync 3 を自分でコンパイルする必要があります。まあ、「作成日」がなくなっても大きな問題にはならないでしょうから、このままでも良いかと思います。


「拡張属性」は rsync コマンドの -E オプションでコピーされるようになります。「拡張属性」には「カスタムアイコン情報」とか「ダウンロード元の URL」とかが格納されているので、ちゃんとコピーした方が良いです。

2014/08/19 01:48 kmiya への返信

これはdateコマンドで作ったシェル変数を使うのではないでしょうか? 例えば、

today=`date +%Y%m%d`

yesterday=`date -v -1d +%Y%m%d`


として、mkdir $today とすると、今日の日付(20140819)がついたフォルダ(ディレクトリ)ができますよ。


詳しくは dateコマンドのマニュアルを参照します。

2014/08/19 20:09 kmiya への返信

そうだと思います。 実際には、コマンドを記述したシェルスクリプトを実行することになると思います。 しかしながら、私自身はrsyncコマンドを使った事が無いので、実際に巧くいくかどうかは解りません(済みません)。 少し変数の値を変えるなり、試し用のフォルダを作成するなどして、作動を確かめてみるとよいのではないでしょうか?

2014/08/20 04:16 kmiya への返信

すみません、ちょっと私には解りません。 でも、rsyncのコマンドとバックアップの処理を分ける意図もわかりません。 あるいは、シェルスクリプト内で定義した変数のスコープの問題でしょうか? エラーの記述を良く読んでみるとヒントが載っているかもしれません(ここに書き込んで頂いた方が分かり易いです)。


サポートコミュニティの皆様、ご指導の程、宜しくお願い申し上げます。

2014/08/21 21:11 kmiya への返信

すみませんが1~4で何をしたのかがさっぱり分かりません。なので、一般論になりますが、bash -x foo.sh みたいな感じで -x オプションを付けてトレースしてみてはどうでしょうか?おそらく $yesterday が期待どおりに展開されてないのだと思いますが...。

このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

rsyncの差分バックアップを自動化したい、日付でフォルダを自動で作る方法を教えてください。

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。