NixOS 配置回滚完全指南:从 GRUB 启动菜单到 `nixos-rebuild --rollback`

发布时间:2026/9/21 18:49:25
NixOS 配置回滚完全指南:从 GRUB 启动菜单到 `nixos-rebuild --rollback` 包管理器操作系统【免费下载链接】nixpkgsNix Packages collection NixOS项目地址https://gitcode.com/GitHub_Trending/ni/nixpkgs点击查看免费下载导读在 NixOS 中执行nixos-rebuild switch切换到新配置后如果新配置表现不佳服务起不来、桌面进不去、内核不兼容等你并不需要手动修复系统——NixOS 的每次配置切换都会以 generation代际的形式留存历史快照回滚到任意一个旧配置只是几步命令的事。本文基于 NixOS 官方手册 rollback.section.md 展开结合 nixpkgs 仓库中 GRUB 引导器生成逻辑、switch-to-configuration激活脚本等源码实现系统讲解两条回滚路径通过引导菜单在重启时回到旧配置以及在运行中的系统里直接切换回上一个配置。读完本文你将能熟练使用nixos-rebuild switch --rollback、手动调用switch-to-configuration并理解回滚背后的 generation、profile 与垃圾回收机制。一、为什么 NixOS 能一键回滚不可变存储与 generation要理解回滚先要理解 NixOS 的一个基本事实每次nixos-rebuild都会构建出一个全新的、内容寻址的 store 路径如/nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055旧配置的路径不会被覆盖只要没有被垃圾回收garbage-collect它就始终存在于 Nix store 中。每个已部署的配置会作为/nix/var/nix/profiles/system这一 profile 的一个 generation 被记录下来通过形如system-N-link的符号链接指回对应的 store 路径。这也是官方手册中用来枚举可用配置的命令$ ls -l /nix/var/nix/profiles/system-*-link ... lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link - /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055这里N如 268是系统配置的代际编号编号越大表示越新。需要强调的是回滚的前提是旧配置还没有被垃圾回收。官方文档也明确指出GRUB 引导菜单只能列出hasnt been garbage-collected的配置清理旧配置的方法可参考 cleaning-store.chapter.md其中同样确认了NixOS system configurations are stored in the profile/nix/var/nix/profiles/system。二、方式一从 GRUB 引导菜单回滚适合系统无法启动的情况如果新配置严重到无法正常启动例如内核或 initrd 出问题这是唯一的回滚途径。2.1 操作步骤重启机器进入 GRUB 引导菜单。打开子菜单NixOS - All configurations这里列出了所有尚未被垃圾回收的历史配置。选择要回退到的那一代配置条目通常会附带日期与版本信息形如NixOS - Configuration 268 (2026-09-20 - 25.05...)。正常启动进入该系统。2.2 启动后把它设为默认配置从旧配置启动后当前运行中的系统路径/run/current-system已经是该旧配置。但为了让后续重启也默认进入这一配置而不只是本次引导需要执行# /run/current-system/bin/switch-to-configuration bootboot这个动作的含义是把当前配置设为下次启动的默认项但不立即切换运行状态。从 nixpkgs 仓库的源码 what-happens-during-a-system-switch.chapter.md 可以确认switch-to-configuration支持switch、test、boot等动作其中如果动作是switch或boot会先更新引导器使该配置成为下一次启动的配置。也就是说用boot动作更新的是引导器层用switch动作则还会在运行中完成单位切换与激活。2.3 底层原理GRUB 子菜单是怎么生成的All configurations 子菜单并非 GRUB 自动识别而是 NixOS 在每次构建引导器配置时由 install-grub.pl 中的addProfile子程序见 install-grub.pl#L575-L612生成的。其核心逻辑# Emit submenus for all system profiles. sub addProfile { my ($profile, $description) _; # Add entries for all generations of this profile. $conf . submenu \$description\ --class submenu {\n; sub nrFromGen { my ($x) _; $x ~ /\/\w-(\d)-link/; return $1; } my links sort { nrFromGen($b) nrFromGen($a) } (glob $profile-*-link); ... } addProfile /nix/var/nix/profiles/system, distroName - All configurations;这段代码清晰地展示了子菜单的构成方式通过glob $profile-*-link扫描/nix/var/nix/profiles/system-*-link形式的所有代际链接用正则\/\w-(\d)-link提取代际编号并按编号从大到小排序最新的排在最前对每个链接读取nixos-version文件得到版本用链接的 mtime 得到日期拼成菜单条目distroName - Configuration N (date - version)跳过损坏的条目缺少nixos-version文件时输出 skipping corrupt system profile entry 警告。因此你在引导菜单里看到的配置列表本质上就是/nix/var/nix/profiles/systemprofile 下所有现存 generation 的投影。引导器还额外支持system-profiles/目录下的其他 profile会生成distroName - Profile $name形式的子菜单。2.4 相关引导器配置项GRUBboot.loader.grub.configurationLimit控制引导菜单中最多保留多少条配置默认值为100见 grub.nix#L634-L642原因是GRUB has problems when there are too many entries条目过多时 GRUB 会出现问题。install-grub.pl中last if $curEntry $configurationLimit;正是这一限制的实现点。systemd-boot对应选项为boot.loader.systemd-boot.configurationLimit默认值为null不限制只要没被垃圾回收就全部列出并注释指出限制数量有助于防止引导分区磁盘耗尽见 systemd-boot.nix#L234-L245。三、方式二在运行中的系统里切换回上一个配置如果新配置能够启动只是运行效果不理想可以在不重启的情况下直接回滚# nixos-rebuild switch --rollback该命令等效于手动调用上一个系统配置里的激活脚本进行switch动作# /nix/var/nix/profiles/system-N-link/bin/switch-to-configuration switch其中N是上一个配置的代际编号。两者的差别在于nixos-rebuild switch --rollback会帮你解析当前 profile 指向上一个 generation而手动方式需要你自行确定N可用上文的ls -l /nix/var/nix/profiles/system-*-link查看。执行后当前运行环境会切换到旧配置profile 符号链接也会随之更新指向该旧 generation从而保证后续重启默认进入的是这个已回滚的配置。四、深入理解switch-to-configuration回滚动作的底层实现switch-to-configuration是回滚链路中的关键程序它位于每个系统 store 路径的$out/bin/switch-to-configuration。从源码看当前 nixpkgs 中该程序已经统一为switch-to-configuration-ngRust 实现switchable-system.nix 中通过ln -sf ${lib.getExe pkgs.switch-to-configuration-ng} $out/bin/switch-to-configuration建立链接且注释明确说明the new switch-to-configuration-ng, which is now the only switch-to-configuration implementation。其项目说明见 switch-to-configuration-ng/README.md。它的工作方式对理解回滚行为很有帮助以当前正在运行的配置/run/current-system为起点计算向目标配置迁移所需的动作序列迁移计算综合两份数据源/etc/fstab挂载与交换分区变化和当前 systemd 状态单位启停差异动作按固定顺序执行先systemctl stop停止单位再运行激活脚本$out/activate随后按需daemon-reexec重启 systemd、daemon-reload、重启 sysinit、reload/restart/start相应单位最后输出失败或新启动的单位列表。这些细节均出自 what-happens-during-a-system-switch.chapter.md它同时提到两个排障环境变量STC_DISPLAY_ALL_UNITS1默认会过滤部分单位输出和STC_DEBUG1输出更详细的调试信息。当你回滚后想确认到底启停了哪些单位、服务是否全部拉起时这两个变量很有用。五、回滚失败或系统异常时的补充手段进入救援模式如果回滚后的系统状态仍然异常例如关键服务未启动可执行systemctl rescue进入单用户救援 shell手动排障后再exit退出详见 maintenance-mode.section.md。启动问题定位在 GRUB 菜单中按e编辑启动项可在linux行追加内核参数如systemd.debug_shell、rescue来诊断启动失败原因详见 boot-problems.section.md。日常重启与关机回滚或排障过程中常用reboot等价于systemctl reboot与shutdown等价于systemctl poweroff见 rebooting.chapter.md。六、回滚与垃圾回收别让旧配置消失最后需要再次强调回滚能力与垃圾回收的耦合关系。nix-collect-garbage会清理未被引用的 store 路径而 generation 链接system-N-link正是对旧配置 store 路径的引用。如果你执行了类似nix-env --delete-generations old或针对系统 profile 的旧代际清理对应配置就会失去引用并被回收此后它既不会出现在 GRUB 的 All configurations 子菜单中--rollback也无法再回到那一代。所以对配置满意、确认稳定后再考虑清理旧代际以释放磁盘空间若担心升级风险可在升级前记录当前代际编号并保留最近几代不清理作为回滚保险。总结NixOS 的回滚能力建立在两个支柱之上一是 Nix store 的不可变性——旧配置路径不会被覆盖只要存在引用generation 链接就不会被回收二是引导器与激活脚本的协作——GRUB 的 All configurations 子菜单由 install-grub.pl 扫描system-N-link生成switch-to-configuration则负责在运行中完成单位迁移与激活。掌握nixos-rebuild switch --rollback与手动switch-to-configuration boot两条路径并结合configurationLimit与垃圾回收策略做好配置代际管理即可在面对任何一次失败升级时从容回到稳定状态。赞分享包管理器操作系统【免费下载链接】nixpkgsNix Packages collection NixOS项目地址https://gitcode.com/GitHub_Trending/ni/nixpkgs点击查看免费下载相关推荐VDO.Ninja高级功能WHIP/WHEP流媒体技术实战VDO.Ninja高级功能WHIP/WHEP流媒体技术实战 VDO.Ninja是一款强大的WebRTC工具可将远程视频源引入OBS或其他工作室软件。其中WH音视频直播即时通讯离线也能跑 Whisper V3 Turbo 语音识别sherpa-onnx 三分钟上手实录离线也能跑 Whisper V3 Turbo 语音识别sherpa onnx 三分钟上手实录 很多开发者第一次接触语音识别时都踩过同一个坑调云 API 太贵包管理器操作系统Otomi Core核心架构深度解析Istio、Argo CD与GitOps工作流Otomi Core核心架构深度解析Istio、Argo CD与GitOps工作流 Otomi Core作为Linode Kubernetes Engine的创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考