2026 リモート Mac rsync `--link-dest` / `--copy-dest` 増分スナップショット:ディスク・走査・inode と原子切替
リモート Mac へ iOS/macOS 成果物を毎回フルコピーすると SSD と inode を急速に消費します。同一 APFS ボリューム上で rsync --link-dest を使えば未変更ブロックをハードリンク共有でき、--copy-dest でリンク不可の例外を補えます。原子リリース、SHA256 ゲート、files-from とマニフェストをこの順で繋ぐのが現場向きです。
目次(TOC)
1. 三つの痛み:フルコピー、途中公開の窓、inode と走査の壁
ディスクと時間:ツリー丸ごと複製はリンクと xattr まで含めて遅く、派生データと帯域を奪います。
途中公開の窓:本番ツリーへ直書きすると中断時に新旧混在が残ります。ステージングで閉じ、検証後にシンボリックを一度だけ更新します(原子リリース)。
inode と走査:ハードリンクはブロックは共有してもディレクトリ項は増えます。巨大ツリーは先に --files-from で列挙面を絞ります。
- 複製倍率:三世代フルで論理サイズが約三倍に見えます。link-dest は未変更を同一データへ束ねます。
- ロールバック根拠:直前成功版が無いと link-dest が成立しません。N-1 は必ず残します。
- 並行競合:同一プレフィックスへの同時 rsync は半端な木を晒します。ジョブ ID でサブディレクトリを分けます。
2. 意思決定表:link-dest、copy-dest、 tarball、ハードリンク無しの rsync
増分リンクと tarball / フル rsync の棲み分け用メモです。
| 観点 | `--link-dest` 増分 | `--copy-dest` 補助 | 階層 tarball | ハードリンク無し staging rsync |
|---|---|---|---|---|
| ディスク占有 | 未変更ブロック共有、倍率≈1+Δ | 一部ファイルはフルコピー | 単一ファイル転送、走査は低め | 世代ごとにフル複製 |
| 同一FS要件 | 強い依存 | 依存は弱い | ボリューム跨ぎ可 | ボリューム跨ぎ可 |
| 走査コスト | パス集合に比例 | 同上 | 低い | 高い |
| 原子切替との相性 | ステージングと相性が良い | 相性が良い | 展開ウィンドウが必要 | 相性が良い |
3. How-to:ディレクトリ設計、基準版の選び方、七つの手順
レイアウト例:/srv/releases/build-…/ を不変ディレクトリとして積み、/srv/releases/current をシンボリックにします。PREV はゲート済み直前版の絶対パスを CI が注入し、人手で current を触りません。
# PREV=/srv/releases/build-20260506-183000
# NEXT=/srv/releases/build-20260507-091500
rsync -a --delete --link-dest="$PREV" \
${LOCAL_BUILD}/ "ci@${REMOTE_MAC}:$NEXT/"
- PREV 健全性:manifest 欠落時は盲信せずフルシードから再構築します。
- NEXT 準備:空ディレクトリを作り、所有者とモードを PREV に揃えます。
- files-from:巨大ツリーは manifest で対象を確定してから link-dest を重ねます。
- SSH 生存:
ServerAliveInterval等で長距離切断を減らします。 - SHA256 ゲート:
shasum -a 256と manifest 一致を必須にします(整合性稿)。 - current 切替:成功後のみ
ln -sfn "$NEXT" /srv/releases/currentです。 - 保持と掃除:N 世代ルールに合わせ、削除前に PREV 参照中ジョブが無いか確認します。
# ハードリンクできない少数オブジェクトへ copy-dest を併用する例
rsync -a --link-dest="$PREV" --copy-dest="$PREV" \
./artifacts/ "ci@${REMOTE_MAC}:$NEXT/"
4. 性能とリスク:走査、クロスマウント、権限とハードリンク不可
クロスマウントは赤線です。別コンテナ・USB・ネットワークではリンク可否が変わります。df でデバイス一致を確認し、無理なら tarball へ寄せます。
特殊ファイル(ソケット、FIFO、一部デバイス)はリンク不可です。--copy-dest で失敗率を下げつつ、manifest に型を載せ監査可能にします。
権限と xattr:必要フラグはバージョンで差が出ます。基準ツリーへの誤 chmod は次世代へ伝播するため、基準は読み取り中心にします。
5. 指標の置き場:ディスク倍率、リンク数、ロールバック SLA
差分が小さい版では追加ディスクをフル比で数%〜35%に抑える例が多いです。ディレクトリ項は世代に線形なので掃除ルールを別立てします。
ゲート秒数、切替秒数、ロールバック秒数をメトリクス化し、exit code だけに頼りません(例:120s / 1s / 30s の暫定 SLO)。
6. FAQ:並行ジョブ、マニフェスト、検証ゲートとの組み合わせ
質問:link-dest は SHA256 の代替か。回答:いいえ。容量と複製時間の話であり改ざん検知は manifest 側です。
質問:同一 NEXT を複数人が書くか。回答:避けます。ジョブ ID で分け、合格物だけ昇格させます。
質問:手動 SFTP と混在は。回答:権威が二重化し増分前提が壊れます。経路は一本化します。
7. まとめとホスト型 Mac への橋渡し
--link-dest を staging・manifest・SHA256・シンボリック切替の列へ入れると、リモート Mac の世代保持コストを線形から差分近傍へ寄せられます。
反面、同一ボリューム・権限衛生・並行隔離が要り、自前運用では共有アカウントや帯域争いで節約分が工数に消えることもあります。
隔離・可観測性・監査既定を初期から揃えたい場合は SFTPMAC リモート Mac レンタルとヘルプを参照し、増分と原子切替をホスト基準へ載せ替えます。