以后装 .NET SDK,可能真的只需要一行命令了
装 SDK 这件事,一直是笔糊涂账
每次有人问我"机器上装 .NET 要注意什么",我都答不出一句完整的话。
Windows 上你得去下安装器,勾一堆选项;macOS 上 brew 和官方 pkg 两套说法,谁对谁错能吵半天;Linux 上 apt、tarball、dotnet-install.sh 三条路同时在跑。装完文件散在系统目录里,想删干净还得翻文档。
更烦的是多版本。一个老项目钉在 8.0,新项目要 10.0,CI 上还得跑 preview。三套 SDK 挤一台机器,环境变量一改,昨天还能 build 的项目今天就报找不到 SDK。
这个局面,微软自己也知道难看。
10 月 15 日,微软自己下场了
.NET 博客发了篇 Introducing dotnetup,作者 Chet Husk,正式把 dotnetup 推到公共预览。定位很直白:官方出的 .NET 工具链管理器,基本就是 ".NET 版的 rustup"。
dotnetuppreview-8c1303博客开头那段话挺有意思,它没有吹功能,先承认了现状:macOS 和 Linux 上装 .NET 历来要在包管理器、tar 包、独立脚本之间做选择,而这些方式"经常和权限撞车、把文件撒得满 root 目录都是、让多版本共存变得比本该的更别扭"。
官方给的目标是"大幅降低概念数量"。翻成人话就是:别再让人先搞清楚自己平台上该用哪种装法了。
它到底解决了什么
官方列了五条设计目标,我按自己的理解重新排了一遍:
一套命令走遍所有平台。Windows、macOS、Linux 不再各玩一套,命令和参数保持一致。
默认不要管理员权限。SDK、运行时、元数据全塞在用户目录,不碰系统目录,不需要 sudo。
多版本真正共存。正式版、预览版、每日构建可以同时装着,互不干扰。
按"意图"跟踪,不按版本号。你说"我要 .NET 10 的最新",它每个月 servicing 自动跟上;你说"我就要 10.0.3",它就钉死不动。
认 global.json。团队项目钉版本的机制继续有效,构建结果仍然可预期。
最后一条我觉得最要紧。以前用 dotnet-install.sh 也能装,但脚本装完就不管了,它不知道你机器上有几个 SDK,也不知道哪个项目在用哪一个。 dotnetup 是带账本的。
博客里那句反问写得挺实在。有人问:这些事我用 dotnet-install.sh 不也能干?官方回:能,大部分都能。但你少了四样东西——对已装 SDK 和运行时的管理、签名与校验和验证、批量安装多个 SDK 的速度、以及每个平台统一的命令入口。
三条命令,先装上
macOS(Zsh):
$ curl -fsSL https://aka.ms/dotnetup/get-dotnetup.sh | zsh
Linux(Bash):
$ curl -fsSL https://aka.ms/dotnetup/get-dotnetup.sh | bash
Windows(PowerShell):
> irm https://aka.ms/dotnetup/get-dotnetup.ps1 | iex
装完跑初始化:
> dotnetup init
Welcome to dotnetup!
SDK Channel: latest
Mode: Terminal Mode (Suggested)
Would you like to install
.NET with the recommended settings?
> Yes, proceed with defaults and install
Downloading SDK
Installing SDK
Installed SDK
它只问你两件事:装哪个 SDK 通道,以及你想怎么让终端找到托管的 dotnet。默认推荐的是 Terminal Mode,也就是把配置写进 shell profile。回车确认,它自己下载、安装,装完 dotnet --version 就能用。
想看一眼机器上现在是什么状况:
> dotnetup list
Installations (managed by dotnetup):
Tracked channels:
SDK latest (source: explicit)
Installed versions:
SDK ()
Total: 1
输出按安装根目录分组,列出跟踪的通道,还标了来源(比如 source: explicit)。哪个仓库在"续命"一个老 SDK,这里一眼就能看到。
global.json 从"文件"变成了"账本"
这是 dotnetup 和所有土办法真正拉开差距的地方。
在仓库目录里直接跑,后面不带通道:
> dotnetup sdk install
它会从当前目录往上找最近的 global.json,读里面的 version 和 rollForward,然后把 rollForward 翻译成一个"通道"来跟踪。找不到文件就用 latest。如果文件格式错了,命令直接失败,不会悄悄去用父目录那份。
官方给出来的映射表是这样的(以 10.0.103 为例):

