为什么现在什么都用Rust写?
当时我在办公桌前等脚本运行,突然发现我的工具链语言变了。脚本原本是用 pixi 运行的,而 pixi 是用 Rust 写的。它的运行环境来自 uv,也是 Rust。我赶紧拿出 ripgrep 来查找一个我几乎不熟悉的函数,还没来得及往后靠在椅背上,它就返回了结果。
而且这还不是我一个人遇到的情况。Solid 2 自带一个基于 Oxc 的 Rust 编译器工具链,其性能比它所取代的 JavaScript 编译器快 20 到 350 倍。Bun 花了 11 天时间,用 Rust 重写了 50 万行代码。Linux 内核正式支持 Rust。Vite 正在将底层打包工具从 JavaScript 替换为 Rust。Debian 正在 APT(一个你曾经登录过的很多服务器都使用的软件包管理器)中强制添加 Rust 依赖,并要求四个缺少可用 Rust 工具链的架构在六个月内完成升级,否则将被淘汰。到了现在,我干脆用 Rust 写这篇文章算了。🤣
这一切都不是我事先决定的。一个工具替换了另一个,一个库在熟悉的命令下被替换,我日常工作的默认语言也未经我允许就切换了。
这值得我们仔细思考一下,因为这并非一个循序渐进的过程。我最初是为了写这篇文章而深入挖掘,结果发现这可能是软件史上规模最大的协同迁移项目,而且我越深入了解,就越觉得这不像是一个关于语言的故事。
我有点跑题了。我们先从 bug 类说起,因为接下来要讨论的一切都与它息息相关。
1、我曾经编写这个运动正在淘汰的代码
内存安全是一个狭窄、不起眼的保证:程序不能读取或写入它不拥有的内存。当C或C++程序越过数组末尾,或者在将内存归还给系统后继续使用它时,你会得到那些有着著名名字的错误家族。缓冲区溢出。释放后使用。它们不是逻辑错误;程序完全按照指令执行。它们是语言从未检查的权限错误。
我职业生涯的早期大部分时间都在那个世界中度过。在一家名为Pathware的初创公司,我为一台计算显微镜编写了傅里叶叠层成像算法,这是一种从不同照明角度捕获的一堆低分辨率图像中重建单个高分辨率图像的技术。构建一台定制显微镜意味着大量的复杂线性代数,比我预期的要多,而真正造成混乱的部分很少是我猜测的那些。数学大多表现正常。内存则不然。我们不断遇到内存安全问题,并通过手工逐一解决,这就是当时的做法。我不记得当时认为这是一个语言问题。后来,在航空宇宙公司,不同的领域,又是C++。
你接受手动内存管理作为速度的代价,并告诉自己你很小心。每个人都告诉自己他们很小心。
然后平台所有者公布了他们的数据。微软和Chrome都报告说,大约70%的严重安全漏洞是内存安全错误。不是冷门的。是大多数。这一个统计数据成为安全社区的北极星,因为它重新定义了情况:内存不安全不再是工艺问题,而成为可衡量的、可预算的负债。
Android是我们拥有的最干净的实验。谷歌开始用Rust编写新的Android代码,同时基本保持旧的C和C++不变。内存安全问题从2019年占Android漏洞的76%下降到2024年的24%。没有英雄式的重写。只是新代码的不同默认值,随着旧代码停止被触及,旧错误逐渐消失。
在这个头条之下,是一些我仍然不知道如何处理的数据。Android的Rust代码的内存安全漏洞密度大约是其C和C++的千分之一,这正是你所希望的。Rust更改的回滚率大约是四分之一,代码审查时间少25%。最后一个我一直在思考。这门有着与你斗争声誉的语言产生的更改,审查者显然争论得更少,我有理论但不会在公开场合捍卫它们。
2、栈的底部先走了
Linux内核在2025年12月结束了Rust的实验状态,GPU驱动程序和核心基础设施现在正在进入主线。对于一个二十年来对C++说不的项目来说,这是一个值得走过的非凡之门。
Ubuntu比我预期的走得更远。25.10将sudo-rs(用Rust重写的sudo)作为默认设置发货。第一个这样做的主要发行版。有一个名为oxidizr的工具,其全部工作是将GNU coreutils替换为Rust uutils版本,目标是Ubuntu 26.04 LTS。你手指下的命令,ls和cp和sort,现在是迁移。我不知道是否按时发布。Canonical之外没有人知道。但没有人半心半意地构建一个名为oxidizr的工具。
同样的替换正在更远离核心的地方发生,大多没有新闻。youki在runc曾经运行的地方运行容器。Arti是一个全新的Tor实现。rustls坐在OpenSSL曾经坐的地方,ntpd-rs保持时钟,fish重写了它的整个shell。这就是为什么我在上面说你的shell;如果你使用fish,你一直在运行Rust而没有被告知。至于这一切有多完整,截至2026年初,uutils与GNU coreutils的测试对等率为92.2%。
微软正在做只有微软才会做的事情:将win32k图形代码移植到Rust,GDI区域代码已经在Windows内部发货,并重写SymCrypt加密库,在其之上进行形式化验证。加密和字体解析正是你按爆炸半径分类时会开始的地方。
你的构建工具比你先到达那里。在Python中,uv每月下载约1.26亿次,是2025年Stack Overflow调查中最受喜爱的技术,这是我从未想过会写关于包安装器的句子。我们过去常以运动的方式争论pip。OpenAI在3月19日宣布收购Astral,即uv和ruff背后的公司。在JavaScript方面,Vite 8用Rolldown和Oxc替换了内部组件,两者都是Rust,构建速度快了10到30倍。如果你编写Solid、Vue或Svelte,你的框架从未改变语言,但你的代码走向生产的整条路径确实改变了。
Bun是我最喜欢的数据点,因为它最混乱。5月,Bun团队宣布他们将53.5万行Zig重写为Rust,使用64个并行Claude实例在11天内推送了6,778次提交。2,000次构建后,内存使用量从6.7 GB降至609 MB。Zig的创建者Andrew Kelley称结果为"未经审查的垃圾"。与此同时,Rust构建仍是一个没有发布日期的并行实验。这两点都很重要。重写以不可能的速度发生,三个月后,你安装的二进制文件仍然是Zig的那个。
3、这一切之下有一个截止日期
推动内核和加密库的是采购、资金,最终是责任。责任是集中注意力最快的一个。一旦利害关系是国家安全和以数十亿美元衡量的企业风险,"重写太难了"就不再是任何人接受的答案。
2024年初,白宫国家网络总监办公室用平实的联邦语言论证了让关键软件摆脱内存不安全语言的必要性。ONCD编写国家网络安全战略;它不执行任何东西,这在衡量该文档重要性之前值得了解。然后CISA和联邦调查局跟进了一些更具体的东西。CISA是网络安全和基础设施安全局,国土安全部的一个部分,其指导方针被关键基础设施运营商期望遵循,其要求很具体:在2026年1月1日之前发布内存安全路线图,优先处理面向网络的代码和加密。
内存安全路线图是一份比名称听起来更枯燥的文档。它命名你的代码库中哪些部分是内存不安全的,将那些面向网络或处理加密的部分标记为优先事项,并说明你计划如何以及何时将缺陷从它们中移除。这是承诺日期的文书工作。这些都不具备法律效力,这是人们想要跳过它时会抓住的细节。
再读一遍那个日期。它已经过去了。我们已经过了内存安全是前瞻性建议的时刻——我们现在处于一个没有迁移故事的C++代码库是客户可以提出的问题的时代。当我说这次迁移更多是关于时代而非语言时,这就是我的意思。在过去两年的某个地方,内存不安全变成了许多供应商必须书面解释的东西,我不确定有人决定了那么多,因为它只是累积了。
4、重写实际上成本多少
这里我需要小心不要写广告。
小规模重写需要几个月。中等规模的需要一到两年。最大的可能需要两到五年,相当多的重写完全失败。Prisma将其Rust查询引擎移回TypeScript,理由是技能差距和部署复杂性。Loglog Games三年后放弃了,结论让我印象深刻:重构优秀,迭代速度差。curl尝试采用hyper(Rust HTTP库)达到了95%,然后在最后5%上死了。
一些性能提升甚至不是Rust的。uutils sort运行速度大约是GNU sort的四倍,ripgrep在6秒内处理了37 GB目录,而grep需要52秒。但其中一部分是用三十年后见之明重写任何东西的优势,没有向后兼容的伤疤组织。一些归功于语言的功劳是重新开始赢得的,我认为没有干净的方法从外部将两者分开。
当微软将TypeScript编译器移植到原生代码时,团队选择了Go。不是Rust。他们想要与现有代码库的结构兼容性和大团队的速度,垃圾收集对他们的工作负载来说已经足够了。在行业历史上最大的内存安全推动中,地球上最受关注的编译器项目之一看着Rust,合理地说了谢谢,不用。
5、回到那十一天
我在Bun的故事中也太快地略过了一些东西,它值得单独一节。
那次重写花费了约16.5万美元。将这个数字与刚才的时间线对比一下。五十万行系统代码在两种语言之间移动是一个两到五年的项目,由已经精通两种语言的人员组成,而Bun在11天内完成了,预算甚至不够一个高级工程师一年的费用。
在我职业生涯的大部分时间里,编译语言在成本上输掉,而不是在质量上。你需要已经知道它的人,那个人很难雇佣,工作时间足够长,问题可能在你发布之前就不再重要了。Prisma自己解释恢复到TypeScript时将技能差距放在首位,这是穿着技术外衣的人员配置判决。
模型恰好非常擅长使Rust昂贵的特定事情。设计工作仍然是人类的,关于重写是否值得尝试的决定也是如此。剩下的是枯燥的中间部分:将已知正确的实现从一种语言移植到另一种语言,与对第400行有异议的借用检查器协商,编写没人喜欢的FFI样板代码。Rust的学习曲线一直是前端加载和机械的,这接近于人类最差的模型,接近于模型最好的。
从我的角度来看,这对那些永远无法资助的工作最重要。研究软件充满了应该是更快东西的Python,它保持Python是因为研究生有18个月和论文要完成,而不是因为有人权衡了工程权衡并选择了慢。当编译实现不再花费某人一年的生命时,那些被搁置为不合理的项目开始再次看起来合理。不是所有项目,也不是那些一开始就是坏主意的项目。
然后Kelley的判决降临其上,那百万行代码中没有一行达到稳定版本。
这两件事同时成立,我不认为紧张关系能干净地解决。编写Rust变得便宜了。审查是成本去的地方,仍然有人必须阅读一百万行更改的代码。我还没有看到任何愿意接手这项工作的模型。
6、逃生舱是语言的一部分
Rust让你关闭保证。
这被排除在推销之外,如果你是决定团队是否迁移的人,这是我想先知道的部分。
关键词是unsafe,它字面意思就是它所说的。在unsafe块内,编译器停止执行使Rust内存安全的规则。你可以解引用原始指针。你可以直接调用C库。借用检查器退后一步,相信你的话。
这不是任何人忘记关闭的疏忽。它必须存在,因为迟早程序必须与硬件对话,或与用C编写的操作系统对话,或与永远不会重写的库对话。一个不能做这些事情的语言无法运行内核,这正是内核和Windows能够接受Rust的原因。
问题是它使保证比口号更窄。人们使用unsafe的地方往往是驱动程序、分配器、你将指针交给别人C的边界。也就是说,危险的工作仍然集中在选择退出检查的代码中,编译器的承诺在这些块的边缘停止。
你得到的回报是一张地图,这不是什么都没有。grep一个不熟悉的Rust代码库中的unsafe,你就有了一份午饭前要看的地方清单。三十年的C交给你整个仓库,祝你好运。有清单不等于读过它,我不知道有多少团队实际上这样做。但Rust在除了有人标记的地方之外的所有地方都是内存安全的,这些地方是可搜索的。
7、然后,六天前,另一只鞋掉了
8月20日,攻击者在crates.io(Rust的包注册表)上发布了arrayref、internment和append-only-vec的恶意版本,使用了被泄露的维护者凭据。被投毒的版本引入了一个名为proc-macro1的拼写错误包,一个真正的proc-macro2的假兄弟,其构建脚本下载了一个在编译时运行的有效负载。被泄露的包总共约占2.45亿次生命周期下载。Rust安全团队在它上线后86到107分钟内拉取了每个恶意版本,根据Nextron Systems的报告工作,这比我记忆中的任何注册表响应都快。Wiz的研究人员随后将该基础设施与朝鲜国家行为者联系起来,与一个被追踪为UNC1069的组织有重叠。
我过去一年一直在写这个确切的剧本。npm被黑了。React被黑了。LiteLLM、GitHub。每一篇都以同样的地方结束:弱点是我们默认扩展到依赖的信任。现在内存安全语言的生态系统运行了相同的脚本。
这不是内存安全错误。这是信任错误。
借用检查器验证的任何内容与被盗凭据或在编译时在你的机器上执行任何它喜欢的构建脚本无关。Linux内核Rust代码中的第一个CVE从另一个角度说明了同样的观点:它是一个竞争条件,内存安全永远不会捕捉到的一类错误,普通逻辑错误得到同样的通行证。在没有人标记为不安全的代码中,Rust关闭了一整类漏洞,这是一个大而昂贵的类别。注册表、维护者账户、构建脚本、被盗凭据:这些都不会因为实现语言的改变而变得更安全。
8、模型正在两方面工作
再回到那十一天,因为那个故事有一个版本,我就是那个标记。
使五十万行迁移负担得起的能力也打开了一条几年前不存在的供应链故障,它比我开始阅读这篇文章时预期的走得更远。
向编码模型请求一个库,它有时会命名一个不存在的库。这个名字通常是发明而不是拼写错误,听起来合理且完整产生。一项针对576,000个样本的学术研究发现,幻觉包名称的比率为19.7%。云安全联盟发现,其中43%的发明名称在每次重新运行同一提示时都会返回。稳定是那句话中造成伤害的词。一次性的幻觉是噪音,但可重复的幻觉是某人可以抢占并等待的名字。5月,研究人员发现了127个幻觉包名称,Claude Sonnet 4.6、GPT-5.4-mini、Gemini 2.5 Pro和DeepSeek V3.2都产生了。相同的假名,跨越四个不同实验室的模型。
有人称之为slopsquatting,我讨厌但无法改进。
当代理是安装的那个时,风险会扩大。一个人阅读proc-macro1坐在proc-macro2旁边时,至少有机会仔细查看。代理检查名称是否解析,如果解析,它就安装。朝鲜操作者已经为此故意构建:PromptMink活动编写了npm README文件,旨在对语言模型而不是人类阅读时显得权威。
天花板也高于麻烦。Anthropic报告称破坏了它所描述的第一次AI协调的网络间谍活动,一个中国国家支持的团体操纵Claude Code自己对大约三十个目标进行入侵。
所以账本两边都有条目。将编写Rust的成本从数年削减到十一天的模型也削减了运行入侵活动的成本,并且引入了2023年没有人有的依赖信任问题。这两者都远远超出了借用检查器的监视范围。它们回到了同一个老问题,即你刚安装的东西是否是你打算安装的东西。
9、周一实际怎么做
这些大部分落在某个地方维护C或C++的人身上,所以从那里开始,从路线图开始而不是任何代码。我会首先列出用内存不安全语言编写的组件,然后标记那些解析不可信输入或面向网络的组件,并给最差的两个设定真实日期。这涵盖了CISA实际要求的大部分内容,我宁愿在缓慢的周四起草它,而不是在审计员等待的时候。
如果你编写Rust,工作范围更窄。Rust安全团队发布了一个命令,用于检查被泄露的版本是否曾经到达你的机器,扫描你的本地~/.cargo/registry/cache以查找受影响的发布。即使你相当确定,我也会运行它。然后去读你的构建脚本做了什么,因为build.rs在编译时以你的权限执行任意代码,我敢打赌我们大多数人从未打开过属于我们安装的依赖的构建脚本。
如果代理为你添加依赖,在安装之前添加一个步骤:确认包在你的模型建议它之前就存在。下载、仓库、历史记录。这就是全部检查,它在稳定的幻觉到达你的锁文件之前捕捉它们。
其他人得到简短版本:打开你的依赖树,计算维护者而不是包。我不断回到这个数字,因为它是这个故事中语言迁移没有触及的一件事。
10、更大的基础,更大的目标
那么为什么现在一切都用Rust编写?因为这一次,安全性、性能和责任都在大致相同的方向上推动,工具变得足够好,切换不再需要信念。我的终端更快了,我的操作系统更安全了,我为此没有支付任何费用,我不确定我甚至会抱怨什么。
但我一直翻来覆去的是我们实际交换了什么。我们用一个我们理解的错误类别换取了一个在没有人预算的方向上不断增长的攻击面。模型发明了一个依赖名称,某人已经注册了它。一百万行的重写在十一天内落地,没有人读过它们。更安全的砖块,更大的建筑,以及自从npm事件以来我们一直想更换的前门上同样廉价的锁。
我没有一个整洁的地方来结束。迁移是值得的;仅Android的数据就为我解决了这个问题。这只是不是全部答案,那些将其作为唯一答案出售的人正是那些对下一个arrayref感到惊讶的人。
原文链接: Why Is Everything Written in Rust Now?
汇智网翻译整理,转载需注明出处。