
.NET 10 正式版发布之后我手头几台 Ubuntu 机器终于可以放心升级开发环境了。前两天刚把主力工作机从 Ubuntu 22.04 升到 24.04第一件事就是把 .NET 10 SDK 装好。整个过程整体来说不算折腾但中间有几个细节确实值得单独记一笔——仓库地址、密钥格式、还有首次运行时的环境变量任何一个没处理对都可能让你卡在莫名其妙的地方。这篇文章就按时间线把我从零开始安装 dotnet 10 的完整过程记录下来包括选型思路、仓库接入、实际执行的命令、中途遇到的报错和排查方法以及最后在 VS Code 里跑通项目的验证路径。如果你也准备在 Ubuntu 24.04 上安装 .NET 10直接照着走就行。1. 为什么选 .NET 10以及安装方式选型的思路1.1 版本选型的几个考量先说为什么是 .NET 10 而不是继续留在 .NET 8。.NET 10 是 2025 年 11 月发布的 LTS 版本意味着它会获得三年的官方支持对生产环境来说这个时间窗口非常重要。我手上有几个 ASP.NET Core 项目今年要陆续重构既然要重新搭环境不如直接用最新的 LTS 版本省得明年又折腾一次升级。另一个原因是 Ubuntu 24.04 属于 .NET 10 官方支持的 Linux 发行版。微软对 .NET 的系统支持矩阵更新得很勤快Ubuntu 24.04代号 Noble Numbat从很早就被列入了支持范围这意味着依赖库的兼容性测试基本都做过了不像之前在某些激进版本上那样需要自己动手解决 libicu 和 OpenSSL 的兼容问题。1.2 三种安装方式对比apt 源、snap、手动解压在 Linux 上装 .NET SDK选来选去其实就是三条路微软官方 apt 仓库、snap 包、还有手动解压 tar.gz。三条路我都试过各有各的适用场景。安装方式优势短板适合场景微软官方 apt 源自动处理依赖和系统更新整合在一起需要手动接入仓库和密钥日常开发主力环境snap安装简单自动沙箱隔离文件路径特殊部分工具链会有权限问题只想快速跑一个 demo手动解压 tar.gz完全可控适合离线环境依赖要自己补齐PATH 要自己配服务器、CI/CD 镜像这次我选的是官方 apt 源。原因很简单日常开发机器上我希望 SDK 能跟随系统一起更新而且 apt 会自动处理 libicu、openssl 这些底层库的版本冲突省心很多。1.3 为什么最终走在官方源路线有一个容易被忽略的点snap 版 .NET 在很多场景下会和 VS Code 的 C# Dev Kit 扩展产生路径解析问题因为 snap 把可执行文件封装在 /snap/dotnet-sdk/ 目录下面而 dotnet 命令在解析 DOTNET_ROOT 的时候经常拿不到真实路径。我之前在一台测试机上踩过这个坑后来直接把 snap 卸了换成官方源。如果你以后遇到C# 扩展找不到 SDK这类问题优先检查是不是 snap 安装导致的。手动解压的方式我也用过适合无外网环境或者需要同时维护多个 SDK 版本的场景。但日常开发尤其你是第一次在 Ubuntu 上搭 .NET 环境的话我还是推荐先走官方源等熟悉了整个目录结构之后再按需手动管理也不迟。2. 装之前的准备仓库接入、密钥、依赖一个都不能少2.1 先确认系统版本和架构动手之前先把系统底细摸清楚。不同 Ubuntu 版本的仓库地址不一样写错了 apt 更新的时候会直接 404。我用这几条命令确认环境lsb_release -a uname -m我的机器输出是 Distributor ID: UbuntuDescription: Ubuntu 24.04.2 LTS架构是 x86_64。注意这里有一个关键点Ubuntu 24.04 的仓库路径里用的是noble代号如果你复制了旧教程里的jammy、focal后面 apt update 一定会报错。这个细节非常容易忽略我见过不少人在这一步翻车。2.2 安装基础依赖接下来把安装过程需要的几个工具装好。虽然 Ubuntu 桌面版默认带了 curl但有些精简安装的服务器版本没有最好还是确认一下sudo apt update sudo apt install -y curl ca-certificates software-properties-commonca-certificates这个包尤其重要它负责 SSL 证书的校验。如果你发现后面 curl 拉取密钥时报证书错误多半就是系统缺了这个包。2.3 添加 Microsoft 签名密钥微软的 apt 仓库用的是自有签名密钥需要先把它导入系统。这里要注意密钥文件的存放位置。老教程喜欢直接把密钥放到 /etc/apt/trusted.gpg.d/ 目录下但新版 apt 对这个目录的密钥格式管得越来越严最稳妥的做法是用gpg --dearmor转换成二进制格式放到 /usr/share/keyrings/ 下面curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg执行完可以检查一下文件是否存在并且确认它是二进制格式而不是 ASCII 文本file /usr/share/keyrings/microsoft-prod.gpg正常输出应该包含PGP public key block字样。如果你看到的是ASCII text说明 dearmor 步骤没生效后续 apt 会报Key is stored in legacy trusted.gpg keyring之类的警告。2.4 写入官方仓库源写入仓库源这一步是整个安装过程中最容易出错的环节。网上能找到很多旧命令直接用deb [archamd64] https://packages.microsoft.com/repos/microsoft-ubuntu-noble-prod noble main写到 /etc/apt/sources.list.d/microsoft.list。这种方式在 24.04 上还能用但更规范的做法是显式指定signed-by参数让 apt 明确知道密钥在什么地方避免后续更新时出现密钥不匹配的警告echo deb [archamd64,arm64,armhf signed-by/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/repos/microsoft-ubuntu-noble-prod noble main | sudo tee /etc/apt/sources.list.d/microsoft.list这里再提醒一句如果你用的是 Ubuntu 24.04 的 ARM 版本比如树莓派 5 或某些 ARM 开发板把arch后面的内容对应改成arm64就行仓库本身同时支持 amd64、arm64 和 armhf。2.5 更新索引时可能出现的两个小问题仓库写入之后跑sudo apt update可能会遇到两类问题我都实际碰到过。第一类是Certificate is not yet valid或者证书相关的报错。这个大概率是系统时间不对Ubuntu 的自动时间同步偶尔会失灵尤其你在虚拟机里装了快照恢复之后。解决办法是sudo apt install ntpdate sudo ntpdate ntp.ubuntu.com或者干脆进设置里面把自动时间同步重新打开。第二类是Key is stored in legacy trusted.gpg keyring警告。如果你之前用过旧版安装脚本密钥被导入了 /etc/apt/trusted.gpg.d/新 apt 会提示你把密钥迁移到 keyrings 目录。遇到这种就直接把旧的密钥文件删掉只保留 keyrings 目录下那份。不然会多一个“键盘输入密码”的烦人提示。3. 安装 dotnet 10 SDK 的完整过程与报错记录3.1 apt install 命令与预期输出仓库和密钥都就绪之后剩下的就很简单了。直接安装 SDK 包sudo apt update sudo apt install -y dotnet-sdk-10.0安装过程中 apt 会自动处理依赖。我这边装完系统额外拉了几个依赖包包括aspnetcore-runtime-10.0和dotnet-runtime-10.0。这是因为 SDK 包含完整运行时而 apt 的依赖解析器会自动补齐底层组件。如果只想安装运行时而不是完整 SDK可以单独安装dotnet-runtime-10.0或者aspnetcore-runtime-10.0体积会小不少。但日常开发我强烈建议直接装 SDK否则dotnet new、dotnet build这些命令都不可用等于残废。3.2 两个常见的 404 错误排查过程我在另一台机器上复现安装时遇到了 apt update 报 404 的问题。具体报错是Err:4 https://packages.microsoft.com/repos/microsoft-ubuntu-noble-prod noble InRelease 404 Not Found [IP: 13.107.213.33 443]这个报错出现的第一时间就该去检查仓库地址的代号。我用lsb_release -c确认了一下系统代号发现那台机器实际是 Ubuntu 23.10代号 mantic而我在源里写的是 noble那当然找不到对应目录。还有一个容易被忽略的情况如果你用 Docker 或者 LXD 容器宿主机是 22.04 但容器内是 24.04偶尔会出现 apt 缓存指向旧仓库的问题。这时候用sudo apt clean sudo apt update清理缓存重试即可。3.3 依赖冲突libicu 版本问题的修复正常安装过程一般不会遇到 libicu 冲突但如果你在系统里手动装过其他版本的 ICU 库或者用了第三方的 PPAapt install 时可能会提示类似The following packages have unmet dependencies: dotnet-sdk-10.0 : Depends: libicu72 ( 72.1~) but it is not installableUbuntu 24.04 自带的是 libicu74而 .NET 10 官方要求最低 libicu72。大部分情况下 apt 会帮你自动把 libicu72 从系统源里拉下来但如果你之前把系统源改成了某个精简镜像或者添加了删掉默认源的奇怪 PPA就会导致依赖解析失败。我的处理办法是把默认的 Ubuntu 源恢复回来注释掉那些乱七八糟的第三方源然后sudo apt update再重新安装 dotnet-sdk-10.0。这个依赖在官方源里是有的只要源没问题就能自动装上。3.4 安装完成后的目录布局装完顺手看一下文件结构这对后面排查问题非常有帮助ls -la /usr/share/dotnet/正常情况下能看到dotnet可执行文件还有sdk、shared、LICENSE.txt等目录。sdk下面就是具体的 SDK 版本号目录shared下面按运行时类型分了Microsoft.NETCore.App、AspNetCore.App和Microsoft.NETCore.App.Host.linux-x64等。如果你同时装了 .NET 8 和 .NET 10这两个版本会并列存在互不影响。我还习惯额外配置一个环境变量echo export DOTNET_ROOT/usr/share/dotnet ~/.bashrc echo export PATH$PATH:$DOTNET_ROOT ~/.bashrc source ~/.bashrc很多第三方工具比如 Omnisharp、C# Dev Kit 的旧版本都会读取 DOTNET_ROOT 来定位运行时。不设置这个变量虽然 dotnet 命令能用但偶尔会出现编辑器找不到运行时的情况。我在 Ubuntu 24.04 上实测过加上这个变量之后 VS Code 里的智能提示稳定了很多。4. 验证、首个项目与工具链配置4.1 dotnet --info 的输出解读安装完第一件事就是验证版本信息dotnet --info我这里的输出显示了Version: 10.0.x以及对应的Base Path: /usr/share/dotnet/sdk/10.0.x/。这里有个小技巧如果你同时装了多个版本的 SDK可以根据Base Path路径看出当前默认跑的是哪个版本。另外重点看一下Runtime Environment部分里面有OS Name: ubuntu、OS Version: 24.04、OS Platform: Linux、RID: ubuntu.24.04-x64。RID 输出正确说明运行时和系统的匹配没问题后面发布单文件时会依赖这个值。4.2 创建第一个控制台项目验证完 SDK 版本创建一个空项目跑一遍dotnet run确保整个链路的编译和运行都没问题mkdir -p ~/projects/hello cd ~/projects/hello dotnet new console -o HelloDotnet cd HelloDotnet dotnet run首次运行dotnet new时系统会初始化 NuGet 缓存、生成开发证书所以稍微慢一点是正常的几秒钟到十几秒不等。如果你觉得每次执行都打印一堆首次使用提示很烦可以写入环境变量关掉这些输出export DOTNET_CLI_TELEMETRY_OPTOUT1 export DOTNET_NOLOGO1把这两行也加到 ~/.bashrc 里之后 dotnet 命令的输出会干净很多。dotnet run成功之后控制台会打印Hello, World!。这说明编译器、运行时、项目模板全部正常。4.3 NuGet 源与 dotnet 工具的补充配置接下来是很多人容易忽略的 NuGet 源配置。默认情况下 NuGet 会访问 nuget.org如果你所在的网络访问这个源速度很慢包的还原过程会很痛苦。我习惯在用户级别配置文件里增加一个镜像源mkdir -p ~/.nuget/NuGet nano ~/.nuget/NuGet/NuGet.Config配置文件内容如下?xml version1.0 encodingutf-8? configuration packageSources add keynuget.org valuehttps://api.nuget.org/v3/index.json / /packageSources /configuration如果你所在网络访问 nuget.org 缓慢可以考虑在packageSources里增加本地的私有源或者可用镜像具体地址根据你自己的网络环境填写即可。这个配置文件的优先级逻辑是项目级配置优先于用户级配置用户级配置优先于机器级配置。常用全局工具的安装也是一个例行步骤。EF Core 的迁移工具是必须装的dotnet tool install --global dotnet-ef装完之后注意工具的可执行文件默认放在~/.dotnet/tools目录不在 PATH 里。需要手动加一下echo export PATH$PATH:$HOME/.dotnet/tools ~/.bashrc source ~/.bashrc否则你执行 dotnet-ef 会提示 command not found我至少在三四台机器上遇到过这个问题几乎每次都要花几分钟想起来。4.4 VS Code 与 C# 开发体验的快速整理Ubuntu 24.04 上我用 VS Code 配合 C# Dev Kit 做日常开发体验已经很接近 Windows 上的 Visual Studio 了。安装扩展时有两个注意点第一C# Dev Kit 扩展会要求你安装 .NET SDK它能自动检测到系统里的 dotnet 10。如果它没检测到先回终端跑一遍dotnet --version确认命令可用然后重启 VS Code。还是不行就检查上一章说过的 DOTNET_ROOT 环境变量。第二解决方案资源管理器里的“启动”按钮依赖项目的 launchSettings.json。用dotnet new console、dotnet new webapi模板创建的项目都自带这个文件不需要额外处理。如果打开旧项目没有启动配置可以在 .vscode/launch.json 里手动配置console类型的启动项。5. 使用一段时间之后的几点体会和需要留意的地方5.1 多版本共存与 SDK 切换的注意事项日常开发中不同项目可能锁定不同的 SDK 版本比如老项目还在用 .NET 8新项目已经用 .NET 10。两者共存完全没问题apt install dotnet-sdk-8.0和apt install dotnet-sdk-10.0可以同时存在默认命令跑的是最新版本。但有些老项目会通过 global.json 锁定 SDK 版本。这种情况下你需要为老项目生成一个 global.jsondotnet new globaljson --sdk-version 8.0.100注意如果你的系统里还装着 .NET 8 SDK这个文件才会生效。如果没有对应的 SDKdotnet 会提示你安装相应版本。5.2 从预览版升级到正式版时的注意点如果之前装的是 .NET 10 Preview 或者 RC 版本升级到正式版时最好先卸载旧版再装正式版sudo apt remove dotnet-sdk-10.0* sudo apt autoremove sudo apt install -y dotnet-sdk-10.0这样做的原因很简单预览版和正式版的包名、版本号在 apt 源里是并列的直接apt upgrade可能会残留旧版本目录。旧版本目录里的运行时和官方新版本混在一起偶尔会导致dotnet --list-runtimes输出多条相似记录实际倒不会出问题但排查问题时容易看花眼。如果你是用手动解压方式装的预览版升级流程更要注意把 /usr/share/dotnet 整个目录删掉再重新解压。千万不要覆盖式解压旧版本残留的共享框架文件可能和新版本不兼容到时候编译能过运行突然报 TypeLoadException追查起来很费劲。5.3 实际项目中的编译和发布表现装好之后我顺手把公司的一个 ASP.NET Core 项目拉下来做了一次完整验证。项目用的是 .NET 10 EF Core 10依赖大概二十来个 NuGet 包。第一次dotnet restore花了大约一分半后续再 restore 就快很多。编译一个中型项目大概几秒到十几秒相比之前在 Windows 上的体验Ubuntu 24.04 下的响应速度完全不输内存占用还更低。发布单文件的时候需要额外指定运行时标识符dotnet publish -c Release -r linux-x64 --self-contained true -o ./publish我分别测了 framework-dependent 和 self-contained 两种发布模式。在 Ubuntu 24.04 上如果没有特殊需求用 framework-dependent 就够了目标机器只要装了对应版本的运行时就能跑。如果目标是完全没有 .NET 环境的机器那再用 self-contained。5.4 最后的几点体会在整个安装和后续使用的过程中我最想强调的还是仓库地址和密钥的问题。Ubuntu 24.04 的代号是 noble这个代号对应错了后面所有步骤都会跟着出错。另外gpg --dearmor生成的文件路径、格式都要对apt 对密钥的管理比旧版严格得多不规范就会警告或者直接拒绝。这些细节在官方文档里其实都有写但分散在好几篇文章里实操的时候很容易漏。如果你之前用过旧版本的安装脚本建议花十分钟把旧的密钥和源清理干净再重新来一遍。干净的环境下装 dotnet 10正常情况下十五分钟之内就能搞定。装完之后顺手把 DOTNET_ROOT 和 dotnet tools 的 PATH 配置好VS Code 里的开发体验基本可以达到开箱即用的水平。