猫の手なら貸せる

いろいろ共有できたらいいなとおもってます

launchd呼び出しのrsyncを成功させる

Googleの検索でエラーコードを調べてる人が多かったので記事を分離しました。
元記事は以下になります。rsyncとlaunchd(Mac推奨のcronの後続)を用いて、定期的にバックアップ取ろうとしていました。
nkhnd.hatenablog.jp

環境

転送元:MacbookAir (2019 Retina) Mojave
転送先:RaspberryPi (Sambaによる共有)

権限があるディレクトリにも関わらずOperation not permitted

事象

このエラーはユーザーのLibraryディレクトリなどを、launchdでrsync同期を行おうとした際に発生しました。
以下はMacバイスのバックアップをリモートディレクトリにrsyncしようとした際に発生した例です。

2019/12/18 06:48:02 [29222] rsync: opendir "/Users/nkmm/Library/Application Support/MobileSync/Backup/." failed: Operation not permitted (1)
rsync: opendir "/Users/nkmm/Library/Application Support/MobileSync/Backup/." failed: Operation not permitted (1)
2019/12/18 06:48:02 [29222] IO error encountered -- skipping file deletion
IO error encountered -- skipping file deletion
2019/12/18 06:48:02 [29222] .d..tp...... ./
2019/12/18 06:48:02 [29222] rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1209) [sender=3.1.3]
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1209) [sender=3.1.3]

ファイル権限自体はきちんとユーザーが所持しています。

MobileSync $ ll
total 8
drwxr-xr-x   4 nkhnd  staff   128 12 18 07:09 .
drwx------+ 32 nkhnd  staff  1024 12 16 21:18 ..
drwxr-xr-x   4 nkhnd  staff   128 12 18 06:45 Backup  #←きちんとrsyncを行うユーザーが所持
MobileSync $ cd Backup && ll
NekoBook:Backup nkmm$ ll
total 0
drwxr-xr-x    4 nkhnd  staff   128 12 18 06:45 .
drwxr-xr-x    4 nkhnd  staff   128 12 18 07:09 ..
drwxr-xr-x  262 nkhnd  staff  8384 12 17 06:35 (Apple DeviceのIDをもつディレクトリ)
drwxr-xr-x  262 nkhnd  staff  8384 12 17 06:38 (Apple DeviceのIDをもつディレクトリ)

また、「システム詳細設定」「セキュリティとプライバシー」におけるターミナルの「フルディスクアクセス」は許可しています。

f:id:nkhnd:20191218071304p:plain

発生理由と対処法

(追記) 良さも悪さもできるbashにフルディスクアクセスを許可するのは、セキュリティ的にだいぶ怪しいため非推奨です。
通常アクセスに制限がかけられている~/Library以下などは、直接アクセスせず、アクセスしたい場所を安全なディレクトリへシンボリックリンクすることをお勧めします。私もこの方法に移行しました。
例えばiOSバイスiTunesバックアップが作成される~/Library/Application Support/MobileSync/Backup/を新たに作成した~/backフォルダに自動的に転送するには、次の方法でシンボリックリンクを作成します。

