三类痛点:为什么「传完」仍可能在发布后才爆雷
痛点 1:静默位错误与跨文件系统时间戳。默认 rsync 以大小与 mtime 作为「是否需要重传」的主要启发式条件;当构建机与远程 Mac 分属不同文件系统、或 NFS/容器层导致时间戳精度被截断时,可能出现跳过实际已损坏文件的假阴性。对包含数千小文件的 dist 目录,这种假阴性会在 CDN 或签名校验阶段才暴露,排障成本指数级上升。
痛点 2:断线与半包。大文件上传中断后若未用 --partial-dir 隔离临时文件,恢复时目录可能处于不可声明一致态;CI 重试还会与残留交错,必须把批次号写入审计,不能只看最后一次退出码。
痛点 3:SFTP 侧无法回答「谁写了什么」。多人共用同一写入账号、或图形客户端默认不记录本地操作者时,服务端日志只能看到认证成功与字节数,难以对应到具体发布批次。与多租户隔离和并发预算协同时,若缺少按流水线拆密钥与按目录打标签,审计字段会长期空白,合规抽查也无法过关。
为何 2026 年仍不能把「mtime + size」当作完整性证明
mtime/size 是元数据近似,不是内容充分条件:touch 统一时间戳、解压改写权限、同大小占位文件等均可造成假阴性。强交付链路应在里程碑使用摘要:要么 rsync --checksum(CPU 更贵),要么流水线生成 manifest 并在远端 shasum -c 硬闸门;后者更易配合原子发布:先校验 releases/<批次> 再切 current。SFTP 与 rsync 对符号链接与扩展属性的默认处理不同,须在规范中固定 flags,manifest 只列业务相关文件,避免误报。
决策矩阵:全量 checksum、独立 SHA256 清单与发布后抽检
下表帮助在 CPU、时间与风险之间做显式取舍;可与团队 SLAs 对齐后写入仓库内规范。
| 策略 | 适用场景 | 主要成本 | 失败时可观测性 |
|---|---|---|---|
rsync --checksum(-c) | 目录中等、CPU 充裕、希望单命令闭环 | 两端全文件哈希扫描,大目录可能数倍延长 | 同步日志中可见跳过/重传原因 |
构建端 manifest + 远端 shasum -c | CI 已生成产物包、需与发布闸门脚本统一 | 维护 manifest 生成与路径规范化 | 非零退出码直接阻断切链,易集成 Slack/邮件 |
| 发布后抽检 + 监控 | 极大仓库、全量校验不可接受 | 仍存在低概率漏检,需要抽样设计 | 依赖线上探针与签名比对,滞后可能以小时计 |
| 仅 size/mtime(默认 rsync) | 内网千兆、信任域极高、临时同步 | 最低 | 最差;不推荐作为生产发布主路径 |
实操:rsync 断点、带宽与 CI 校验闸门(至少五步)
下列命令需在测试环境验证后再用于生产;将 deploy@remote-mac 与路径替换为你的远程 Mac 或托管节点。与原子发布结合时,目标应为版本目录而非直接覆盖对外路径。
# 步骤 1:在构建端生成 SHA256 清单(示例:dist 目录)
cd dist && find . -type f -print0 | sort -z | xargs -0 shasum -a 256 > ../manifest.sha256
# 步骤 2:带断点与部分目录的 rsync(降低半包污染当前目录)
rsync -avP --partial --partial-dir=.rsync-partial \
--bwlimit=8000 \
-e "ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=6" \
./ ../manifest.sha256 \
deploy@remote-mac:/srv/app/releases/202603281200/
# 步骤 3:远端执行校验闸门(非零则禁止切链)
ssh deploy@remote-mac "cd /srv/app/releases/202603281200 && shasum -a 256 -c manifest.sha256"
# 步骤 4:通过后记录审计批次(示例:写入 JSONL)
ssh deploy@remote-mac "echo '{\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"batch\":\"202603281200\",\"gate\":\"shasum\",\"exit\":0}' >> /var/log/ci-publish-audit.jsonl"
# 步骤 5:再执行 ln -sfn 或等价原子切换(参见原子发布专文)
# ssh deploy@remote-mac "ln -sfn /srv/app/releases/202603281200 /srv/app/current"
若必须使用纯 SFTP上传,仍可在上传结束后于远端用同一份 manifest.sha256 做校验;关键是不要让图形客户端在校验前就对生产路径做 in-place 覆盖,而应写入 releases 子目录,与软链发布模型一致。
可引用数据:闸门阈值、磁盘与审计保留周期
基线建议:(1)空闲空间 ≥ 单次包体2.5 倍(断点文件、上一版、manifest)。(2)CI 超时 ≥ P95 同步耗时三倍;300MB 级跨国常见 45–180 秒。(3)审计含流水线 ID、提交 SHA、批次目录、校验退出码、主体;保留 ≥ 90 天。(4)启用 --checksum 后记录首次全量基线耗时。写入账号仅写 releases/*;只读账号读 current。与Chroot 组合时可限制 CI 仅单一前缀。
FAQ、内链收束与为何考虑租赁远程 Mac
断点续传目录要提交到 Git 吗?
否。.rsync-partial 应加入 .gitignore;仅在发布机保留,用于传输中断后的安全恢复。
manifest 与 npm/yarn 锁文件有何关系?
锁文件约束依赖版本;manifest 约束构建产物字节级输出。二者互补,不能互相替代。
何时必须上独立校验闸门而非仅依赖 rsync 退出码?
当产物用于签名校验、应用商店上传或付费客户交付,且链路包含公网或多跳代理时,应在切流量前执行 shasum -c 或等价步骤。
自建与租赁远程 Mac均可复现上述流程;自管需承担磁盘告警、密钥轮换与带宽抖动。发布频次升高时,把隔离目录与 SFTP 准入交给托管可省救火时间。SFTPMAC 支持在受控目录内继续使用断点、SHA256 闸门与软链模型。建议预发先跑通「同步 → 校验 → 切链」再切生产。
若希望减少自管远程 Mac 的磁盘、权限与在线率问题,把 SFTP 准入与目录隔离交给专业托管,同时继续用 rsync 与校验闸门保障产物完整性,可以了解 SFTPMAC 的套餐与节点选型。
