kexec是一个快速启动机制,允许通过已经运行的内核的上下文启动一个Linux内核,不需要经过BIOS。BIOS可能会消耗很多时间,特别是带有
众多数量的外设的大型服务器。这种办法可以为经常启动机器的开发者节省很多时间。Kexec是实现kdump机制的关键,它包括2个组成部分:
一是内核空间的系统调用kexec_load,负责在生产内核(production kernel 或 first kernel)启动时将捕获内核(capture kernel或sencond kernel)
加载到指定地址。
二是用户空间的工具kexec-tools,他将捕获内核的地址传递给生产内核,从而在系统崩溃的时候能够找到捕获内核的地址并运行。
没有kexec就没有kdump。先有kexec实现了在一个内核中可以启动另一个内核,才让kdump有了用武之地。
kdump是一种在linux内核崩溃时获取内存转储的方法,它的主要原理是为系统配置两个内核,其中用于运行正常业务的内核称为生产内核,而在内核崩溃时用于转储信息的内核被称为捕获内核(crash kernel)。最初系统通过生产内核启动,并在启动过程中为捕获内核保留其运行所需的内存。当系统启动完成后,它将通过应用层服务,将捕获内核镜像加载到其对应的保留内存中。此后,生产内核就可像其它系统一样,正常地处理相关的业务。
若内核在运行中发生崩溃,且已设置了捕获内核,则生产内核则会首先准备好转储文件,然后启动捕获内核。捕获内核启动以后,将会生成转储文件vmcore。
当 linux 系统内核发生崩溃的时候,生成了转储文件 vmcore。而后通过分析该 vmcore 文件就可以诊断出内核崩溃的原因,从而进行操作系统的代码改进。而 crash 就是一个被广泛使用的内核崩溃转储文件分析工具。
sudo apt install linux-crashdump
修改kexec-tools
|------------------------| Configuring kexec-tools |-------------------------------------|
| |
| |
| If you choose this option, a system reboot will trigger a restart into a |
| kernel loaded by kexec instead of going through the full system boot |
| loader process. |
| |
| Should kexec-tools handle reboots (sysvinit only)? |
| |
| |
| |
|------------------------------------------------------------------------------------------------|
安装成功后,将会在/etc/init.d中多了几个文件
kdump-tools
kexec
kexec-load
如果选择了No,也可以手动启动
sudo dpkg-reconfigure kexec-tools
这将修改/etc/init.d/kexec中的LOAD_KEXEC ,LOAD_KEXEC=true
sudo kdump-config show
如果未安装kdump,将会提示
kdump-config: command not found
如果安装了kdump-config, 将会提示:
- /etc/default/kdump-tools: USE_KDUMP is not set or zero
- no crashkernel= parameter in the kernel cmdline
dpkg-query: package ‘kdump-tools’ is not installed and no information is available
这个参数默认是0,有文章说可以通过下面命令修改/etc/default/kdump-tools 文件中的 USE_KDUMP 参数为 1,表示启用了这个功能。
sudo dpkg-reconfigure kdump-tools
经过实测(包括重启)并没有什么效果,不清楚是什么原因。因此只能手动修改该参数
sudo vim /etc/default/kdump-tools
USE_KDUMP=1
配置以后再次执行
sudo kdump-config show
将不会提示 * /etc/default/kdump-tools: USE_KDUMP is not set or zero
如果存在/etc/default/grub.d/kdump-tools.cfg这个文件,执行
sudo vi /etc/default/grub.d/kdump-tools.cfg
否则,执行
sudo vi /etc/default/grub
将GRUB_CMDLINE_LINUX_DEFAULT=""
中的参数修改为
GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT crashkernel=384M-:512M"
这个参数的格式是crashkernel=[总内存范围]:[保留内存大小]
[总内存范围]
可以是一个具体的内存大小,也可以是一个范围。例如,384M-表示总内存大小在384M以上。[保留内存大小]
则是你想要保留的内存大小。这部分内存将在系统启动时被预留出来,用于在系统崩溃时保存内核转储。所以384M-:512M这个参数的意思是,对于总内存大小在384M以上的系统,保留512M的内存用于内核转储。
sudo update-grub
sudo reboot
第一步:
sudo sh -c "echo 1 > /proc/sys/kernel/sysrq"
第二步:
sudo sh -c "echo c > /proc/sysrq-trigger"
这里不直接使用sudo echo x > /proc/xxx/xxx/xxx
的原因是使用它会报错Permission denied,是因为重定向符号 “>” 也是 bash 的命令。sudo 只是让 echo 命令具有了 root 权限,但是没有让 “>” 命令也具有root 权限,所以 bash 会认为这个命令没有写入信息的权限。
其中echo 1 > /proc/sys/kernel/sysrq
和echo c > /proc/sysrq-trigger
是用来触发SysRq功能的命令。SysRq功能是一种种魔术系统请求键,可以让用户向内核发送一些特殊的命令,以获取或控制系统的信息或状态。
echo 1 > /proc/sys/kernel/sysrq
向sysrq文件中写入1是为了开启SysRq功能(写入0是关闭SysRq功能),但是这需要内核支持(CONFIG_MAGIC_SYSRQ选项),它会让内核响应用户输入的任何操作,只要内核没有挂掉。此功能只是临时开启,重启后SysRq会自动关闭。如果想让此功能一直生效,在/etc/sysctl.conf
里面设置kernel.sysrq
的值为1. 重新启动以后,此功能将会自动打开。
echo c > /proc/sysrq-trigger
是用来触发故意让系统统崩溃(crash)命令的命令,它会让内核立即即崩溃,并且不会管你有没有数据没有写回回磁盘,也不卸载载磁盘,而是完完全全地关机。
执行后,等待系统重启,在/var/crush中会生成几个文件,
root@ubuntu10:/var/crash# tree .
.
├── 202401021909
│ ├── dmesg.202401021909
│ └── dump.202401021909
├── kexec_cmd
└── linux-image-3.13.0-24-generic-202401021909.crash
其中
补充知识一:sysrq的参数
当一个sysrq命令被触发,内核将会打印信息到内核的环形缓冲并输出到系统控制台。此信息一般也会通过syslog输出到/var/log/messages
或/var/log/syslog
。有时候,可能系统已无法响应,syslogd可能无法记录此信息。在这种情况下,建议你设置一个串口终端来收集这个信息。
补充知识二:CONFIG_XXX参数一般不需要修改
有的文章linux内核调试(四)内核转储kdump说,在安装kdump后,需要修改这几个参数,来支持kexec
CONFIG_KEXEC=y
CONFIG_SYSFS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_CRASH_DUMP=y
CONFIG_PROC_VMCORE=y
CONFIG_DEBUG_INFO=y
这些针对的是高阶用户的,实际上除了CONFIG_DEBUG_INFO外,其他几个参数默认都是y,可以通过下面的命令查看。
sudo vim /usr/src/linux-headers-$(uname -r)/.config
据说CONFIG_DEBUG_INFO开启后,会使得编译出的内核和模块文件的大小大大增加,所以一般也不需要选。
打开sysctl.conf文件:
sudo vim /etc/sysctl.conf
在文件末尾添加以下行以配置内核崩溃后自动重启:
kernel.panic = 10
这将设置系统在内核崩溃后等待10秒后自动重启。您可以根据需要调整等待时间。
运行以下命令以使更改生效:
sudo sysctl -p
ls //usr/lib/debug/boot
namelist是一个包含了内核调试符号的vmlinux内核镜像文件
内核调试符号是指包含了调试信息的内核镜像文件,它可以帮助开发者或者分析者定位内核的错误或者性能问题。
添加一个新的源到/etc/apt/sources.list.d
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-security main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list
执行更新源
sudo apt update
如果报错The following signatures couldn't be verified because the public key is not available: NO_PUBKEY C8CAB6595FDFF622
添加软件源公钥
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C8CAB6595FDFF622
这里的keys后面的值,填写报错信息里面信息里面NO_PUBKEY
后的值
再次执行
sudo apt update
下载vmlinux
sudo apt-get install linux-image-$(uname -r)-dbgsym
再次执行
ls /usr/lib/debug/boot
就能看到下载好的文件
下载指定的vmlinux内核镜像如果上面的方法行不通,还有其他两种方法,参见Ubuntu安装上的vmlinux在哪里?
命令格式
crash [options] namelist [dumpfile] [modpath]
其中
例如:
crash /usr/lib/debug/boot/vmlinux-3.13.0-24-generic /var/crash/202401021909/dump.202401021909