视频点此
有没有想过,当系统出现了内核级别的错误导致完全卡死时还可以自动重启,甚至还能提供一份出错时候的系统快照让你发现出错的位置?对于Windows,内核错误往往会伴随着蓝屏的出现,并提示错误代码。蓝屏的时候有部分情况可以做到自动重启,但大多数情只会卡在蓝屏界面,等待用户手工操作。对于Linux,因为内核的稳定性,出现这种层次的错误在日常应用中几乎遇不到。而一旦遇到,就直接卡死没有任何提示,这会让错误排查变得很困难。而由于驱动的缺陷,确实会有一些电脑的配置让Linux内核运行不稳定导致系统完全无响应的现象频发。所以在这种情况下,自动重启并提供错误文件就十分必要了。那有办法实现吗?有。今天就跟着我打造一个内核保姆吧。可能稍微的硬核一点儿…有些硬核…或者说…还蛮硬核的。
思路
就像最近报道的美国“末日计划”,一旦主领导人遭遇不测,则北方司令部司令可临时替代总统,直到新的领导人产生。这种内核也一样。在正常的内核里边嵌入另一个崩溃拯救内核待命。一旦正常的内核卡死,则自动启动拯救内核,在这个内核下导出当前崩溃的系统环境并重启回正常的内核。还挺好理解的吧?
方法
理解了思路就可以开始制作了。注意,我是Arch系统。对于RedHat和Debian分支,只可做参考。因为部分操作在其他发行版不适用,部分操作不需要像Arch这么麻烦。
再来约定两个内核的名字吧:正常使用的内核叫主内核,崩溃时启动的内核就叫拯救内核。
1、准备需要的软件包
asp //获取内核源文件的工具
base-devel //编译依赖包
pacman-contrib //更新MD5工具
kexec-tools //将拯救内核注入到主内核的工具
makedumpfile //精简快照文件体积,通过AUR安装
安装好这些软件包,就可以正式开始了。
2、获取内核源码
因为这个内核需要我们自己编译出来,所以它并不会跟随源的更新而更新,因此我推荐用长期支持内核作为模板进行编译,并且除非出现异常,否则就一直用就可以了。为了方便,可以通过官方的内核模板来制作这个内核。这里假设在~/build/
文件夹下执行下面的指令。
asp update linux-lts
asp export linux-lts
3、修改模板
与一般的内核不同,拯救内核需要修改一些参数以开启错误快照功能。编辑~/build/linux-lts/config
,修改下述参数并保存。
CONFIG_DEBUG_INFO=y
CONFIG_CRASH_DUMP=y
CONFIG_PROC_VMCORE=y
再编辑相同文件夹下的PKGBUILD
,修改下述内容并保存。
pkgbase=你自定义一个包名以区分一般的内核。比如叫linux-dump
4、更新MD5并开始编译
现在终端进入~/build/linux-lts
,输入命令updpkgsums
完成更新,再输入makepkg -s --skippgpcheck
开始编译。
你可能会发现,这其实就类似手工安装AUR的过程。所以在这一步进行的时候,如果发现下载内核源码相关文件的过程太慢,可以参考我以前说过的内容,通过事先下载的方法来解决。
而且因为是编译内核,所以这个过程消耗的时间并不短,具体时间就看你的电脑配置了,一般应该差不多一个小时的时间吧。
5、安装自定义内核
漫长的等待之后,你会在~/build/linux-lts
下面发现两个.tar.xz文件。现在你要做的,就是使用pacman -U 两个文件名
来安装上编译好的内核。
由于没有做优化,所以这个内核的fallback文件会很大导致EFI分区可能不够进而提示错误。但无需担心,主要的内容已经安装完成,我们可以进入/boot
将fallback删除掉。
内核安装完成。如果你想确定一下是否已经安装成功,可以直接更新grub文件,然后选择这个自定义内核启动,或者如果你会临时修改grub启动项参数的话,可以直接修改来临时测试一下,因为一般用不到这个内核做引导。
然后,去往~/build/linux-lts/src/唯一的那个文件夹/
下,将vmlinux
拷贝出来备用——如果你想做内核Debug而不单单只是做崩溃重启来用的话。
6、添加内存参数
虽然崩溃内核在主内核崩溃时才启动,但还是需要实现为其分配内存空间以保证它可以随时拥有足够内存来启动,因此需要在主内核增加参数来空出一部分内存。这也意味着这部分内存在主内核中就不能被使用了。编辑/etc/default/grub
,修改如下参数并保存:
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet crashkernel=256M@16M"
crashkernel部分是新增的,意思为从内存的16M地址位置开始,向后空出256M的内存区域。
之后,使用grub-mkconfig
来更新grub文件。
现在重启电脑,浏览/proc/iomem
文件,如果有一行为Crash kernel
,则证明主内核已经为拯救内核分配了空闲空间,修改成功了。
7、制作服务
到此就已经完成了大部分困难的工作了,接下来只需要制作两个服务,让拯救内核自动部署,卡死时自动导出错误快照并重启即可。
先来制作自动导出快照和重启的服务。将下述内容保存为/etc/systemd/system/kdump-save.service
:
[Unit]
Description=Create dump after kernel crash
DefaultDependencies=no
Wants=local-fs.target
After=local-fs.target
[Service]
Type=idle
ExecStart=/bin/sh -c 'mkdir -p /var/crash/ && /usr/bin/makedumpfile -c -d 31 /proc/vmcore "/var/crash/crashdump-$$(date +%%F-%%T)"'
ExecStopPost=/usr/bin/systemctl reboot
UMask=0077
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
通过这个服务,可以实现每当主内核出现错误,拯救内核启动时,将当前的环境快照保存到/var/crash/
下,命名为crash-dump-日期时间
,然后重启系统。
千万不要在主内核启动这个服务。否则你会陷入无限重启,无法自拔。
然后制作自动加载拯救内核的服务。将下述内容保存为/etc/systemd/system/kdump.service
:
[Unit]
Description=Load dump capture kernel
After=local-fs.target
[Service]
ExecStart=/usr/bin/kexec -p [/boot/vmlinuz-linux-dump] --initrd=[/boot/initramfs-linux-kdump.img] --append="root=[root-device] systemd.unit=kdump-save.service irqpoll maxcpus=1 reset_devices"
Type=oneshot
[Install]
WantedBy=multi-user.target
其中:
- [/boot/vmlinuz-linux-dump] 为你的拯救内核vmlinuz文件的文件名,一般是在boot目录,但名称是你自己定的
- [/boot/initramfs-linux-kdump.img] 同理
- [root-device] 为你的/挂载点设备
- 真正编写时,将上述的三个位置换成自己的,并且不需要中括号
然后,通过systemctl enable kdump
实现启动时自动部署拯救内核。
现在,重启你的电脑,查看/sys/kernel/kexec_crash_loaded
文件,如果显示1
,则证明拯救内核已经加载,双内核保障系统就建设完成了。
8、测试
接下来就是激动人心的测试环节。但正常使用的系统稳的一批,因此我们可以手工让内核出错,从而触发这个拯救机制来测试。但为了看效果,推荐进入到tty界面测试,图形界面只会在卡死一段时间后自动重启而看不到任何过程。
- 登录tty界面
- 提权到超级用户
sudo su
- 手工输入一个错误的系统调用,使内核崩溃
echo c > /proc/sysrq-trigger
好了,现在你已经手工让内核崩溃掉了。你会发现,在崩溃的一瞬间,拯救内核开始启动,并将错误内容导出,然后将你的电脑重启了。
至此,一个双内核加持的系统便制作完成了。不知你看没看出来,无论是各种载入状态的判断,还是让内核崩溃,都体现了一切皆文件的精髓:不管干什么,其本质都是在读写文本文件。而且你应该还可以发现,除了导出错误之外,因为可以自动重启,所以它还能为服务器做到错误自动恢复的功能。但到底要如何用好这个第二内核,就看你自己了。
如果你有耐心看到了这里,或者说你真的从视频跳到这里了,那么恭喜你,这里有5.4.28长期支持版本的编译文件,你可以直接下载而无需等待AUR从外网下载了。
地址:https://pan.baidu.com/s/1O8tkjjAKB-93clV1_Wm_JQ
提取码:6gfb