最近一直在搞redhat。之前客户的机器都没有配置kdump,于是挨个给几百台虚机配kdump。我顺便就研究了下kdump的相关东西。
kdump是用来分析内核问题的好东西。当内核运行出现问题时,比如常见的死机,操作系统就已经不工作了。当计时器超时,也就是判断内核已经失效后,系统会引导crashkernel,也就是用来下载kdump的另一个内核。当它启动后,会按照kdump配置中的信息,将指定的内存空间中的内容存到硬盘指定位置。这样我们就可以根据生成的vmcore文件来分析是什么原因导致了系统故障。
kdump的配置可以直接redhat官网上去找,官方有提供配置的脚本,会自动备份你的配置并根据你的系统配置(主要是内存容量)修改对应配置文件里的参数。
其他的配置网上也都有,就不多说了。主要说几个点吧:
一个是/boot/grub/grub.conf里的crashkernel。crashkernel参数是指定给crashkernel留出多少内存空间的,你的内存越大,crashkernel在生成kdump时需要的内存越多,所以这个选项与内存大小有关,具体的需要去查一下,另外,redhat 5版本这个参数的写法是crashkernel=memory@offset的写法,但是在redhat 6中offset已经没有了,就是crashkernel=memory。
第二个是/etc/kdump.conf中的core_collector makedumpfile -c --message-level 1 -d 17。这条配置中-d是指定dumplevel,这里设置的是17,你可以根据redhat给出的说明修改为其他值。这个dumplevel会影响dump时dump内存哪些部分;尤其对于服务器来说,因为内存都非常大,如果全部页都dump的话,耗时长而且生成的vmcore非常的大,很占存储空间;通过指定不同的dumplevel,crashkernel会忽略一些没什么用的内存页,比如空白页,空白页里面没有数据,但是默认情况下它也会被dump下来。
第三个还是/etc/kdump.conf里的参数'default reboot,这条很简单,但是很有用。不配置这条并不会影响kdump正常工作,但是kdump默认情况下是不会自动重启机器的,也就是说在kdump完成之后,就一直处在待机状态。而此时你通过显示屏看不出内核是正在dump或是已经dump完成,因为屏幕什么也不显示。为了保险起见你只能多等一会,等内核dump完成再手动重启。另外,如果服务器故障后做了dump,你又没有发现这件事,那服务器就一直处在不工作的状态,这样很可能影响使用这台服务器的人的正常工作。如果你装的是物理机,又不支持ipmi和kvm console,机房又在别的地方。。。。。那不就坑爹了?你只有大老远跑一趟机房手动去按电源开关了。
/etc/init.d/kdump status,这条可以查看kdump的运行状态,当然如果是刚配置了kdump,必须要重启才能生效。
echo c > /proc/sysrq-trigger,这条是测试kdump的。记得输入这条命令之后系统内核会panic!!所以如果要测试需要在维护期间,不然业务都中断啦。成功的话,在你指定的目录下会生成vmcore文件(在新生成的文件夹里面),默认是/var/crash。
kdump生成成功了,那么怎么分析kdump呢?分析kdump需要下载相应的包才行。
需要的包中,kexec-tools在redhat 5以后都自带了,不用安装。另外两个是:
kernel-debuginfo-common-x86_64-2.6.32-xxx.el6.x86_64.rpm和
kernel-debuginfo-2.6.32-xxx.el6.x86_64.rpm
将xxx替换为相应的内核版本号就是要下载的包了。注意这两个包在redhat的安装镜像中是没有的,yum源似乎也没有,需要自己到网上去下载。我是在http://rpm.pbone.net/上下载的,这个里面相对比较全(redhat官网我没找到。。。)。
注意这里的版本号,不是和你的内核版本对应,而是和vmcore的版本号对应。如果你是本机生成了vmcore,在本机上分析,那么不存在这个问题;如果是一台6.2的redhat生成了vmcore,你把它传到了redhat 6.5的机器上去分析,那么你应当在这台6.5上安装6.2版本的kernel-debuginfo-common和kernel-debuginfo。注意这两个包只能安装一个,也就是说不同版本的kernel-debuginfo-common(和kernel-debuginfo),只能在一台机器上安装一个,如果要分析不同版本的vmcore,只能先删除原先的包,再安装另一个版本了。
环境准备完成,接下来分析vmcore了。分析使用的是crash命令:
crash /usr/lib/debug/lib/modules/2.6.32-xxx.el6.x86_64/vmlinux /var/crash/xxx/vmcore
两个参数,vmlinux路径和vmcore路径(如果你没安装前面的包,这个路径下是没有vmlinux的)。如果成功载入的话,就会进入crash的shell里面。
crash>
常用的命令就是:
crash> bt
crash> log
bt是显示内核最后运行的命令相关的情况,log是内核的日志。
其他命令网上搜一下就有了。或者在shell里面输入help也能看到有哪些命令。
这里给一个bt命令的输出吧:
PID: 2511 TASK: ffff8808686a0b40 CPU: 8 COMMAND: "kondemand/8"
#0 [ffff88086a47d8a0] machine_kexec at ffffffff81031fcb
#1 [ffff88086a47d900] crash_kexec at ffffffff810b8f72
#2 [ffff88086a47d9d0] oops_end at ffffffff814f04b0
#3 [ffff88086a47da00] die at ffffffff8100f26b
#4 [ffff88086a47da30] do_trap at ffffffff814efda4
#5 [ffff88086a47da90] do_divide_error at ffffffff8100cfff
#6 [ffff88086a47db30] divide_error at ffffffff8100be7b
[exception RIP: find_busiest_group+1477]
RIP: ffffffff81054ad5 RSP: ffff88086a47dbe0 RFLAGS: 00010046
RAX: 0000000000000000 RBX: ffff88086a47ddfc RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000018 RDI: 0000000000000018
RBP: ffff88086a47dd70 R8: ffff88089c44f860 R9: 0000000000000000
R10: 0000000000000000 R11: 0000000000000001 R12: 00000000ffffff01
R13: 0000000000015fc0 R14: ffffffffffffffff R15: 0000000000000000
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#7 [ffff88086a47dd78] thread_return at ffffffff814ecda1
#8 [ffff88086a47de38] worker_thread at ffffffff8108b33c
#9 [ffff88086a47dee8] kthread at ffffffff81090886
#10 [ffff88086a47df48] kernel_thread at ffffffff8100c14a
顶部显示的是进程的信息以及最后执行的命令。#数字就是堆栈信息。
至于更具体的分析。。。这个就没法讲了(我也不会)。vmcore里主要是堆栈信息之类的,基本上是内核开发人员才用crash来分析vmcore。对于其他人而言,也看不懂里面的内容,不过可以追踪以往的案例,通过vmcore的信息来判断是否是一个以前出现过的已知的BUG,从而根据以往的案例找到问题的原因并加以解决。
转载至:http://www.jianshu.com/p/87bf13ef494c