...
Back

Rust 版 coreutils 要进你的服务器了,该查的是这些

Ubuntu 26.10 完成了用 Rust 版 uutils 替换 GNU coreutils 的迁移,包括 cp、mv 和 rm。它按可直接替换来设计。而「可直接替换」是对常见路径的承诺,你的脚本活在不常见的那条上。

Rust 版 coreutils 要进你的服务器了,该查的是这些

Rust 版 coreutils 要进你的服务器了 🦀

Ubuntu 26.10 完成了两个版本前启动的迁移:GNU coreutils 被 uutils —— 一套 Rust 重写实现 —— 取代。最后三个钉子户 cpmvrm 在 26.04 LTS 里还留在 GNU 版本上,因为 uutils 那边有一批 TOCTOU 问题要先修。上游修完了,26.10 收尾。

如果你自己跑一台 Linux 服务器,这种变更很容易一挥而过。官方说法是对最终用户没有功能差异:uutils 以与 GNU 可直接替换为目标,任何偏差都按 bug 处理。这是个真实且值得肯定的承诺。

它同时也是一个关于常见路径的承诺。


「可直接替换」承诺了什么,没承诺什么

可直接替换意味着:你用的参数行为符合预期,输出长得一样,退出码对得上。对 ls -lacatchmoddu 来说,这几乎就是全部,你确实一辈子也不会察觉。

它没有承诺的是:某个脚本依赖的每一种行为都是被规定过的行为。Shell 脚本会不知不觉攒下一堆没人写进文档的依赖:

  • stderr 的确切措辞。 任何做 2>&1 | grep 'No such file' 的地方,匹配的都是一个从来不是接口的字符串。
  • 碰巧成立的顺序。 管道里不带 --sortls,或者被当成稳定的通配展开顺序。
  • 没人测过的参数组合。 在既不支持 reflink 也不支持稀疏文件的文件系统上跑 cp --reflink=auto --sparse=always
  • 某个并不存在的参数的行为。 脚本里用了 GNU 特有扩展,然后跑在实现不同的系统上。

这些都不是 uutils 的失败。它们是替换一个做了三十年参考实现的东西所要付的常规代价,而代价落在写脚本的人头上。


最要紧的那三个,正是被押后的那三个

cpmvrm 最后才切换,不是巧合。它们是会破坏性地动你数据的那几个,而它们被押后恰恰是因为 time-of-check-to-time-of-use 问题 —— 那类"路径校验完、动手之前中间变了"的 bug。

这既是当初值得等的理由,也是现在值得留意的理由。这三个同时还是你的备份脚本、部署脚本和日志轮转最依赖的。


十五分钟能测完的东西

别去审计所有脚本。把要紧的那几个拿新二进制跑一遍,比对结果。

# 我现在用的是哪个实现?
cp --version | head -1        # "uutils coreutils" 还是 "cp (GNU coreutils)"
 
# 脚本里那条确切的调用,行为还一样吗?
#   在临时目录上跑,不要在生产上。
mkdir -p /tmp/ct/{src,dst}
printf 'x' > /tmp/ct/src/file
ln -s file /tmp/ct/src/link
cp -a /tmp/ct/src/. /tmp/ct/dst/ && ls -la /tmp/ct/dst

在一台你真的在运维的服务器上,有三件事特别值得查:

  1. 备份或同步那条路径。 任何用到 cp -a--preserve、硬链接或稀疏文件的地方。确认权限、属主、符号链接和时间戳都活下来了 —— 而不只是"文件到了"。
  2. 任何解析输出的地方。 在脚本里 grep cp mv rm ls 后面跟管道的位置。每一处都是你在依赖输出格式。优先用退出码和 find -print0,别去解析。
  3. 你的错误分支。 故意让操作失败 —— 目标只读、源不存在、磁盘满 —— 确认脚本仍然能发现。退出码契约是最可能正确的部分,也是你的脚本最可能忽略、转而去匹配字符串的部分。

这件事奖励的升级纪律

Ubuntu 26.10 是过渡版本:支持九个月,不是五年。如果你拿它跑生产,你已经接受了更快的节奏。如果你跑 LTS,那你有到下一个 LTS 之前的时间去找出自己的坑 —— 而过渡版本正是找坑的地方,在一台不服务任何人的机器上。

这才是真正的建议。不是"审计你的脚本"(没人会做),而是"在 LTS 把它变成你的问题之前,在一台随手可扔的 26.10 虚拟机上,把部署和备份脚本各跑一遍"。

这次迁移的内存安全理由是站得住的,兼容性工作也明显做得认真。这两点都成立,同时你那个用了十五年的备份脚本仍然可能是例外。一台临时虚拟机、十五分钟,就能告诉你是哪种。


来源: OMG! Ubuntu · It's FOSS