跳转到内容

大文件分卷与光盘交付

把 10 GB 以上的离线包切成若干卷、刻盘带到现场、在目标机上合并校验解包。本文记录实测验证过的完整链路。

Linux 常用命令 中"对 tar.gz 文件进行切割和合并及 md5 校验"一节的关系:那节是纯 Linux 侧的切割思路,本文补上 Windows 侧分卷、光盘刻录约束、以及 PowerShell 编码坑

结论

  • 已经是 .tar.gz 的成品包不要再打一次 tarsplit 只做字节切片,tar 只负责最后解包,两者不叠加。
  • Windows 上 split / md5sum / bash 来自 Git for Windows 的 Git\usr\bin,该目录不在 PATH 里(安装程序只加了 Git\cmd),需全路径调用或临时补 PATH。
  • PowerShell 的 > 重定向写 UTF-16LE,生成的 md5 校验表 md5sum -c 读不了,必须用 cmd /c 做重定向。
  • 光盘必须用 UDF 格式。ISO9660-only 会截断长文件名,分卷顺序错乱,合并出来是坏包。
  • 分卷校验要逐卷做,这样哪张盘划伤在合并前就能定位,不用重刻全部。

适用范围与环境

环节运行环境
分卷Windows PowerShell 5.1(用 Git 提供的 coreutils)或 Linux
生成校验表同分卷侧
刻录Windows 刻录软件
读取 / 合并 / 校验 / 解包现场 Linux 服务器

实测样例:Devops_Kubernetes_arm64_v8.20.0.tar.gz,18,690,897,878 字节(17.41 GB),按 7 GB/卷切分。

前置条件

  • 原包完整,且已有一个权威的 md5/sha256 值(通常随包提供 .md5 文件)。
  • 输出盘剩余空间 ≥ 原包大小。分卷不压缩,所有分卷加起来等于原包体积。
  • Windows 侧已装 Git for Windows(提供 split.exe / md5sum.exe)。

先确认 coreutils 的位置,Windows 上不要假设它在 PATH 里:

powershell
Get-Command split -ErrorAction SilentlyContinue
# 无输出 = 不在 PATH,用下面两种方式之一

步骤

1. 分卷

Windows PowerShell(已验证):

powershell
# 方式 A:临时补 PATH,仅当前窗口有效
$env:Path += ";D:\software\Git\usr\bin"
cd <包所在目录>
split -b 7G -d -a 2 Devops_Kubernetes_arm64_v8.20.0.tar.gz devops_pkg.part-

# 方式 B:不动 PATH,直接写全路径(路径无空格时不需要 & 调用运算符)
D:\software\Git\usr\bin\split.exe -b 7G -d -a 2 Devops_Kubernetes_arm64_v8.20.0.tar.gz devops_pkg.part-

Linux 侧等价命令:

bash
cd <包所在目>
split -b 7G -d -a 2 Devops_Kubernetes_arm64_v8.20.0.tar.gz devops_pkg.part-

参数含义:

参数作用
-b 7G每卷 7 GiB(7 × 1024³ = 7,516,192,768 字节)。要十进制 7,000,000,000 用 -b 7GB
-d后缀用数字(0001…)而不是字母,保证 glob 排序正确
-a 2后缀宽度 2 位。分卷数会超过 99 时改 -a 3
末位参数输出前缀,实际文件名为 前缀00前缀01

本样例产出 3 个文件:part-00 7 GiB、part-01 7 GiB、part-02 3.41 GiB。

输出文件名不要太长。 刻录到 ISO9660 时超过 8.3 的名字会被截断,短前缀(如 devops_pkg.part-)更稳。

2. 生成分卷校验表

Windows PowerShell(已验证):

powershell
cmd /c "D:\software\Git\usr\bin\md5sum.exe devops_pkg.part-* > devops_pkg.parts.md5"

Linux 侧:

bash
md5sum devops_pkg.part-* > devops_pkg.parts.md5

这里必须用 cmd /c 包一层。 PowerShell 的 > 默认写 UTF-16LE(带 BOM),md5sum -c 会报 no properly formatted MD5 checksum lines found。 自检方法——读首字节:[System.IO.File]::ReadAllBytes($f)[0..3]55 54 46 2D 是 UTF-16 BOM(错), 纯 ASCII 哈希表应以十六进制字符开头(如 62 36 36 39 = b669)。

3. 刻录

一张盘放一个分卷;把 devops_pkg.parts.md5 一起刻进第一张盘,现场才有校验依据。

格式必须选 UDF,不要 ISO9660-only。

