网上关于crash kernel的捕获的教程大多都是基于封装好的kdump-service之类的(例如kdump-tools),方便确实是方便的,但是它隐藏了一些细节,导致我修改参数的时候也不知道从何下手。
个人感觉,本质上,所谓的kdump-tools其实就是基于kexec做了封装:
kexec -p ...命令,来加载dump-capture kernel(用来捕获内核)/var/crash里面的文件,然后进行分析了。因此,在使用kdump-tools时,用户几乎看不到dump-capture kernel的启动过程,就被跳过了。
kdump确实方便,但是了解kexec的原理我觉得也比较有意思。
参考官方教程:https://www.kernel.org/doc/html/next/admin-guide/kdump/kdump.html
$ vim /etc/default/grub
修改下面这行参数,此处的参数含义参考 (https://www.kernel.org/doc/html/next/admin-guide/kdump/kdump.html)
...
GRUB_CMDLINE_LINUX="crashkernel=4096M"
...
$ sudo update-grub
$ sudo reboot # 以新配置重启电脑
实验中遇到的问题
- 设置为"crashkernel=512M",在后面实验执行完
echo c | sudo tee /proc/sysrq-trigger后,出现花屏后等了很久也没有启动内核。(正常现象应该是花屏后隔几秒就开始启动内核),然后进入保护模式,按ctrl+d继续启动
参考: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可以参考 文档 中的说明实验现象:
运行命令后,可以使用
cat /sys/kernel/kexec_crash_loaded查看,结果应该为1
sudo echo c > /proc/sysrq-trigger # 这个命令在某些系统上会没有权限,因为sudo只对echo命令生效,而未对管道符号">"生效
echo c | sudo tee /proc/sysrq-trigger # 使用sudo tee
手动触发panic后,电脑开始关机,屏幕花屏,然后隔几秒就开始启动内核,然后进入保护模式,中间有个提示,按ctrl+d可以继续启动内核。最后进入用来dump-capture的内核。
# 内核处于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:
# 拷贝(需要花挺久时间,大概几分钟)
$ sudo cp /proc/vmcore .
# 拷贝完的文件大小为188G(猜测是192G-4G=188G)
$ ls -lh
total 8.0G
-r-------- 1 root root 188G Nov 16 07:56 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
得到compressed_core后,就可以使用crash来分析了(ps:最好使用源码安装的高版本crash)
$ sudo crash /home/dell/lmy/linux-lmy-latest/vmlinux ./compressed_core
这部分教程比较多,就略了。
vim /etc/default/grub
sudo update-grub
# 此处使用--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主要是内核切换的触发条件不太相同。