ottijp blog

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しています.

$HOME/Library/LaunchAgents/my.mediabackup.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>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

解決策

こちら↓の方法で解決できました.

cf. launchd - How to run a LaunchAgent that runs a script which causes failures because of System Integrity Protection - Ask Different

私の場合Root accessは要らなかったで,次のような感じで対応しました.

  • シェルスクリプトをapp化
  • launchd用の定義ファイル変更
  • 作ったappのリムーバブルディスクへのアクセスを許可

シェルスクリプトをapp化

まず,バックアップ用シェルスクリプトを呼び出すappファイルを作ります. これはシステム設定のプライバシ(FDA:Full Disk Access もしくは Files and Folders)で, このバックアップ処理のみに権限を与えるためです.

スクリプトエディタで次のようなスクリプトを書き, appとして保存します.

$HOME/bin.local/media-backup.app
on run
	do shell script "/bin/bash /Users/USERNAME/bin.local/media-backup"
end run

launchd用の定義ファイル変更

launchdのバックアップサービスを,このappを呼び出すように変更しました.

$HOME/Library/LaunchAgents/my.mediabackup.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>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

media backup fda

これにより,プライバシ設定にこのappが追加され,バックアップが正常にできるようになりました.

media backup fda2

ちなみに,FDA(Full Disk Access)の方は設定が追加されませんでした. 私の場合はこれで大丈夫でしたが,バックアップ処理の内容によってはFDAのアクセス許可が必要な場合もあるかもしれません.

うまくいかなかった方法

ググッて見つかった解決法に,FDAにbash,rsyncなどを手動登録する方法があって,一応試してみたのですがうまく動きませんでした. 広範囲に権限を付与しなくてよくなるので,今回のようにapp化してやるほうがセキュリティ上も良さそうです.

refs


ottijp
都内でアプリケーションエンジニアをしています
© 2024, ottijp