文章目录
前言
网上关于crash kernel的捕获的教程大多都是基于封装好的kdump-service之类的(例如kdump-tools
),方便确实是方便的,但是它隐藏了一些细节,导致我修改参数的时候也不知道从何下手。
个人感觉,本质上,所谓的kdump-tools
其实就是基于kexec做了封装:
- kdump在安装后,会修改内核启动参数,添加crashkernel等配置
- (常规kernel)开机时,kdump会自动生成
kexec -p ...
命令,来加载dump-capture kernel(用来捕获内核) - 然后,系统崩溃后,系统会使用kexec切换内核到dump-capture kernel,此时kdump会自动压缩vmcore文件并保存到/var/crash目录(这个过程是利用一个service脚本)
- 保存好vmcore之后,kdump就直接重启机器,并切换到常规kernel。
- 最后,用户就可以查看
/var/crash
里面的文件,然后进行分析了。
因此,在使用kdump-tools时,用户几乎看不到dump-capture kernel的启动过程,就被跳过了。
kdump确实方便,但是了解kexec的原理我觉得也比较有意思。
参考官方教程:https://www.kernel.org/doc/html/next/admin-guide/kdump/kdump.html
一、添加crashkernel参数后,启动主机
- 修改grub参数,设置kernel启动参数
$ vim /etc/default/grub
修改下面这行参数,此处的参数含义参考 (https://www.kernel.org/doc/html/next/admin-guide/kdump/kdump.html)
...
GRUB_CMDLINE_LINUX="crashkernel=4096M"
...
- 更新grub配置
$ sudo update-grub
$ sudo reboot # 以新配置重启电脑
- 至于这里应该设置多大的空间,与系统内存大小有关。如果太小,无法正常启动dump-capture kernel。我这里192M的内存,设置"crashkernel=512M"时出问题
实验中遇到的问题
- 设置为"crashkernel=512M",在后面实验执行完
echo c | sudo tee /proc/sysrq-trigger
后,出现花屏后等了很久也没有启动内核。(正常现象应该是花屏后隔几秒就开始启动内核),然后进入保护模式,按ctrl+d继续启动
二、使用kexec加载用来dump-capture的内核
参考:https://www.kernel.org/doc/html/next/admin-guide/kdump/kdump.html
sudo kexec -p /boot/vmlinuz-5.15.0-79-generic \
--initrd=/boot/initrd.img-5.15.0-79-generic \
--append="root=/dev/mapper/ubuntu--vg-ubuntu--lv ro 1 irqpoll nr_cpus=1 reset_devices"
- 其中
root=/dev/mapper/ubuntu--vg-ubuntu--lv
可以参考cat /proc/cmdline
里面的参数 ro 1 irqpoll nr_cpus=1 reset_devices
可以参考 文档 中的说明- dump-capture kernel应该也可以与上一步的kernel是同一个。
实验现象:
运行命令后,可以使用
cat /sys/kernel/kexec_crash_loaded
查看,结果应该为1
三、通过手动触发panic启动用来dump-capture的内核
# sudo echo c > /proc/sysrq-trigger # 这个命令在某些系统上会没有权限,因为sudo只对echo命令生效,而未对管道符号">"生效
echo c | sudo tee /proc/sysrq-trigger # 使用sudo tee
四、实验现象/记录
1、手动触发panic后实验现象
手动触发panic后,电脑开始关机,屏幕花屏,然后隔几秒就开始启动内核,然后进入保护模式,中间有个提示,按ctrl+d可以继续启动内核。最后进入用来dump-capture的内核。
2、查看dump-capture kernel的信息
# 内核处于dump-capture kernel
$ uname -r
5.15.0-79-generic
# 存在/proc/vmcore文件,且大小为整个内存的大小(188G)
$ ls -lh /proc/vmcore
-r-------- 1 root root 188G Nov 16 07:42 /proc/vmcore
# 但是当前内核只有4G的内存,猜测是与crashkernel的设置有关?
$ free -h
total used free shared buff/cache available
Mem: 4.1Gi 780Mi 2.0Gi 9.0Mi 1.3Gi 3.0Gi
Swap: 8.0Gi 0.0Ki 8.0Gi
# cat /proc/cpuinfo查看CPU时,只打印了一个CPU,说明目前只有一个CPU在使用(原本应该是有很多CPU的)
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 106
model name : Intel(R) Xeon(R) Gold 6330 CPU @ 2.00GHz
stepping : 6
microcode : 0xd0003a5
cpu MHz : 800.038
cache size : 43008 KB
physical id : 0
siblings : 1
core id : 4
cpu cores : 1
apicid : 8
initial apicid : 8
fpu : yes
fpu_exception : yes
cpuid level : 27
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 invpcid_single intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local split_lock_detect wbnoinvd dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq la57 rdpid fsrm md_clear pconfig flush_l1d arch_capabilities
vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec tsc_scaling
bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs mmio_stale_data eibrs_pbrsb
bogomips : 4000.00
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 57 bits virtual
power management:
3、尝试拷贝整个vmcore
# 拷贝(需要花挺久时间,大概几分钟)
$ sudo cp /proc/vmcore .
# 拷贝完的文件大小为188G(猜测是192G-4G=188G)
$ ls -lh
total 8.0G
-r-------- 1 root root 188G Nov 16 07:56 vmcore
4、尝试使用makedumpfile压缩vmcore
# 压缩vmcore
$ sudo makedumpfile -l --message-level 1 -d 31 /proc/vmcore ./compressed_core
Copying data : [100.0 %] - eta: 0s
# 可以看到compressed_core的大小只有1G左右
$ ls -lh
total 8.0G
-rw------- 1 root root 1007M Nov 16 07:57 compressed_core
-r-------- 1 root root 188G Nov 16 07:56 vmcore
5、crash分析
得到compressed_core后,就可以使用crash来分析了(ps:最好使用源码安装的高版本crash)
$ sudo crash /home/dell/lmy/linux-lmy-latest/vmlinux ./compressed_core
这部分教程比较多,就略了。
附录
1、如何更改grub参数
- 修改配置文件
vim /etc/default/grub
- 更新grub
sudo update-grub
2、如何使用kexec快速切换内核
# 此处使用--reuse-cmdline使用当前的启动参数,不过也可以根据需要改成别的参数
# 加载内核
$ sudo kexec -l /boot/vmlinuz-5.15.0-79-generic --initrd=/boot/initrd.img-5.15.0-79-generic --reuse-cmdline
# 切换内核
$ sudo kexec -e
可以看到,与kexec -l
相比,kexec -p
主要是内核切换的触发条件不太相同。