僕はiTunesのメディアファイルを始め、動画、画像ファイルを全て外付けのHDDに保存して管理している。
昔はNASだったんだけど、引っ越してから無線の速度が遅くなったので単純な外付けHDDに回帰した。
で、それはいいんだけど、最近ファイルが壊れていたりすることに気付いた。
古いHDDのせいだろうか。
幸か不幸か、大して重要じゃないファイルなのでよかったが、流石にこの大容量の資産にバックアップがないこの状況が少し怖くなってきた。
今までもたまに気が向いたときに別の外付けHDDにバックアップを取ったりしていたが、気が向いた時だけじゃ心もとなさ過ぎる。
バックアップを毎晩、自動実行しようと思うに至った。
で、Windowsのようにrobocopyコマンドを使おうとしたけど、当然Macにはrobocopyなんてコマンドは無い。
その上、定期実行しようにもWindowsで言うタスクスケジューラが無い。Windows脳 の僕はこれで少しパニックになった。
そんな色んな障害を乗り越えた(乗り超えるほど大きい壁じゃない)作業メモを残そうかなと思う。
なお、前提として僕はシェルスクリプトなんて書いたこともない素人 である。
「cron?良くワカンネ 」というレベルである。
実際、良くわからなくて今回使わなかった。今度また挑戦する。
1. バックアップを行うコマンド(シェルスクリプト)を書く
最悪手動でも、バックアップを1クリックで行えるコマンドファイルを作成できれば、
Macでバッチファイル的なものを作成する
のようにして1クリックバックアップシステムが作れるはず。
まずはバックアップを行えるようなコマンドを探した。
2秒で見つかった。
rsync
差分更新まで行ってくれるイカした奴。
僕の望む同期の形を考え、以下のようなオプションを設定した。
rsync - atuv -- delete コピー元 コピー先
-a…元の権限を保持する
-t…元のタイムスタンプを保持する
-u…追加、更新されたファイルだけをコピーする
-v…処理中の経過ファイルを表示する(後述のログ出力のため)
–delete…コピー元にないファイルがコピー先にあった場合、削除する
要するに、バックアップ元と寸分たがわぬ構成をコピーする、という趣旨だ。
それで、最初は単純に以下のような1行コマンドで済ませていた。
rsync - atuv -- delete "/Volumes/From_HDD/" "/Volumes/To_HDD/"
だけど、あんまり好きじゃない点が一つあった。
Macで外付けHDDに接続した場合、”.”から始まる不可視ファイルが作成されるが、これらまでバックアップ先にコピーされてしまう。
なので、バックアップ元の外付けHDD内の通常フォルダのみに対してrsyncを行うようなコマンドに修正した。
ついでにrsyncの出力をログとしてファイルに残すようにした。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash
fromHDD="/Volumes/バックアップ元HDD名/"
backupHDD="/Volumes/バックアップ先HDD名/"
logFile="/ログ出力先ディレクトリ/SyncLog"`date +%Y%m%d`".log"
if [ ! -e $fromHDD]; then
echo "No FromHDD $FromHDD" >> $logFile
echo "HDD Sync Error" | mail -s "HDD Sync Error" Address@gmail.com
return
fi
if [ ! -e $backupHDD]; then
echo "No backupHDD $backupHDD" >> $logFile
echo "HDD Sync Error" | mail -s "HDD Sync Error" Address@gmail.com
return
fi
for folder in `ls -F $fromHDD | grep /`
do
fromdir=$fromHDD$folder
backupdir=$backupHDD$folder
rsync -atuv --delete $fromdir $backupdir >> $logFile
done
echo "HDD Sync is Completed" | mail -s "HDD Sync Completed" Address@gmail.com
これでバックアップ元HDD直下のフォルダについて、全てバックアップ先にコピーされる。
ただ、上記スクリプトの欠点は、バックアップ元HDD直下にスペースを含むフォルダが有る場合、上手く動作しないことだ。
つまり、”test folder”というフォルダがあると、”test”と”folder”という2フォルダと認識されてしまう。
工夫すればどうにでもなると思うけど、スクリプトをシンプルにしたかったのでこのままにしておいた。
工夫する知識も気力も無いです。
2. シェルスクリプトを定期実行する
さて、スクリプトはできたが、定期実行はできるのか。
ちゃんとやるならcronやlaunchで設定するのが良いらしい。
でも、よくわからないので、原始的な方法を採った。
Macの標準カレンダー(旧iCal)とAutomatorを用いる方法だ。
MacのAutomatorで新規作成を行う。
書類の種類は「カレンダーアラーム」にする。(アプリケーションでも良い。その場合は後述の設定が必要)
アクションで、「ユーティリティ」→「シェルスクリプトを実行」を選択する。
上記のスクリプトを記述し、保存する。
以上により、Macの標準カレンダーにイベントが登録される。
時刻や繰り返しの設定を適宜変更すれば、定期タスクの設定が簡単に可能だ。
ちなみに、「カレンダーアラーム」でなく、「アプリケーション」を作成した場合、appファイルが作成される。
このappファイルを開くと、シェルスクリプトが実行されるので、後はこのappを定期的に実行するように、手動で標準カレンダーに登録すれば良い。
カレンダーで普通にイベントを追加し、
「通知」→「カスタム」を選択する。
初期状態では通知が「メッセージ」となっていると思うので、ここを「ファイルを開く」にする。
ファイルの種類がカレンダーになっているので、ここで「その他」を選択し、先程のappファイルを選択する。
ちなみに、GoogleカレンダーやiCloudのカレンダー等、クラウド上のカレンダーではこの通知の設定が保存されなかった。
未検証だが、クラウド上と動機する過程で「ファイルを開く」通知が消えてしまうのだろう。
ローカルのMac上のイベントとして設定したほうが確実だ。
後は時刻や繰り返しを設定することで、定期的にスクリプトが実行できる環境が完成する。
基本的に「カレンダーアラーム」で設定したほうが簡単だと思う。
ちなみに「カレンダーアラーム」で作成した場合、そのappファイルは以下の場所に保存されている。
/Users/UserName/Library/Workflows/Applications/Calendar
appファイルを常に手元においておきたい場合は「アプリケーション」で作成するのもありだと思う。
・参考にしたページ
rsync – 高速なファイル同期(バックアップ) – Linuxコマンド
iCalで指定時刻にアプリを呼び出す
【Linux】bashで指定したディレクトリ内のファイルを取得する
lsでディレクトリのみ,ファイルのみ,表示する
追記(2015/05/30)
定期実行でカレンダーを使うのは負けた気がしてきたので結局launchdを使うことにしました。
MacでScriptを定期実行する方法