意思很清楚:你写的是 10.0.103 加 latestPatch,它只装一个 10.0.1xx 的通道需求,以后这个功能带出了 10.0.108,它跟着走。rollForward 是 disable 那几类的,它就老实钉在 10.0.103,dotnetup update 也不会动它。顺便说一句,allowPrerelease 不影响它派生的通道。
还有一个我觉得特别实用的参数:
> dotnetup sdk install --update-global-json
图片
它在派生通道里装最新的 SDK,然后把新版本号写回 global.json。关键是只改 sdk.version 这一行,原有格式、其他属性、连文件编码都保留。你仓库里那份排得整整齐齐的 JSON 不会被搞乱。
以后想一次性把所有跟踪的仓库都升上去:
> dotnetup sdk update --update-global-json
老实说,这玩意儿能替掉不少"每个补丁星期二手动改版本号"的活。
每月更新、每日构建,都归它管
日常维护就一条:
> dotnetup update
它把所有跟踪的 SDK 和运行时通道重新解析一遍,装最新匹配版本。更新完还会自动做一次垃圾回收,把没有任何需求再引用的旧组件删掉。另一个通道或者精确版本还在用的,会留着。
图片再细一点,可以只动 SDK,或者只动运行时:
# 只更新 SDK
> dotnetup sdk update
# 只更新运行时(含 ASP.NET Core,Windows 上还有桌面运行时)
> dotnetup runtime update
# 只装某个运行时,比如 .NET 10 的 ASP.NET Core
> dotnetup runtime install aspnetcore@10.0
至于预览版和每日构建,这次是当一等公民处理的。以前想验一个 bug 修没修,得去 GitHub 翻原始 tar 包,手动解压到某个目录,再改环境变量。
现在:
图片> dotnetup sdk install preview
> dotnetup runtime install daily
> dotnetup sdk install daily
# dotnetup 自己也能更新
> dotnetup self update
装完不想要,卸掉就完了,不用再去系统目录里翻残留。
现在别急着全量切换
公共预览就是公共预览。官方文档第一句就写着"功能和行为可能会更改",正式版的支持生命周期也还没定。我把文档和几篇上手记录对着看了一遍,有几个地方是真的会踩:
Windows 上的 everywhere 模式要小心。init 在 Windows 会推荐它,这个模式会改系统 PATH 和 DOTNET_ROOT。改完之后,dotnetup 托管的安装会优先于 Visual Studio 装的那套 SDK。如果你有项目依赖 VS 里的机器级 SDK,而 dotnetup 又没装同一个版本,build 就直接挂了。
想试水,先选 shell 或者 none。
none 模式最有意思,它完全不碰 PATH 和 DOTNET_ROOT,改成命令转发,退出成本几乎为零:
> dotnetup env set none --dotnetup-on-path true> dotnetup dotnet build
另外三个坑,也一并记下来:
global.json 里写了 sdk.paths 的话,预览版会把第一个条目当路径用,但不认识 $host$ 这个占位符,也不会跳过空条目。要么别写 sdk.paths,要么显式加 --install-path。
卸载命令的范围比想象中大。dotnetup sdk uninstall 10.0.1xx --source globaljson 删的是安装根目录下所有匹配的 global.json 需求,不只是你当前这个仓库。别手滑。
系统级安装还没支持。现在只管用户目录。CI 里跑没问题,不需要 root,也能非交互执行;但 GitHub Actions 和 Azure DevOps 的一等公民集成还在路线图上。另外,Windows 上的系统级安装管理,官方说后续版本会补。
谁该用,谁可以先等等
如果你只在一台 Windows 机器上写一个项目,Visual Studio 装完就够用,dotnetup 现在对你意义不大。
但下面任意一条中了,值得花十分钟试:
— 手上同时维护好几个钉在不同 .NET 大版本上的仓库
— 经常要在本地跑 preview 或者每日构建验证问题
— 在 Linux 容器或者 CI 里动态装 SDK
— 给新同事配环境时,不想再写一篇"装 .NET 踩坑指南"
最后一条是我最看重的。工具链这种东西,价值不在于它本身多能打,而在于它能把"环境问题"从每天的对话里删掉。
官方文档在 learn.microsoft.com/dotnet/core/tools/dotnetup,走 aka.ms/dotnetup/docs 也能到。反馈去 dotnet/sdk 仓库的 discussions,里头有个专门的 dotnetup 分类。
顺带说一句,路标里还提到要给 AI 助手补 agent skills,让自动化工具默认就会伸手拿 dotnetup。这个方向挺对的。现在让 AI 帮你配环境,最容易翻车的恰恰就是装 SDK 这一步。
一句话收尾:dotnetup 解决的不是"能不能装"的问题,是"装了以后谁来管"的问题。
资料来源:.NET 官方博客(2026-10-15,作者 Chet Husk)、Microsoft Learn dotnetup 文档(dotnetup 公共预览版)。预览版功能可能变更,以官方文档为准。
作者声明本文无利益相关,欢迎值友理性交流,和谐讨论~

