服务器的网络至少要能顺畅地访问 Nix Cache(https://cache.nixos.org), 大部分用作代理的(中国境外的)服务器通常都没有问题。
- 如果你正在安装 tcp-brutal, 请确保先跑一遍 tcp-brutal 安装脚本(即使会失败)。
否则, 请先手动安装好对应的 linux-headers。 - 给你的服务器装上 Nix。
如果你用 Debian 11 或者更新的 Debian, 可以直接apt install nix
。
如果你的软件仓库没有 Nix, 可以参考 https://nixos.org/download/ 里的操作执行一键脚本。
只需要安装好 Nix 即可, 我们的目标并不是将你的系统变成 NixOS。 - 下载这个 gist 里的
shell.nix
到你的服务器上。 - 在
shell.nix
同一目录执行nix-shell --run fix-kernel-headers
, 等它跑完。 - 如果你是在安装 tcp-brutal, 请重新跑一遍安装脚本以编译和载入模块。
否则, 请参考你正在安装的模块的文档继续, 通常情况下执行dkms autoinstall
就可以重新编译模块。
如果你只是想装好内核模块, 现在你就可以关掉这个网页了。
问题的起源是我们收到了数个 tcp-brutal 用户的 Issue (#7、 #18、 #21), 这些用户在 Debian 11 或者 Ubuntu 20.04 这种几年前的系统上使用 6.x 的 xanmod 内核, 并且在尝试安装 tcp-brutal 时失败。
Building module:
cleaning build area...
make -j1 KERNELRELEASE=6.9.10-x64v3-xanmod1 KERNEL_DIR=/lib/modules/6.9.10-x64v3-xanmod1/build all...(bad exit status: 2)
Error! Bad return status for module build on kernel: 6.9.10-x64v3-xanmod1 (x86_64)
Consult /var/lib/dkms/tcp-brutal/1.0.2/build/make.log for more information.
检查 /var/lib/dkms/tcp-brutal/1.0.2/build/make.log
, 可以看到如下输出:
# cat /var/lib/dkms/tcp-brutal/1.0.2/build/make.log
DKMS make.log for tcp-brutal-1.0.2 for kernel 6.9.10-x64v3-xanmod1 (x86_64)
Thu 25 Jul 2024 04:44:24 PM UTC
make -C /lib/modules/6.9.10-x64v3-xanmod1/build M=/var/lib/dkms/tcp-brutal/1.0.2/build modules
make[1]: Entering directory '/usr/src/linux-headers-6.9.10-x64v3-xanmod1'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: gcc-13 (Debian 13.3.0-1) 13.3.0
You are using: gcc (Debian 10.2.1-6) 10.2.1 20210110
CC [M] /var/lib/dkms/tcp-brutal/1.0.2/build/brutal.o
/var/lib/dkms/tcp-brutal/1.0.2/build/brutal.c:38:5: warning: no previous prototype for ‘tcp_sock_get_sec’ [-Wmissing-prototypes]
38 | u64 tcp_sock_get_sec(const struct tcp_sock *tp)
| ^~~~~~~~~~~~~~~~
./tools/objtool/objtool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./tools/objtool/objtool)
./tools/objtool/objtool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./tools/objtool/objtool)
make[3]: *** [scripts/Makefile.build:244: /var/lib/dkms/tcp-brutal/1.0.2/build/brutal.o] Error 1
make[3]: *** Deleting file '/var/lib/dkms/tcp-brutal/1.0.2/build/brutal.o'
make[2]: *** [/usr/src/linux-headers-6.9.10-x64v3-xanmod1/Makefile:2070: /var/lib/dkms/tcp-brutal/1.0.2/build] Error 2
make[1]: *** [Makefile:240: __sub-make] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-6.9.10-x64v3-xanmod1'
make: *** [Makefile:13: all] Error 2
实际上关键的只有这两行:
./tools/objtool/objtool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./tools/objtool/objtool)
./tools/objtool/objtool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./tools/objtool/objtool)
在 Linux 内核编译的 make prepare
阶段, 会先编译几个会在后续编译阶段用上的程序,
而这些编译好的 executable 也被作为 linux-headers 的一部分进行分发。
这些 executable 依赖编译机器上的 Glibc,
而 Glibc 有前向兼容问题 —— 链接到新版本 Glibc 的程序, 无法在旧版本 Glibc 的环境下执行。
在 #7 与 #18 中, 遇到这个问题的用户尝试通过修改软件仓库的配置文件, 从较新版本的软件仓库更新 Glibc, 但是, 这种跨版本的「不完全更新」可能会在后续安装某个包时导致系统损坏。 我们不打算推荐这种做法。
Nix 可以在多种 Linux 发行版上运行, 并且能够提供较新的 Glibc。 除此在外, Nix 还提供了一个叫做 patchelf 的工具, 可以修改 ELF 文件的 interpreter 和 rpath。 这个工具原本是用来修改既存的 executable 使其能够在 NixOS 这种非 UNIX 兼容的环境下运行的。 但是, 我们也可以用它修改 linux-headers 中的 executable, 使其通过 Nix 的 Glibc 执行, 从而解决上面提到的问题。
于是我编写了这个 Nix 脚本使这个操作可以「一键」执行。
因为 Debian 11 上用 apt install nix
安装的 Nix 版本太旧不支持 Flake, 才不是因为我懒。
不需要。 经过测试 gcc-10 编译的内核模块一样可以正常加载。 此外, 如果你需要 gcc-13, Nix 也可以快速地提供一个环境。