最近一次我在一台刚装好Ubuntu 24.04 LTS的工作机上部署.NET 10开发环境前前后后折腾了小半天踩了几个不折腾根本遇不到的坑。这篇就是我整个安装过程的实操日志从环境准备、apt源替换、SDK安装、验证运行到VS Code集成、NuGet源配置、排障记录全部照实记录。如果你是刚把系统升级到24.04、或者正打算在这版系统上安装dotnet并开始写C#的项目这篇内容可以直接照着操作连我踩过的坑都帮你标好了。先说结论Ubuntu 24.04上装dotnet 10本身不复杂麻烦的是安装之前的环境清理、安装之后的路径配置以及几个看起来莫名其妙、实际上有明确原因的报错。这篇日志会把每一步命令、每一个坑、每一次排查的过程都写清楚力求你照着走一遍就能顺利跑起来。1. 为什么这次选择在24.04上装dotnet 101.1 系统版本确认与基础状态检查动手之前先确认系统版本这一步千万别省。我之前见过有人在22.04上照着24.04的教程操作结果apt源、依赖包全部对不上白折腾一个多小时。lsb_release -a输出里确认是Ubuntu 24.04.2 LTS或者24.04.x代号noble。内核版本可以用uname -a看一眼一般5.15以上都没问题dotnet不挑内核版本但和部分显卡驱动、容器运行时有关联顺手记录一下没坏处。接着检查架构。x86_64就写amd64ARM架构的机器比如树莓派5、部分国产开发板需要下载arm64版本后续注册apt源和下载SDK时架构名不能搞错。arch然后快速看一下磁盘空间。dotnet SDK完整装下来大概占用2GB到3GB加上NuGet缓存、全局工具、模板文件建议预留10GB以上空间。我用df -h /查看根分区确认还有60多GB空闲才放心往下走。1.2 dotnet 10值得升级的理由说实话如果你的生产环境还在用.NET 6或.NET 8不一定要急着升.NET 10。但在新装系统上直接上最新长期支持版本是合理选择。.NET 10最大的变化集中在三个方面性能进一步提升JIT编译优化、垃圾回收调整对高并发服务端程序友好。AOT发布更成熟不需要运行时环境也能跑原生二进制部署体积和启动速度都非常可观。C#语言新特性集合表达式、partial属性、扩展成员预览等写起来更简洁。由于24.04是当前最活跃的LTS版本很多开发工具链比如GitLab 19、新版Docker镜像、VSCode 1.9x以上版本都已经把默认支持基线提升到24.04。系统层面你绕不开它那开发环境直接架上.NET 10是比较省事的组合。1.3 安装方式选型apt源、snap还是手动解压在Ubuntu上装dotnet主要有三条路官方apt源、snap包、手动解压二进制包。我直接说结论推荐apt源方式次级推荐手动解压snap方式我有过不愉快的经历下面解释原因。安装方式优点缺点适合场景apt源依赖管理自动、版本更新可感知需要注册Microsoft仓库大多数人的首选snap包隔离干净、自动更新首次运行慢、路径特殊、与VS Code snap版易冲突临时体验、容器内测试手动解压tar.gz完全可控、可在用户目录安装需要自己配PATH、更新全手动无root权限的服务器环境snap版本会在/snap/dotnet/下创建沙箱环境运行时通过挂载方式映射到/usr/lib/dotnet看着方便但如果你再用snap方式装VS Code终端里执行dotnet命令时经常出现PATH识别不到的情况因为两个snap互相看不到对方的挂载目录。这个坑我在第4节详细说。所以我最后选了注册Microsoft官方apt源的方式把dotnet包和系统包管理统一在一起依赖问题自动解决。2. 安装前的系统准备与apt源配置2.1 先做系统更新顺手替换apt源我的习惯是先不急着加dotnet源先把系统自身更新到最新状态。这一步除了常规的apt update和apt upgrade还要处理一个国内用户经常遇到的老大难默认官方源速度慢。如果你在海外服务器或网络无障碍环境下官方源没问题。但我在国内的机器上实测过直接从archive.ubuntu.com拉取更新包经常只有几十KB/s换镜像源后能跑到几MB/s。替换源的方法不复杂先备份sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak24.04的apt源格式和旧版不一样现在是DEB822格式路径在/etc/apt/sources.list.d/ubuntu.sources不再是sources.list单文件。用sed直接替换镜像域名sudo sed -i s|http://archive.ubuntu.com|http://mirrors.aliyun.com|g /etc/apt/sources.list.d/ubuntu.sources sudo sed -i s|http://security.ubuntu.com|http://mirrors.aliyun.com|g /etc/apt/sources.list.d/ubuntu.sources我用的是阿里云镜像源实测速度和稳定性都不错。如果你在南方省份腾讯云和华为云的镜像源也可以选一个距离近的就行。替换完执行sudo apt update sudo apt upgrade -y等它跑完重启一遍让新内核和库文件生效。这里提醒一下升级完系统后内核可能变化重启能避免后续装dotnet依赖时遇到内核模块不匹配的问题。2.2 安装基础依赖包虽然dotnet SDK自带大部分依赖但有几个包在24.04的最小化安装里默认没有直接装SDK时会补装不过我习惯提前装好避免中途出现奇怪的问题。sudo apt install -y wget curl ca-certificates apt-transport-https gnupg这几个包的作用分别是wget和curl用来下载注册脚本和测试网络ca-certificates是HTTPS证书信任链的必备组件apt-transport-https确保apt能通过HTTPS访问源gnupg用来导入微软的GPG签名密钥。没有装apt-transport-https的话后续添加Microsoft源会报错 Unable to locate package因为apt不认识https协议头。这是很常见的一个坑提前装上就能避开。2.3 检查网络连通性这一步看似多余但实际安装时网络问题是最容易让人误判的。我用来检查的几条命令curl -I https://packages.microsoft.com curl -I https://dotnet.microsoft.comcurl -I只请求头信息不下载实际内容速度快。看到HTTP/2 200就是通的如果超时或返回403先查DNS解析和防火墙规则再排查其他问题。另外NuGet官网https://api.nuget.org/v3/index.json也建议测一下SDK安装完之后创建项目需要从NuGet拉包这一条不通的话后面照样卡住。3. dotnet 10 SDK安装完整过程3.1 注册Microsoft软件源到了核心环节。dotnet官方推荐的方式是通过Microsoft的Linux软件仓库分发这样能保证和apt包管理深度集成。执行如下命令wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb下载的deb包主要做两件事把Microsoft的GPG公钥写入系统信任链同时生成/etc/apt/sources.list.d/microsoft-prod.list源文件。装完之后执行apt update刷新源列表此时应该能看到microsoft-prod源里的dotnet相关包。如果执行apt update时报GPG错误原因是钥匙过期或未导入成功重新导入即可curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg然后检查/etc/apt/sources.list.d/microsoft-prod.list里的源指向是否正确我见过部分情况下源文件路径指向了旧的noble代号手动改成正确的即可。3.2 安装dotnet SDK 10源注册好之后安装命令一条就够sudo apt install -y dotnet-sdk-10.0如果只需要运行时比如只跑别人编译好的程序可以只装dotnet-runtime-10.0但大多数开发场景建议直接上SDKSDK里包含运行时还能使用dotnet new、dotnet build等命令。安装过程中apt会解析依赖自动装上一些基础运行库比如libicu、libssl、libgssapi等这些是dotnet运行时在Linux上工作的必要组件不用手动干预。如果你还需要同时保留.NET 8很多旧项目还在用可以并行安装sudo apt install -y dotnet-sdk-8.0多个版本SDK共存没有任何冲突它们各自安装在自己的目录下通过global.json或dotnet --list-sdks管理版本选择。安装完成先跑一下版本验证dotnet --version dotnet --list-sdks我这边输出的是10.0.x同时能看到系统里所有已经安装的SDK版本。如果dotnet命令提示找不到大概率是PATH问题我下面单独说。3.3 PATH配置与权限细节apt方式安装的dotnet默认路径是/usr/lib/dotnet/安装器会自动把/usr/bin/dotnet软链接指过去正常情况下不需要手动配PATH。但如果你遇到command not found检查这几处which dotnet ls -la /usr/bin/dotnet ls -la /usr/lib/dotnet/dotnet如果软链接丢失手动重建sudo ln -s /usr/lib/dotnet/dotnet /usr/bin/dotnet另外如果你用的是zsh需要在~/.zshrc里确认PATH包含/usr/lib/dotnet。我在测试时发现有些环境变量在bash里正常切到zsh后失效原因是zsh启动时读取的是~/.zshrc而不是~/.bashrc。还有一个权限细节dotnet首次运行会创建~/.dotnet缓存目录如果当前用户home目录的权限有问题或者之前用sudo高速缓存过root用户文件会导致普通用户执行dotnet时Permission denied。排查方法ls -la ~/.dotnet sudo chown -R $USER:$USER ~/.dotnet3.4 创建第一个项目并运行安装是否真的成功跑一个最小项目看效果最实在。我习惯用web API模板做验证因为ASP.NET Core涉及依赖注入、配置、Kestrel等核心组件能跑起来说明环境基本没问题dotnet new webapi -n HelloDotnet cd HelloDotnet dotnet run第一次执行dotnet run会触发NuGet还原耗时取决于网络状况我在替换过NuGet源之后大约用了40秒左右。看到输出里有Now listening on: http://localhost:5xxx就算成功了。浏览器访问该地址能看到返回的JSON响应。如果测试机器没有桌面环境用curl http://localhost:5xxx验证也可以。新项目跑通之后建议顺手做一次发布测试确认完整的构建链路没有缺失dotnet publish -c Release发布目录下会生成可执行文件和DLL这一步通过说明SDK组件完整可以放心进入日常开发。4. 开发环境集成与日常使用细节4.1 VS Code的snap版和dotnet命令的兼容问题开发C#离不开编辑器我在24.04上最常用的组合是VS Code C# Dev Kit插件。但这里有个非常隐蔽的坑如果你通过snap安装VS Codesudo snap install code --classic那么VS Code内置终端里执行dotnet命令会有概率报command not found。原因是snap应用运行在受限环境中默认只暴露部分系统路径/usr/lib/dotnet未必在snap的PATH映射里。排查方法很简单在VS Code的终端里执行echo $PATH如果发现没有/usr/lib/dotnet就是这个问题。解决方式有两种在VS Code的settings.json里给终端设置PATHterminal.integrated.env.linux: { PATH: /usr/lib/dotnet:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin }直接在~/.bashrc末尾追加一行export PATH$PATH:/usr/lib/dotnet我个人推荐第一种因为只影响VS Code终端不至于污染全局环境。这类坑调起来很恼人因为命令行单独执行dotnet是正常的一旦在编辑器里就不行特别容易让人误判成插件问题。4.2 NuGet包源配置国内网络环境下必做由于NuGet官方源api.nuget.org的服务器基本都在海外国内直连的时候经常出现超时、还原失败的情况。解决办法是把NuGet源切换/增加为国内可信镜像。NuGet的配置文件分用户级和项目级用户级配置在~/.nuget/NuGet/NuGet.Config。我的做法是直接把镜像源加到用户级配置里这样所有项目都能生效dotnet nuget add source https://mirrors.aliyun.com/nuget/v3/index.json -n AliyunMirror dotnet nuget add source https://mirrors.cloud.tencent.com/nuget/ -n TencentMirror添加完之后可以通过dotnet nuget list source查看当前所有源。注意多个源同时存在可以提升一些私有包的可用性但也可能造成版本选择不一致如果你对包来源有严格要求可以把官方源暂时禁用在急用时单独开启dotnet nuget disable source nuget.org配置完镜像源之后之前遇到的还原超时问题基本消失。我在测试中执行dotnet restore的速度提升了至少5倍。4.3 中文语言环境与文件编码的潜在干扰这个话题我在日志里专门记了一笔因为现象太迷惑。24.04有一个被广泛讨论的中文环境相关异常部分中文语言包或中文输入法组件会导致终端输出乱码、文件路径里中文名显示异常甚至在个别系统版本下dotnet build的输出文本编码判断错误。我的系统是英文locale只装了中文输入法所以没遇到严重问题。但如果你的系统安装时选择了中文语言环境建议先检查locale确保LANG是zh_CN.UTF-8或en_US.UTF-8这样的合理值如果显示C或POSIXdotnet的日志输出、NuGet错误信息全都会变成乱码。解决方式是手动生成localesudo apt install -y locales sudo locale-gen en_US.UTF-8 zh_CN.UTF-8 sudo update-locale LANGen_US.UTF-8至于和代码本身相关的中文编码问题在.csproj文件里设置InvariantGlobalizationfalse/InvariantGlobalization可以保证国际化的代码按预期运行不过一般默认值就够用不需要额外配置。4.4 AOT发布与单文件部署尝试dotnet 10的AOT发布比之前版本稳定很多依赖项处理更漂亮本来编译原生二进制时经常出现的剪裁警告也减少了。我实际测试了一个简单的控制台程序dotnet publish -c Release -r linux-x64 --self-contained -p:PublishAottrue命令执行时间大约50秒生成的原生二进制大小约12MB直接扔到一个没有dotnet运行时和依赖库的干净容器里也能跑起来。单文件发布非AOT也很方便dotnet publish -c Release -r linux-x64 --self-contained -p:PublishSingleFiletrue这两种方式各有适用场景AOT启动极快、内存占用低适合云函数、边缘设备单文件发布对第三方库兼容性更好适合交付给用户直接运行。建议两个都试一遍感受一下差异。5. 实际排障记录安装过程中遇到的三次报错5.1 现象一Unable to locate package dotnet-sdk-10.0这个报错出现在我执行sudo apt install dotnet-sdk-10.0的时候当时愣了一下因为注册源的步骤明明执行成功了。排查过程如下执行apt-cache search dotnet发现输出里只有dotnet-sdk-8.0没有10.检查/etc/apt/sources.list.d/microsoft-prod.list发现源文件里的Ubuntu版本代号是jammy22.04而不是noble.回看注册deb包的命令确认使用的配置包是config/ubuntu/24.04/packages-microsoft-prod.deb.问题根源很简单我在下载deb包时用了旧的URL缓存虽然没有报错但装进去的是22.04的源配置。删除错误源文件重新用24.04的包注册apt update之后就能搜到dotnet-sdk-10.0了。提示如果使用旧版系统迁移过来的源文件务必检查源文件里的代号jammy和noble的包版本差异很大混用会带来依赖冲突。5.2 现象二No such file or directory 的DLL加载错误第一次安装完成后执行dotnet --info能打印版本信息但创建完项目执行dotnet build时抛出一个特别奇怪的错误A fatal error occurred. The folder [/usr/share/dotnet/host/fxr/10.0.x] does not exist报错路径是/usr/share/dotnet但我安装的dotnet明明在/usr/lib/dotnet。排查了半天发现是shell别名或软链接指向混乱造成的。之前系统里装过其他版本的dotnet残留了/usr/share/dotnet软链接。删除旧的软链接重建/usr/bin/dotnet指向sudo rm -rf /usr/share/dotnet /usr/bin/dotnet sudo ln -s /usr/lib/dotnet/dotnet /usr/bin/dotnet这个问题在反复折腾过多版本SDK的机器上经常出现新手可能遇不到但如果你是从旧环境升级上来的留意一下这个路径。5.3 现象三NuGet还原时连接超时我在第4节提过NuGet源配置那次超时问题是在刚装完SDK创建项目时遇到的。当时执行dotnet new webapi能正常创建模板但dotnet restore一直卡在连接api.nuget.org。确认问题后我没有选择反复重试而是直接增加国内镜像源dotnet nuget add source https://mirrors.aliyun.com/nuget/v3/index.json -n Aliyun dotnet nuget remove source nuget.org然后又顺手清理了一次NuGet缓存dotnet nuget locals all --clear重新restore瞬间成功。这个操作看起来简单但要提醒一点清理缓存会把已经下载的包全部删除下次还原要重新下载。如果不是缓存损坏尽量不要每次都用all --clear。5.4 额外记录无法加载libhostfxr.so这个坑是在一台内存很小的2GB机器上遇到的表现是任何dotnet命令都报The library libhostfxr.so was not found原因很直接内存不足安装过程中部分文件没有正确解压完成或者文件系统写入异常。解决方法是确认/usr/lib/dotnet/host/fxr/目录下文件是否完整如果缺失就直接重新安装SDK包sudo apt install --reinstall dotnet-sdk-10.0另外在低内存环境下可以考虑设置DOTNET_gcServer0来减少垃圾回收器的内存占用这个变量对2GB内存机器上的启动稳定性有帮助。6. 写给同样在折腾的人的一些提醒6.1 安装检查单照着过一遍更稳妥折腾完这一趟我把整个流程整理成了检查单下次在新机器上装dotnet就直接过这一遍确认系统版本为Ubuntu 24.04.x架构为amd64或arm64。替换apt源为本地镜像执行apt update apt upgrade -y。安装基础依赖wget、curl、ca-certificates、apt-transport-https、gnupg。用24.04专用deb包注册Microsoft源验证源文件里的代号是noble。apt install dotnet-sdk-10.0同时确认需要的其他SDK版本。执行dotnet --info和dotnet --list-sdks验证安装。创建临时项目跑通dotnet run和dotnet publish。配置NuGet国内镜像源必要时清理缓存。在VS Code或JetBrains Rider里测试终端PATH集成。每一步时间都不长加起来5分钟能做完全部验证。千万别跳过第7步我见过太多人装完SDK不测试就关终端第二天写代码时才发现问题。6.2 最后想强调的几件事根据这次实际安装的经验有几个观点想专门拿出来说第一apt源方式优于手动解压和snap。不要以为手动解压自由度更高等到系统库升级后dotnet跑不起来你会发现包管理器的依赖处理能力才是最省心的。第二国内环境下系统源和NuGet源一定要提前配置。装SDK不换源最多慢一点等创建项目时反复超时那才叫折磨。一次配好后面所有项目都受益。第三多版本SDK共存完全没必要焦虑。dotnet的SDK选择机制做得很好项目里的global.json或.csproj的目标框架能精确控制使用哪个版本旧项目的兼容性不会因为系统里装了新版SDK而受影响。第四遇到奇怪的报错先看路径。我这次排障的三个问题两个都出在路径上。/usr/lib/dotnet、/usr/share/dotnet、/usr/bin/dotnet这几个地方只要有一个指向错了整个环境就像中了邪一样。养成用which dotnet和dotnet --info验证的习惯能省掉大量排查时间。第五如果你和我一样长期需要在Linux下写C#建议抽空把AOT发布、单文件发布、global tool安装这几个场景都试一遍。这些不是高频操作但真到部署阶段时每一个都能救命。这篇日志写到这里我的Ubuntu 24.04开发机已经在稳定运行dotnet 10环境了希望你也能顺利装完少走这些弯路。
