来る研究活動に備えて、先生方が口を酸っぱくしてい言っていた「バックアップは最低3箇所に」を実現すべく、Macのlaunchdを使って自動で3つのクラウドストレージに30分おきにバックアップを取るスクリプトと設定を作りました。
クラウドの準備
まずは、バックアップ先となるクラウドストレーじを準備します。必要となるのは、ローカルに同期用のディレクトリが作成されるクラウドストレージサービス。そこで、今回は
- Dropbox
- Google Drive
- iCloud Drive
を使用しました。それぞれサインインして必要であればアプリをインストールして起動し、ローカルに同期ディレクトリがある状態にします。
ローカルでの準備
今回は、「作業中の大事なファイル」で「30分おきにバックアップを取る」ということで、ホームディレクトリ以下にWorkspaceというディレクトリを作り、そこにあるファイルのみをバックアップ対象としています。

これでディレクトリ構成は完成しました。
同期スクリプトの準備
次に、同期用のスクリプトを作成します。同期対象となるディレクトリを同期先のディレクトリに全く同じ状態で同期するために、rsyncコマンドを使用し、オプションに--deleteを用います。
rsync -a --delete --exclude=".DS_Store" $HOME/Workspace/ $HOME/Dropbox/Workspace
これを3箇所に対して行うので
syncwork.sh
#!/usr/bin/env bash set -eu if [ -d "$HOME/Workspace" ]; then : else echo "error. there is no Workspace." 1>&2 exit 1 fi rsync -a --delete --exclude=".DS_Store" $HOME/Workspace/ $HOME/Dropbox/Workspace rsync -a --delete --exclude=".DS_Store" $HOME/Workspace/ $HOME/GoogleDrive/Workspace rsync -a --delete --exclude=".DS_Store" $HOME/Workspace/ HOME/Library/Mobile\ Documents/com~apple~CloudDocs/Workspace exit 0
これに、echoなどでlog用の出力などを適当に加えれば良いはずです。
launchdへ登録
あたりを参考にさせてもらいました。
launchdにスクリプトを自動で実行してもらうには
1. plistの作成
2. launchctlの実行
を行う必要があります。今回、plistは次のように作りました。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>syncwork</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/USER/Library/LaunchAgents/synwork.sh</string>
</array>
<key>StartInterval</key>
<integer>1800</integer>
<key>StandardOutPath</key>
<string>/Users/USER/PATHTO/synwork.log</string>
<key>StandardErrorPath</key>
<string>/Users/USER/PATHTO/synworkerr.log</string>
</dict>
</plist>plistの記述には変数は使えなので、USERとPATHTOは適当に書き換えます。あとは、launchdに登録するために、これを~/Library/LaunchAgents/syncwork.plistに保存し、ターミナルで
launchctl load ~/Library/LaunchAgents/syncwork.plist
を実行します。
launchctl list | grep syncwork
を実行して名前があれば成功してるはずです。テストのために、最初はStartIntervalの下の1800をもっと短いスパンにするといいかもしれません。