mv ~/Library/Application\ Support/MobileSync/Backup/* ~/back/ #データを退避
rmdir ~/Library/Application\ Support/MobileSync/Backup/ #元ディレクトリは削除
ln -s ~/back ~/Library/Application\ Support/MobileSync/Backup
 #backディレクトリへのシンボリックリンクをMobileSync内でBackupという名前で作成

こうしてやると、フルディスクアクセスを使わず、launchdがディレクトリにアクセスできるようになります。


以下過去の文章。(非推奨)

ディレクトリでは正常にrsyncできることから、MacOSの問題であると切り分けた所、ターミナルではなく、launchdで動作させるプログラム本体を追加するという解決策が提示されました。
mac-ra.com
しかし、rsyncにフルディスクアクセスを許可しても反応しないため、さらに調べた所、bashにフルディスクアクセスを許可し、bashからrsyncを起動すれば正常にアクセスできました。
eclecticlight.co
フルディスクアクセスにbashを設定します。
f:id:nkhnd:20191218074903p:plain plistではrsyncbash越しに起動するように設定します。

<?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>devicessync</string>
 <key>ProgramArguments</key>
 <array>
  <string>/bin/bash</string>
  <string>/Users/nkhnd/rsync.sh</string>
  <string>/Users/nkhnd/Library/Application Support/MobileSync/Backup/</string>
  <string>pi@raspberrypi.local:/mnt/Backup/</string>
  <string>/Users/nkhnd/backup.log</string>
 </array>
 <key>StartCalendarInterval</key>
 <dict>
  <key>Hour</key>
   <integer>7</integer>
  <key>Minute</key>
   <integer>45</integer>
 </dict>
 <key>StandardOutPath</key>
...(省略)...

動作確認を行います。

2019/12/18 07:45:00 Start rsync /Users/nkhnd/Library/Application Support/MobileSync/Backup/ => pi@raspberrypi.local:/mnt/Backup/
2019/12/18 07:45:00 [29398] building file list
2019/12/18 07:45:01 [29398] .d...p...... ./
...(省略)...

無事動作しました。

iconvを指定済みにも関わらずrsync --deleteが更新のないファイルを削除

事象

iconvで文字コードの変換規則を設定しているにも関わらずSambaでマウントしているディレクトリ宛rsync --deleteを行うと、2回目の同期にかかわらず更新のないファイルを削除してしまうことがあります。

以下は実行コマンドの例です。Sambaによって/Volumes/Storageをマウントしています。

$ rsync -auz --delete --iconv=UTF-8-MAC,UTF-8 --exclude '.*' --log-file=test.log /Users/nkhnd/dir /Volumes/Storage/back/

発生理由と対処法

Sambaでマウントしているディレクトリに対しては--iconvが機能しないようです。
Sambaを利用せず、SSH接続を前提にしたパスを指定することで解決します。

rsync -auz --delete --iconv=UTF-8-MAC,UTF-8 --exclude '.*' --log-file=test.log /Users/nkmm/dir nas@raspberrypi.local:/mnt/Storage/back/ 

調査はしていませんが、Sambaでマウントしたディレクトリでは文字コードの変換は不要なのかもしれません。(Sambaによってマウントディレクトリの文字コードが自動的に変換される?)

launchdでrsyncがiconvオプションを認知しない

事象

launchdでシェル内のrsyncを呼びだす場合、及びlaunchdで直接rsyncを実行する際、--iconvオプションが指定できないことがあります。
homebrew等でlibiconvはインストール済みで、記法に間違いはありません。

rsync: --iconv=UTF-8-MAC,UTF-8: unknown option
rsync error: syntax or usage error (code 1) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/rsync/rsync-52.200.1/rsync/main.c(1337) [client=2.6.9]

発生理由と対処法

launchd実行時のシェルでは/usr/local/binにパスが通っていません。
以下は手動・及びlaunchdにenvコマンドを実行させた結果です。

$ cat launchdEnv.log #launchdのenv出力内容
---------- env ----------
...(省略)...
PATH=/usr/bin:/bin:/usr/sbin:/sbin
...(省略)...
$ env #ターミナル上でenvを入力した際の内容
...(省略)...
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
...(省略)...

また、whichコマンドでターミナル上で実行できるrsyncのパスを調べてみます。

$ which -a rsync
/usr/local/bin/rsync
/usr/bin/rsync

どうやらrsyncは二種類(homebrewでインストールしたもの、Mac標準でインストールされているもの)あるようです。
launchdでは/usr/local/binにパスは通っていないので、plistではフルパス(/usr/local/bin/rsync)で実行する必要があります。
launchdで呼び出すシェルスクリプトについての記述もrsyncではなく/usr/local/bin/rsyncと記述しましょう。


現在はセキュリティ面を考慮し、SambaではなくSFTPを利用しています。マウントも(やや難がありましたが)OSXFuseとSSHFSを利用することで実現しました。正常に稼働中です。

Sambaではパスワード認証しかできず、同じセグメント内でしか通信できませんが、SFTPであれば公開鍵認証が利用でき、またSSHと同じ要領でサーバーを外部ネットワークに公開した際にも利用することが可能です。
というのも、なんと格安SIMであるイオンモバイルのデータ2プランのSIMカードグローバルIPの割り当てであるため、家に強固な固定回線がなくても、Docomo(またはSIMロック解除済みの)モバイルルーターがあれば、サーバーを外部に公開することができます。

一時期は外部からファイル管理が行えるようにと考えていましたが、セキュリティ知識不足及びRaspberryPi自体の信頼性に疑問を感じ始めているため、再考中です。