launchdでリムーバブルディスクへのrsyncバックアップがエラーになった場合の解決法
普段,データ用のバックアップをlaunchd + rsyncで行っているのですが, このところうまく動いていないことがわかり,それがMojaveから導入されたプライバシ機能の強化によるものだとわかりました.
cf. macOS 10.14 Mojaveでは新しいプライバシー保護機能のため、ホームディレクトリ以下でもターミナルからアクセスするさいには「フルディスクアクセス」設定が必要に。 | AAPL Ch.
バックアップできていないのはまずいので,回避方法を調べ対応しました.
環境
- macOS: 10.15.3 (Catalina)
- launchd: 7.0.0
- rsync: 3.1.3
旧構成
launchdで /bin/bash を起動し,バックアップ用のシェルスクリプトを呼んでいました. シェルスクリプト内でrsyncしています.
<?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>my.mediabackup</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/USERNAME/bin.local/media-backup</string>
</array>
<key>StartInterval</key>
<integer>86400</integer>
</dict>
</plist>
ターミナル上で直接 $HOME/bin.local/media-backup を呼び出した場合は問題なくバックアップできるのですが,
launchdによる自動起動時や,launchctl start my.mediabackup
などとして実行した時に,
バックアップ処理の中のfindで次のようなエラーが出ていました.
find: /Volumes/MEDIA_BACKUP/: Operation not permitted
ログはStandardOutPath
, StandardErrorPath
を設定して確認しました.
cf. launchd, launchctlについて(導入編) · GitHub
解決策
こちら↓の方法で解決できました.
私の場合Root accessは要らなかったで,次のような感じで対応しました.
- シェルスクリプトをapp化
- launchd用の定義ファイル変更
- 作ったappのリムーバブルディスクへのアクセスを許可
シェルスクリプトをapp化
まず,バックアップ用シェルスクリプトを呼び出すappファイルを作ります. これはシステム設定のプライバシ(FDA:Full Disk Access もしくは Files and Folders)で, このバックアップ処理のみに権限を与えるためです.
スクリプトエディタで次のようなスクリプトを書き, appとして保存します.
on run
do shell script "/bin/bash /Users/USERNAME/bin.local/media-backup"
end run
launchd用の定義ファイル変更
launchdのバックアップサービスを,このappを呼び出すように変更しました.
<?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>my.mediabackup</string>
<key>ProgramArguments</key>
<array>
- <string>/bin/bash</string>
- <string>/Users/USERNAME/bin.local/media-backup</string>
+ <string>/usr/bin/open</string>
+ <string>/Users/USERNAME/bin.local/media-backup.app</string>
</array>
<key>StartInterval</key>
<integer>86400</integer>
</dict>
</plist>
これをlaunchdに登録し直します.
$ cd $HOME/Library/LaunchAgents
$ launchctl unload my.mediabackup.plist
$ launchctl load my.mediabackup.plist
バックアップappのリムーバブルディスクへのアクセスを許可
これでlaunchdによるバックアップタスク実行時にダイアログがでるので,許可します.
$ launchctl start my.mediabackup
これにより,プライバシ設定にこのappが追加され,バックアップが正常にできるようになりました.
ちなみに,FDA(Full Disk Access)の方は設定が追加されませんでした. 私の場合はこれで大丈夫でしたが,バックアップ処理の内容によってはFDAのアクセス許可が必要な場合もあるかもしれません.
うまくいかなかった方法
ググッて見つかった解決法に,FDAにbash,rsyncなどを手動登録する方法があって,一応試してみたのですがうまく動きませんでした. 広範囲に権限を付与しなくてよくなるので,今回のようにapp化してやるほうがセキュリティ上も良さそうです.