kexec踩坑

xeonds

2025-08-12 11:20:09

懒得在服务器折腾笔记里继续写了

我的服务器从大学开始经历过windows,esxi,esxi+ubuntu+windows,一直到现在archlinux+kvm windows/macos的方案。到现在用起来最舒服的还是最后一个方案,aur包多环境好配,系统各组件随用随装。

不过对应的缺点也有,就是arch是个滚动发行版,所以内核会经常更新。没nvidia的话还好,有了nvidia之后内核每次升级都会把对应的headers以及对应的内核模块删了换成新版本,导致nvidia用户态驱动发现内核态部分直接似了然后罢工;换言之就是升级了内核则想继续用nvidia-based的东西就得老实重启。

但是我不喜欢重启服务器,一来不在身边所以服务器一旦似在systemd-init阶段那我是回天乏力;另一方面服务中断也不太好受;虽然我大部分服务都用systemd/dockerd托管,但是也有一些脚本类的服务懒得挂守护进程直接扔到tmux跑的也不少,手动重新拉起也挺烦的。

这时候我就开始找解决方案了:

  1. 老实重启
  2. 找一个不重启就能切换新版本内核的方法
  3. 暂时把当前版本的nvidia内核态驱动找回来苟着
  4. 钝角

遂倒序尝试了一轮。

首先是尝试找回来当前版本的nvidia-dkms,但是modprobe相关操作试了半天不太中,而且linux-header找不到了,遂暂时放弃开始折腾2。

kexec这玩意看起来好像进入内核挺早的,顾名思义这东西跟exec可以类比,用新的内核进程替换当前运行中的内核。最诱惑的是这东西虽然也会中断服务,但是它的重启由于跳过了bios/uefi所以基本是秒级的速度。

然后我就用kexec拉起了新版内核的进程替代了当前版本的内核进程:

# kexec是系统调用但是cli还是得装个工具
sudo pacman -S kexec-tools
# 热重启
kexec -l /boot/vmlinuz-linux --initrd=/boot/initramfs-linux.img --reuse-cmdline
systemctl kexec # 让systemd处理服务停止和kexec动作
# kexec -e      # 直接执行内核替换,我用了这个

然后当天并没有发现什么不对劲的地方;到第二天过了将近24h后我发现不少服务中断了才才感觉不对劲;而发现ssh进程奇慢无比才感觉大事不妙:几乎要等3分钟,ssh才能成功,而且部分指令执行时间极长(现在推测应该是使用的各种工具或多或少有系统调用,而内核大抵的确是似了所以系统调用就stall然后超时自动失败了)。虽然容器里托管的服务都能正常使用,但是吧还是得赶紧重启解决问题。

然后就见证了传奇耐杀王的诞生。

# 普通小连招,卡住几分钟然后无事发生
sudo reboot
sudo shutdown -r now
# 升级但还是反应平静
echo 1 > /proc/sys/kernel/sysrq
echo b > /proc/sysrq-trigger
# 必杀技但是攻击力为0
sudo kill -9 -1
sudo telinit 6

结果嘛,还是经典力学好用,摇人帮忙给服务器手动重启了。以及重启后才想起来服务器上有那个ipmi的存在,既然用户态还活着那就有可能用它当跳板映射ipmi管理界面到我这里来,理论可行可惜没验证。

复盘

ds说是绕过acpi导致的不完全初始化+内存漂移/硬件状态漂移的问题,群u分析估计是新版内核缺了老版的什么符号之类的。

所以说没事别乱用,还是稳第一位。以及下次可以考虑下配个远程桌面看看。

关于kexec的安全用法,感觉第一,用systemd kexec也许能安全点;第二,ds给了个不知道是不是幻觉的--load-preserve-context。第三可能是跨版本kexec本来就不应该这么用。

先这样吧qaq下次滚的时候先把内核exclude了。