近几周来,Ubuntu 25.10 在将传统的 GNU coreutils 替换为 Rust 实现的 coreutils 后,社区内开始出现一系列奇怪的兼容性问题。最明显的症状是在运行一些通过 Makeself 打包的自解压可执行文件(例如若干基准测试套件与安装程序)时出现 MD5 校验失败,导致文件无法正常解包或运行。本文将对已知现象进行梳理,分析可能的技术根源,给出短期与长期的解决方案,并为开发者与维护者提出可执行的建议,帮助尽快恢复生态兼容性并减少用户中断风险。 问题概述与典型案例 受影响的情况最先由一些 Linux 基准测试使用者发现:在同一套文件和网络存储环境下,Unigine、GravityMark 等以 Makeself 打包的可执行文件在 Ubuntu 25.10 上报出 MD5 校验错误,而在其他发行版或同一台机器上切换回 GNU coreutils 后则能正常运行。进一步测试表明,关键点集中在 Makeself 自证完整性时调用 md5sum 命令的环节;当系统使用的是 Rust 实现的 md5sum 时,部分自解压脚本判定校验不通过,但换回 GNU 的 md5sum 则通过。 这些故障不是孤立案例,Launchpad 和社区论坛已有多起相关报告,涉及 VirtualBox 的某些自解压安装包、多个基准测试套件,甚至用户自制的 Makeself 打包脚本也遇到类似问题。
与此同时,Ubuntu 开发者也注意到 Rust coreutils 在少数命令上带来了性能回归或行为差异,引发更广泛的关注。 Makeself 与 md5sum 的交互为何敏感 Makeself 是一种常见的自解压归档方式:将程序和资源以压缩数据附加在一个自包含的 shell 脚本后面,脚本在运行时解包并可选地校验资源完整性。校验通常依赖系统提供的工具链,例如 md5sum。由于 Makeself 的实现面向的是可移植性与轻量性,它会以简单的方式调用 md5sum 并对比输出字符串中的哈希值与预期值。一旦 md5sum 的输出格式、换行或某些边缘语义与早期行为不完全一致,脚本的文本匹配就可能失败,进而导致判定为校验失败。 Rust coreutils 旨在用 Rust 重写常见的 GNU 工具,目标包括性能、安全性和内存安全改进。
绝大多数场景下,新实现保持兼容,但因为实现细节、默认行为、对特殊文件或 fd 的处理方式、以及对某些历史 GNU 非标准特性的实现不同,导致在与外部脚本(尤其是对输出格式或某些空白/尾随换行敏感的脚本)交互时显露兼容性缺口。 潜在技术原因(谨慎推断) 目前还没有单一且被官方确认的"决定性"根本原因,但可以从实现层面做出合理的推断并列出几类可能的差异: md5sum 输出格式上的细微区别可能会触发基于文本精确匹配的脚本失败。比如输出末尾的换行、空格或二进制/文本标志的表现。Rust 实现可能在处理某些文件描述符、特殊设备文件或压缩流时采用不同的缓冲策略或读取方式,从而导致微小差异。md5sum 在遇到特殊字符或非普通文件(比如通过 /dev/fd 提供的流)时的处理逻辑可能不同,Makeself 在解包过程中可能采用临时文件、管道或重定向,这些用法在不同 coreutils 实现下有不同边缘行为。某些历史上 GNU coreutils 的"不严谨"行为被新的实现修正,反而暴露了依赖这些非标准行为的脚本问题。
需要强调的是,上述都属于合理的技术假设。要完全确定根因需要对具体的 Makeself 脚本、调用方式以及 Rust 与 GNU md5sum 的实现差异逐条对比、在若干边界条件下复现失败场景并进行差分测试。 短期应对策略:用户与管理员能立即采取的步骤 对于普通用户或系统管理员,最直接且低成本的应对方法是恢复或并行使用 GNU 的 coreutils 工具集,至少在问题得到根治之前让受影响的脚本继续正常工作。在 Ubuntu 25.10 的仓库中提供了 coreutils-from-gnu 之类的软件包,可以安装以恢复 GNU 实现的工具。通用操作步骤如下:先确认当前系统上 md5sum 的版本与位置,通过命令 md5sum --version 和 which md5sum 来判断当前使用的是哪个实现;如果确认是 Rust 实现导致问题,可以使用 apt 安装 coreutils-from-gnu 包并将系统或特定脚本指向 GNU 的 md5sum。对于不愿或不能更改系统默认工具链的场景,可以在运行 Makeself 包的命令前临时以完整路径调用 GNU 版本的 md5sum,或者在容器/虚拟环境中运行这些自解压脚本。
对于受影响的个人用户,最安全的命令形式是:先更新包索引,然后安装替代包(示例命令为 apt update && apt install coreutils-from-gnu)。安装后再次验证 md5sum --version,应能看到 GNU 标识。如果你不希望改变全局工具链,可以用 which md5sum 找到 GNU md5sum 的路径,并在脚本中临时替换或用环境变量指定该路径。 对 Makeself 使用者和打包者的建议 依赖外部工具输出格式的打包脚本应当增强健壮性。Makeself 的自解压脚本通常是面向通用 Linux 环境的,理想的改进方向包括降低对具体输出格式的敏感度,采用更可靠的哈希校验方法(例如优先使用 sha256sum、sha512sum 等更现代的散列函数),在比较哈希时去除末尾空白或以更灵活的匹配方式处理换行符。另一个可行策略是将校验逻辑改为直接使用内置的脚本级别校验函数(例如在解包脚本内部使用 openssl 或 Python 等语言运行环境来计算哈希),以减少对系统工具细节的依赖。
对于打包者而言,还应在发布前于多个主流发行版与环境下进行测试,尤其是在刚刚发生大规模替换如 coreutils 实现后,应将这些测试列入持续集成(CI)流程,避免因底层工具差异造成批量用户受影响。 发行版维护者与上游应对思路 从发行版角度来看,替换关键用户态工具实现是一个具有高风险的工程决策。虽然长期来看 Rust 实现可能带来性能和安全优势,但在逐步迁移过程中需要保持向后兼容性或提供平滑回退机制。Canonical 与 Ubuntu 的工程团队可以采取的措施包括在发布分支上保留 GNU coreutils 的并行包、提供简单的切换工具或 update-alternatives 配置,并在变更说明中清晰标注风险点与已知不兼容案例。 从 Rust coreutils 项目自身来看,增强与 GNU 行为的一致性、扩展测试用例以涵盖更多真实世界脚本交互场景将非常重要。维护者可以与 Makeself 上游、VirtualBox 等受影响项目沟通,收集具体失败样本并复现问题,进而在实现中修补差异或提供兼容层。
开源社区的协作和快速的问题归因、回退补丁能显著缩短用户受影响的时间窗口。 中长期改进建议 减少因为底层工具替换带来的生态断裂,需要多方配合。发行版应在工具替换时提供明确的兼容性测试套件,重点覆盖常见自解压脚本、安装器与包装格式。开源项目应在 CI 中增加对多种 coreutils 实现和多版本系统的测试矩阵。打包工具如 Makeself 可以升级为更健壮的校验实现或提供兼容性开关,让发布者能够根据目标发行版选择更稳妥的校验方法。 对于需要高度可移植的二进制分发,建议优先使用现代哈希(如 SHA-256)并在打包内置校验实现,避免对外部工具输出的过度依赖。
对敏感环境或大型用户基础的软件供应商,应在重大发行版更换关键组件时与发行版维护团队保持沟通,以便提前识别与修复潜在问题。 如何协助诊断与上报问题 当遇到类似问题时,收集可复现的最小示例和日志至关重要。记录受影响的 Makeself 包、具体的 md5sum 输出、md5sum --version 与 which md5sum 的结果、以及在使用 GNU md5sum 时的差异输出。将这些信息提交到 Launchpad(针对 Ubuntu)或 Rust coreutils 的 issue 列页,并尽可能将失败示例打包为最小复现案例以便上游开发者调试。社区协作能极大加速问题定位与修复。 结论:平衡创新与兼容的实践教训 Ubuntu 25.10 采用 Rust 实现的 coreutils 是一次重要的技术尝试,目标包括提升安全性和长期维护性,但在真实世界的复杂性面前,向后兼容性仍然是关键。
Makeself 等广泛存在的脚本包装器对底层工具的依赖暴露了迁移中的脆弱点。短期内,安装 coreutils-from-gnu 或在容器中回退至 GNU coreutils 是有效的缓解方法;中长期需要通过更完善的测试、上游补丁与打包工具改进来消除兼容性裂缝。 对终端用户而言,遇到 MD5 校验失败时优先检查当前 md5sum 的实现并考虑短期回退或替代。对打包者和维护者而言,应当提高脚本的鲁棒性并在 CI 中覆盖更多环境。对发行版维护团队而言,透明的变更通知、并行包支持和快速的回滚通道将有助于在推进底层技术演进时尽量减少对用户的影响。社区的快速响应与协同修复将是最终降低这种迁移风险的关键。
如果你是受影响的用户并希望获得帮助,建议先收集并保存出现错误时的完整输出,然后在社区论坛或 Launchpad 上附上该信息;如果你是开发者或维护者,考虑将相关测试用例纳入 CI 并与 Rust coreutils 上游保持沟通,协力推动一个在性能与兼容性之间更平衡的实现方向。 。