mac ファイル転送サーバーの4つの経路と、標準で足りる範囲
Macからサーバーへファイルを送る作業は、片付いているように見えて、条件が変わった途端に崩れる。ファイルが大きくなる、回線が途中で切れる、ファイル名に日本語が入る。そのどれかが起きた瞬間に、何年も使ってきたFinderの操作が途中でエラーを返し、転送したフォルダに .DS_Store が散らばり、解説記事から写したコマンドが「そんなオプションは知らない」と言って止まる。mac ファイル転送サーバーの話でつまずくのは、たいていこの3つの場面だ。
原因ははっきりしている。macOSに入っている転送の道具は少し特殊な組み合わせで、世の中の解説の多くはLinux向けに書かれている。手元のMacに実際に何が入っているのかと、4つある経路のどれがその仕事に合うのかを押さえれば、当て推量はほとんど消える。
標準で入っているものと、入っていないもの
いまのMacには、サーバーとのやり取りに必要なものはすでに入っている。よくある用途なら、追加で入れるものはない。
OpenSSHが同梱されており、ssh、scp、sftp が使える。ここで押さえておきたいのは scp の中身が変わったことだ。2022年4月に公開されたOpenSSH 9.0以降、scp は独自の古いプロトコルを使わなくなった。
This release switches scp(1) from using the legacy scp/rcp protocol to using the SFTP protocol by default. 出典: openssh.com
つまり scp と sftp は、いまや下で同じことをしている。リモートのパスに含まれる記号を二重にクォートしろ、という古い注意書きは以前ほど当てはまらなくなった。逆に、古い組み込み機器のように昔のプロトコルしか話せない相手に対しては、-O を付けて旧方式に戻す必要が出ることがある。
curl も入っていて、HTTP、HTTPS、FTP、FTPS、SFTPを話す。nc、smbutil、mount_smbfs も揃っている。一方で入っていないのが素の ftp コマンドだ。Appleは ftp と telnet のクライアントをmacOS High Sierraで取り除いた。FTPが必要な相手には、curl かFinderか、別のクライアントを使うことになる。
rsync も入っている。驚くのはここからだ。
同梱のrsyncは、解説記事に出てくるrsyncではない
macOSは長いあいだrsync 2.6.9を同梱してきた。ライセンスの都合で2006年のビルドのまま据え置かれていたものだ。macOS 15でこれがopenrsyncという別実装に入れ替わった。名乗りは旧版との互換で、いまのシステムで rsync --version を叩くと、プロトコルは29、そして rsync version 2.6.9 compatible と表示される。
互換は同一ではない。ほとんどの解説記事に登場するオプションのいくつかが、実装されていない。
| オプション | 役割 | macOSのopenrsync |
|---|---|---|
| --iconv | ホスト間でファイル名の文字コードを変換 | 使えない |
| -X (--xattrs) | 拡張属性を複製 | 使えない。--extended-attributes はある |
| -A (--acls) | アクセス制御リストを複製 | 使えない |
| --partial | 途中まで送ったファイルを残す | 使える |
| --exclude | 該当するパスを除外 | 使える |
| -z (--compress) | 転送中に圧縮 | 使える |
実害が出るのは --iconv の欠落だ。macOSはファイル名のUnicodeを分解した形で保存し、Linuxのサーバーはほぼ例外なく合成した形で保存する。濁点や半濁点を含む日本語のフォルダ名は、サーバー側で見た目は正しく届くのに、文字列としては別物として比較される。その結果、次に同期したときに同じ名前のディレクトリがもう1つ増える。GNU版のrsyncは --iconv=UTF-8-MAC,UTF-8 でこれを解決する。同梱のopenrsyncにその機能はなく、unrecognized option と返してくる。
日本語のファイル名を含むツリーを扱うなら、パッケージ管理からGNU版のrsyncを入れて、パスの rsync に任せず明示的に呼ぶ。ASCIIだけで完結する相手なら同梱のもので足り、依存が1つ減る。
macOS特有の癖もあと2つある。--exclude='.DS_Store' を最初から付けて、Finderの管理用ファイルがサーバーに溜まらないようにすること。そして、Apple以外のファイルシステムへ複製すると、リソースフォークを抱えた ._名前 という相棒のファイルが残ることがある。tar を使うときは実行前に COPYFILE_DISABLE=1 を指定すると抑えられる。
Finderで足りる範囲と、足りなくなる場所
画面から扱う側はFinderが引き受ける。移動メニューの「サーバへ接続」、ショートカットならCommand+Kだ。smb://、afp://、nfs://、ftp://、WebDAVの http(s):// を話す。Mac同士やサーバーとの共有は、OS X Mavericks以降SMBが既定になっており、AFPはすでに過去の方式という位置づけにある。
共有ドライブにたまに触れるだけなら、これが正解で、これ以上考える必要はない。転送が日常になると、限界が3つ出てくる。
1つ目は、FinderがFTPを読み取り専用でマウントすること。閲覧と取得はできるが、この経路でのアップロードはできない。2つ目は、大きなファイルの複製が途中で切れたとき、多くの場合は再開ではなく最初からやり直しになること。3つ目は、マウントしたネットワークボリュームがローカルのディスクと同じように扱われることだ。Spotlightの索引付け、サムネイルの生成、フォルダ容量の計算が回線越しに走り、マウント全体が使い物にならなく感じられることがある。
そして、Finderには前回の記憶がない。接続のたびに空のダイアログとパスの入力が待っている。週に1回なら気にならず、1時間に1回なら耐えがたい。
4つの経路の使い分け
| 経路 | 向いている用途 | 再開 | 権限の保持 | スクリプト化 |
|---|---|---|---|---|
| AirDrop | 近くのApple製品へ1つ渡す | 不可 | されない | 不可 |
| Finderのサーバへ接続 | 共有をたまに見る | 不可 | 一部 | 不可 |
| scp | 1つのファイルや小さなフォルダを1回 | 不可 | -p で可 | 可 |
| sftp | リモートのツリーを対話的に探る | reget で可 | 一部 | やりにくい |
| SSH越しのrsync | 変化するツリーを繰り返し送る | --partial で可 | -a で可 | 可 |
| SFTPのマウント | リモートのファイルを手元のアプリで編集 | 該当なし | 実装次第 | 一部 |
分かれ目は繰り返すかどうかにある。1回きりの転送は scp の仕事で、それ以上考えるのは時間の無駄だ。毎日走る転送はrsyncの仕事になる。変わっていないファイルを飛ばせるのはrsyncだけで、その差はツリーが大きくなるほど開く。
リモートのファイルシステムを手元にマウントする方式は、別の分類に置いたほうがよい。macOSではmacFUSEとsshfsの組み合わせか、Mountain DuckやForkLiftのような製品が必要になる。リモートのファイルを数個だけ手元のエディタで直す用途には非常に向く。逆に、多数のファイルを高速に読む処理には向かない。1回の読み込みごとに往復が発生するためだ。
繰り返す側を安くする
日々の転送で重いのは、転送そのものではない。その周りで打っている文字のほうだ。
~/.ssh/config に1つ書いておくと、長い接続文字列が単語1つになる。
Host web
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
これで ssh web も rsync -av ./dist/ web:/var/www/site/ も通る。SSHの既定のポートは22番なので、変更しているサーバーだけ Port を足せばよい。末尾の3行は認証済みの接続を10分間使い回す指定で、続けてコマンドを打つときに毎回の認証を省ける。
事故を防ぐ習慣も3つある。まず -n を付けて実行し、何が動くのかだけを一覧させること。次に、送り元のパスの末尾のスラッシュは「そのディレクトリの中身」を意味し、付けないと「そのディレクトリごと」を意味すると理解しておくこと。サーバー上に site/site/ ができる事故は、ほぼこれが原因になる。そして大きなものには --partial --progress を付けること。回線が切れても最初からにならない。
届いたかどうかの確認は、ファイルサイズを信じずにハッシュを比べる。両端で shasum -a 256 ファイル名 を実行すれば決着がつく。rsync自身の -c でも内容の照合はできるが、全部を2度読むので時間はかかる。
着いたあとの権限と時刻で、もう一度つまずく
転送が完走したことと、転送がうまくいったことは別だ。きれいに終わったあとで最も多い失敗は、向こう側の権限にある。原因はrsyncの -a の中身にある。
-a は束ねた指定で、再帰に加えてシンボリックリンク、パーミッション、更新日時、グループと所有者の保持を含む。ところが所有者を保持するには受け側でroot権限が要るため、一般ユーザーで送るとその部分だけが静かに落ち、ファイルは接続に使ったアカウントの持ち物として届く。ウェブサーバーなら、サービス用のアカウントが読めない中身が並び、配信は成功したように見えるのに403が返る、という形で表面化する。
対処は2つある。1つは --chmod=D755,F644 のように転送時のモードを明示して、送り元のローカルの権限が外に漏れないようにすること。送り元の機械が何であっても結果が一定になる。もう1つは、いったん待避用のディレクトリに送り、サーバー側の処理で正しい所有者に付け替えながら本番の場所へ移すこと。接続アカウントにその権限があるかで選べるものが変わるが、どちらかを意識して選ぶほうが、ブラウザ越しに不具合として気づくよりずっと安い。
更新日時にも一言いる。-t が無いとrsyncは日時で変化を判定できず、毎回中身を比べにいく。rsyncを使う意味そのものが消えるので、オプションを1つずつ組み立てるより -a を使うほうが安全だ。
窓の数という、見えにくい費用
Macで配信や納品の作業をするとき、実際に開いている窓を数えてみるとよい。ファイルを探して並べるためのFinderが1つ。転送を実行し、向こう側の結果を確かめるターミナルが1つ。そして多くの場合、rsyncのオプションの書き方を尋ねるためのAIがもう1つ。3つ目は、いまどのディレクトリが選ばれているのかも、相手のサーバーがどうなっているのかも知らない。
3つの窓はそれぞれ別の「現在地」を持っていて、それを手作業で突き合わせている時間が、実は一番の費用になっている。これはファイル転送への不満としては表に出てこない。普通の仕事に見えるからだ。それでも、繰り返しの中でもっとも大きな1項目であることは変わらない。
表示中のフォルダをシェルがそのまま引き継ぐ道具なら、この費用の半分が消える。同じ作業ディレクトリをAIも読んでいるなら、残りの大半も消える。質問が抽象的な一般論ではなく、画面に出ているファイルについての問いになるからだ。つまり判断の軸は転送プロトコルの数ではなく、フォルダとターミナルとAIが同じ窓にあるかどうかに移る。
何ができるのかはできることにまとまっている。長い転送を仕掛けたまま席を離れ、途中経過を手元で確かめる話はiPhone・iPadから続きをにある。他のファイル管理アプリと条件を並べたいときは他のファイル管理との比較を、日本語以外の環境で使う可能性があるなら対応言語を先に見ておくとよい。費用の目安は料金に、細かい判断はよくある質問にまとめてある。
最初に変えるとよいのは道具ではなく設定だ。いちばんよく使うサーバーについて ~/.ssh/config を1つ書き、接続の使い回しを有効にする。そして日々の複製を scp から rsync -av --partial --progress に替える。10分ほどで終わり、打ち直しも、最初からのやり直しも、宛先の取り違えもほとんど消える。それでも残る手間がフォルダとシェルとAIの行き来だったときに、初めて道具を替える話になる。
よくある質問
macOSに入っているrsyncは、Linuxのものと同じですか?
同じではありません。macOS 15以降はopenrsyncという別実装で、rsync 2.6.9互換と名乗ります。-a、--partial、--exclude、--delete などよく使う指定は動きます。一方で --iconv、-X、-A は実装されていないため、GNU版を前提に書かれたスクリプトはオプション不明のエラーで止まることがあります。
日本語のファイル名を転送すると、サーバー側で同じ名前が2つできるのはなぜですか?
macOSはファイル名のUnicodeを分解した形で保存し、多くのLinuxサーバーは合成した形で保存するためです。見た目は同じでも、バイト列としては別物になります。GNU版のrsyncなら --iconv=UTF-8-MAC,UTF-8 で吸収できますが、同梱のopenrsyncはこの指定に対応していないため、GNU版を別に入れるのが現実的な対処になります。
scpはもう使わないほうがよいですか?
いまも同梱されていて、通信も暗号化されています。OpenSSH 9.0以降は下でSFTPを使う作りに変わり、クォートまわりの問題は減りました。古い機器で旧方式しか話せない相手には -O を付けます。ただし2回以上送る相手なら、変わっていないファイルを飛ばせるrsyncのほうが結果的に速く、事故も少なくなります。
FinderからFTPサーバーにアップロードできますか?
できません。FinderはFTPを読み取り専用でマウントするため、閲覧と取得までです。macOSはコマンドの ftp もHigh Sierraで取り除いています。FTPでのアップロードが必要なら curl -T を使うか、CyberduckやFileZillaのようなクライアントを用意します。相手が対応しているなら、SSH越しのSFTPに寄せるほうが安全です。