容量要按介质算,7 GB/卷不是随便定的:

介质容量能否装 7 GB/卷
CD-R700 MB
DVD-54.7 GB
DVD-9(双层)8.5 GB是,留余量
BD-2525 GB
BD-5050 GB

如果手上只有 DVD-5,把分卷大小改成 -b 4500M,本样例会切成 4 卷。

4. 现场读取(Linux)

逐张盘挂载并拷贝:

bash
mkdir -p /mnt/cdrom /root/devops
mount -t udf /dev/sr0 /mnt/cdrom
cp /mnt/cdrom/devops_pkg.part-* /root/devops/
umount /mnt/cdrom

换盘后重复。所有分卷拷到同一目录即可。

5. 合并、校验、解包(Linux)

bash
cd /root/devops

# 5.1 先逐卷校验——坏盘在这一步就能定位,不必等合并完
md5sum -c devops_pkg.parts.md5

# 5.2 按序合并
cat devops_pkg.part-* > Devops_Kubernetes_arm64_v8.20.0.tar.gz

# 5.3 整包校验
md5sum Devops_Kubernetes_arm64_v8.20.0.tar.gz   # 期望 9aa9afa93c273f86c6c8a40d5c24c3b9

# 5.4 解包
tar -xzf Devops_Kubernetes_arm64_v8.20.0.tar.gz

如果随包提供的是裸哈希.md5 文件里只有 32 个十六进制字符,没有文件名),md5sum -c 无法直接消费它,改用:

bash
[ "$(md5sum Devops_Kubernetes_arm64_v8.20.0.tar.gz | cut -d' ' -f1)" = 9aa9afa93c273f86c6c8a40d5c24c3b9 ] \
  && echo MD5-OK || echo MD5-FAIL

机制说明

为什么成品包不要再 tar 一次。 常见的 tar czf - dir | split -b 7G - x.part- 写法适用于"从目录现场打包",因为 tar 的 stdout 直接流进 split,不落中间文件。但对已经是 .tar.gz 的成品,再走一遍只是把已压缩的数据重新 gzip 一次:耗掉大量 CPU 和时间,体积几乎不变。此时 split 单独作用即可。

-d 为什么重要。 split 的默认后缀是字母(aaab…)。数字后缀配合固定宽度,字典序与数值序一致,cat part-* 才能按正确顺序拼接。字母后缀在超过 26 卷时(zazab)也会乱序。

分卷为什么不能单独解压。 split 是纯字节切片,切点与 gzip 的块边界无关。任何单卷都不构成合法的 gzip 流,必须先按序拼回完整文件。

风险与边界

  • 分卷不压缩,只做切分:所有分卷体积之和 = 原包体积,不会变小。输出盘需预留同等空间。
  • cat part-* 依赖文件名排序:前缀固定宽度 + -d 才安全;手工改过卷名或刻录时名字被截断都会破坏顺序。逐卷 md5sum -c 是发现这类问题的必要手段。
  • 在线切割不是原子的:若原包正在被写入,切出来的分卷可能不一致。切割前确认原包写入已结束。
  • 光盘比硬盘脆弱:UDF 格式 + 逐卷校验能把"读不出来"和"读出来是坏的"区分开;每卷单独校验值就是为这个场景准备的。
  • md5 只用于校验传输完整性,不是防篡改手段。对外交付如需防篡改应改用 sha256。

验证与实际结果

以下为已验证结果(2026-09-11,本机实测)。

用 30 字节探针文件跑完整链路,确认切分—校验—合并三个环节字节无损:

text
全路径 split.exe 切分            -> 29 个分卷,正常
cmd /c 生成的校验表首字节        -> 62 36 36 39("b669",纯 ASCII)
md5sum -c 逐卷回读               -> 全部 OK
按序 copy /b 合并回原文件        -> md5 与源文件完全一致(8a250fcd46bdbb7ab60d0973c4051308)

反例(同一实测中确认的失败现象):

text
PowerShell 的 > 重定向生成校验表  -> md5sum -c 报 no properly formatted MD5 checksum lines found
用户窗口直接执行 split           -> CommandNotFoundException(因为 Git\usr\bin 不在 PATH)

注意:在 Hermes terminal 里 Get-Command split 可能解析成功,而用户自己的 PowerShell 窗口失败——两者 PATH 不同。给出依赖外部 exe 的命令前,应查持久 PATH:[Environment]::GetEnvironmentVariable('Path','Machine')

参考来源

无外部资料,全部来自本机实测。

基于 MIT 许可发布