如何让 NixOS 显示一次更新的具体内容
当 NixOS 配置好了 flake、home-manager 等等,后续的更新我们只需要运行:
1❯ nix flake update
2
3❯ sudo nixos-rebuild switch
4building the system configuration...
5activating the configuration...
6setting up /etc...
7reloading user units for davinci42...
8restarting sysinit-reactivation.target
9the following new units were started: NetworkManager-dispatcher.service
10Done. The new configuration is /nix/store/mp17nhbadmffs9ah961ldj0y1l38a73m-nixos-system-azure-25.05.20250424.f771eb4
除了 kernel 的更新需要重启,某些环境变量需要新开 session 之外,其它 pkg 和对应的 systemd-service 应该都是最新的状态了。
但是上面的 log 中,我们是不知道这一次的 switch 具体更新了什么的。
如果 nixpkgs 和 home-manager 的 repo 有新的 commit 我们是可以知道 hash 更新,但是 2 次 commit 之间更新的 pkg 我们是不知道的。
有什么方式,能让我们看到更新前后 2 个 generation 的 diff 吗?
可以使用 nvd1 这个 pkg,它支持对 2 个 generation 做 diff,比如:
1❯ nvd diff /run/booted-system /run/current-system
2<<< /run/booted-system
3>>> /run/current-system
4No version or selection state changes.
5Closure size: 1144 -> 1144 (10 paths added, 10 paths removed, delta +0, disk usage +1.3KiB).
同样的方式,我们就可以对任意 generation 做 diff 了:
1❯ ls -al /nix/var/nix/profiles
2total 52
3drwxr-xr-x 3 root root 4096 Apr 27 20:54 .
4drwxr-xr-x 9 root root 4096 Apr 27 20:15 ..
5lrwxrwxrwx 1 root root 43 Apr 4 00:00 default -> /nix/var/nix/profiles/per-user/root/profile
6drwxr-xr-x 3 root root 4096 Apr 3 17:25 per-user
7lrwxrwxrwx 1 root root 15 Apr 27 20:54 system -> system-166-link
8lrwxrwxrwx 1 root root 85 Apr 27 20:53 system-165-link -> /nix/store/b66ijf8hscs19bz2d8ph6baxgn6p6ff7-nixos-system-azure-25.05.20250424.f771eb4
9lrwxrwxrwx 1 root root 85 Apr 27 20:54 system-166-link -> /nix/store/k57fs0isb02siaaj1vyvjfgsxz882jp1-nixos-system-azure-25.05.20250424.f771eb4
但是这样其实很不方便,我们并不想每次来到这个目录下,找到最后的 2 个 generation 来手动 diff。
正好每次 NixOS 更新也是 2 个单独的命令,写个脚本一起封装了吧:
1alias nfu="treefmt -q . && nix flake update"
2alias nrs="sudo nixos-rebuild switch"
3function ns() {
4 local curVer=$(realpath /run/current-system)
5 nfu && nrs && nvd diff $curVer $(realpath /run/current-system)
6}
- 记录 switch 之前的 system 对应的 generation
- 对 nixos config 目录下所有 .nix 文件做格式化
- 更新 flake
- rebuild switch
- nvd 做 diff
为什么要做临时变量记录 switch 之前的 path 呢?
因为我们永远可以通过 realpath /run/current-system
找到当前的 path,但是找不到 switch 之前的上一个 path。
我们给 environment.systemPackages
添加 neovim 试试看:
1❯ ns
2building the system configuration...
3activating the configuration...
4setting up /etc...
5reloading user units for davinci42...
6restarting sysinit-reactivation.target
7reloading the following units: dbus.service
8the following new units were started: NetworkManager-dispatcher.service
9Done. The new configuration is /nix/store/dc1j0mljl3dvlcn1qlk0qfjfs46kzs12-nixos-system-azure-25.05.20250424.f771eb4
10<<< /nix/store/abccik16826yrr4jgys1mhmkx3qbwp6a-nixos-system-azure-25.05.20250424.f771eb4
11>>> /nix/store/dc1j0mljl3dvlcn1qlk0qfjfs46kzs12-nixos-system-azure-25.05.20250424.f771eb4
12Version changes:
13[C.] #1 python3 3.12.9 x2 -> 3.12.9 x2, 3.12.9-env
14Added packages:
15[A.] #01 c-grammar-neovim 0.11.0
16[A.] #02 libluv 1.48.0-2
17[A.] #03 lua-grammar-neovim 0.11.0
18[A.] #04 luajit 2.1.1741730670, 2.1.1741730670-env x2
19[A.] #05 luajit2.1-lpeg 1.1.0-2
20[A.] #06 luajit2.1-luabitop 1.0.2-3
21[A.] #07 luajit2.1-mpack 1.0.12-0
22[A.] #08 markdown-grammar-neovim 0.11.0
23[A.] #09 markdown_inline-grammar-neovim 0.11.0
24[A+] #10 neovim 0.11.0
25[A.] #11 neovim-unwrapped 0.11.0
26[A.] #12 python3.12-greenlet 3.1.1
27[A.] #13 python3.12-msgpack 1.1.0
28[A.] #14 python3.12-pynvim 0.5.2
29[A.] #15 query-grammar-neovim 0.11.0
30[A.] #16 tree-sitter 0.25.3
31[A.] #17 unibilium 2.1.2
32[A.] #18 utf8proc 2.10.0
33[A.] #19 vim-grammar-neovim 0.11.0
34[A.] #20 vimdoc-grammar-neovim 0.11.0
35Closure size: 1145 -> 1168 (34 paths added, 11 paths removed, delta +23, disk usage +49.0MiB).
很完美!但是这么做具体有什么意义呢?
也没什么,看到 kernel 更新会记得重启一下吧。