分类: LINUX
2007-07-12 16:16:02
通常在出现系统崩溃后,大家会担心再次出现故障,但是发现系统各日志中并没有记录到任何死机前后的信息,无法分析故障原因,认为已经无药可救。但是,实际上,Linux 有多种机制来保证发生系统崩溃后,可以获取有价值的信息用以分析问题。确定是硬件故障,还是应用程序bug 导致的。
Linux 中,有如下几种方法来获取各种崩溃时产生的信息。
Core dump
Core dump 通常用来调试应用程序错误,当某些应用程序运行出现异常崩溃时,可以开启系统的 core dump 功能,来得到一个程序崩溃时的内存信息,用来分析崩溃原因:
在/etc/profile里加上(或者修改)一条:
ulimit -c 0
运行命令:sysctl -w "kernel.core_name_format=/coredump/%n.core"
该命令意思是指core文件放在/coredump目录下,文件名是进程名+.core
Diskdump
diskdump工具提供了在单机上创建和采集vmcore(kernel
dump)的能力,而无须使用网络。当内核本身出现崩溃的时候,当前的内存和CPU状态以及相关的信息都会被保存到一个支持diskdump的磁盘上的保留分区上。
在下一次重新启动的时候,当系统重新启动,diskdump的初始化脚本会从保留分区中读取保存的信息并创建一个vcore文件,然后这个文件被再次存放到/var/crash/目录下,文件名为127.0.0.1-
如下是一个配置 HP SCSI 设备上启用 diskdump 的过程,如果不是 HP SCSI 设备(即设备名为 /dev/sdX的形式),则无须执行第三、四两个步骤。但需要在第一步前先执行命令: modprobe diskdump
第一步:编辑 /etc/sysconfig/diskdump文件,将一个空白分区的设备名填入后保存退出,例如:
DEVICE=/dev/cciss/c0d0p2
第二步:初使化 dump 设备
#service diskdump initialformat
警告:该分区的所以数据会丢失。
第三步:使用 cciss_dump 模块替换当前的 cciss 模块:
在 /etc/modprobe.conf 找到如下行:
alias scsi_hostadapter cciss
修改为:
alias scsi_hostadapter cciss_dump
再增加一行:
options cciss_dump dump_drive=1
注:假设diskdump文件中配置的为 /dev/cciss/c0d[#a]p[#b], 请设置为: options cciss_dump dump_drive=[#a]
第四步:重建 initrd 文件:
#mv /boot/initrd-`uname -r`.img /boot/initrd-`uname -r`.img.old
#mkinitrd /boot/initrd-`uname -r`.img `uname -r`
第五步:设置 diskdump 服务能够开机自启动:
# chkconfig diskdump on
Netdump
如果使用红旗DC4.0 或 3.0 版本系统,是不能支持 diskdump 的,可以利用netdump 来达到输出vmcore 的目的。但是Netdump要求至少有一个服务器以及任意数目的客户端。服务器用来接收客户端死机时的信息,客户端是经常死机的机器。
服务器配置:
1.检验netdump服 务器是否安装完毕:
rpm -q netdump-server
如果未安装,请在光盘 RedFlag/RPMS/ 目录中找到 netdump-server 打头的软件
包,执行命令:
rpm -ivh netdump-server-x.x.x.rpm (x为版本号)
进行安装。
2.服务器包安装后,用命令:
passwd netdump
更改用户的密码.
3.打开服务:
chkconfig netdump-server on
4.运行服务器:
service netdump-server start
客户端配置:
1.校验客户端是否已安装
rpm -q netdump
如果未安装,在光盘 RedFlag/RPMS/ 目录中找到 netdum 打头的软件包,执行命令:
rpm -ivh netdump-x.x.x.rpm (x为版本号)
安装.
2.编辑文件/etc/sysconfig/netdump, 添加如下行:
DEV=eth0
NETDUMPADDR=172.16.81.182
NETDUMPMACADDR=00:0C:29:79:F4:E0
172.16.81.182指 netdump 服务器地址。
3.运行下面的命令,出现提示符时输入密码:
service netdump propagate
4.打开客户端:
chkconfig netdump on
5.运行客户端:
service netdump start
6.测试
为了测试netdump的配置是否正确,在netdump客户机上做下面操作:
cp /usr/share/doc/netdump-xxxxxx/crash.c .
gcc -DKERNEL -DMODULE -I/lib/modules/$(uname -r)/build/include -c crash.c
insmod ./crash.o
这会造成系统崩溃,你会在netdump服务器的/var/crash/<客户端IP>
PS:怎么判断网卡是否支持netdump功能?
内核调试工具netdump需要网卡驱动支持netpoll功能。netpoll的目的是让内核在网络和I/O子系统尚不能完整可用时,依然能发送和接收数据包。主要用于网络控制台(net console)和远程内核调试(KGDBoE)中。实现netpoll功能,主要是要实现kernel中的poll_controller函数,该函数定义:void (*poll_controller)(struct net_device *dev)。该函数的作用是在缺少设备中断的情况下,还能对控制器做出响应。几乎所有的poll_controller函数都定义成如下形式:
void my_poll_controller(struct net_device *dev) {
disable_device_interrupt(dev);
call_interrupt_handler(dev->irq, dev);
enable_device_interrupt(dev);
}
所以,poll_controller只是模拟了来自指定设备的中断。一个最简单的判断一个网卡驱动是否这次支持netpoll功能的方法是安装内核源代码,然后在代码树
/usr/src/kernel-
# grep -r "HAVE_POLL_CONTROLLER" /usr/src/linux-2.4/drivers/net
/usr/src/linux-2.4/drivers/net/3c59x.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/3c59x.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/e100/e100_main.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/e100/e100_main.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/eepro100.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/eepro100.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/pcnet32.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/pcnet32.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/tg3.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/tg3.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/tlan.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/tlan.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/tulip/tulip_core.c:#ifdef HAVE_POLL_CONTROLLER
/usr/src/linux-2.4/drivers/net/tulip/tulip_core.c:#ifdef HAVE_POLL_CONTROLLER
从输出可以看到,3c59x, e100, e1000, eepro100, pcnet32, tg3, tlan和tulip都支持netpoll。
如果系统使用了这些网卡,那么系统应该支持netpoll,那么就支持netdump。
如果希望进一步确认网卡是否是使用这些网卡,可以查看/etc/modules.conf:
# cat /etc/modules.conf
alias eth1 e100
alias eth0 3c59x
SysRq
SysRq组合键是一组"魔术组合键",只要内核没有被完全锁住,键盘还能够使用,不管内核在做什么事情,使用这些组合键可以立即打印出内核的信息。
使用sysrq组合键是了解系统目前运行情况的最好方式。如果系统出现挂起的情况或者在诊断一些和内核相关,比较怪异,比较难重现的问题的时候,使用sysrq键是一个比较好的方式。
为了安全起见,默认SysRq组合键是关闭的。
打开这个功能,运行:
# echo 1 > /proc/sys/kernel/sysrq
关闭这个功能:
# echo 0 > /proc/sys/kernel/sysrq
如果想让此功能一直生效,在/etc/sysctl.conf里面设置kernel.sysrq的值为1. 重新启动以后,此功能将会自动打开。
kernel.sysrq = 1
因为打开sysrq键的功能以后,有终端访问权限的用户将会拥有一些特殊的功能。因此,除非是要调试,解决问题,一般情况下,不要打开此功能。如果一定要打开,请确保您的终端访问的安全性。
如何触发一个sysrq事件?
有几种方式可以触发sysrq事件。在带有AT键盘的一般系统上,在终端上输入一下组合键:
Alt+PrintScreen+[CommandKey]
例如,要让内核导出内存信息(CommandKey "m"),您应该同时按下Alt 和 Print Screen 键,然后按下 m 键. 提示: 此组合键在Xwindows上是无法使用的。所以,您先要切换到文本虚拟终端下。如果您现在是在图形界面,可以按Ctrl+Alt+F1切换到虚拟终端。
当我触发一个sysrq事件的时候,结果保存在什么地方?
当一个sysrq命令被触发,内核将会打印信息到内核的环形缓冲并输出到系统控制台。此信息一般也会通过syslog输出到/var/log/messages.
有时候,可能系统已经无法响应,syslogd可能无法记录此信息。在这种情况下,建议您配置一个串口终端来收集这个信息。
那些类型的sysrq事件可以被触发?
sysrq功能被打开后,有几种sysrq事件可以被触发。不同的内核版本可能会有些不同。但有一些是共用的:
* m - 导出关于内存分配的信息
* t - 导出线程状态信息
* p - 到处当前CPU寄存器信息和标志位的信息
* c - 故意让系统崩溃(在使用netdump或者diskdump的时候有用)
* s - 立即同步所有挂载的文件系统
* u - 立即重新挂载所有的文件系统为只读
* b - 立即重新启动系统
* o - 立即关机(如果机器配置并支持此项功能)
故障分析
虽然我们可以通过上述的几种方法来获取应用程序或操作系统崩溃时的各种信息,但是分析这些问题有一定难度。
常见问题
软件相关
系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,此类问题多数与应用程序Bug有关,不一定在所有相同配置系统中都会产生,但是一旦触发该Bug,就有可能发生崩溃。
系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,也有一些情况是新增的应用需要做一定的操作系统配置,没有设置的话,也有可能出现资源利用问题,导致崩溃发生。
系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,也有一些情况是应用的版本与操作系统版本不匹配,应用软件所需的系统库文件版本不对应,容易引发应用程序崩溃。
系统平时运行正常,近期没有任何新增应用,也没有更改系统配置,却接连发生多次崩溃现象。此类问题多数是压力增大,超出了硬件所能承受的负载,耗尽资源,发生崩溃。
系统平时运行正常,近期无新增应用,系统负载也不高,却发生崩溃现象。不排除操作系统本身的问题,有可能某种操作诱发了一个系统Bug,发生崩溃。
硬件相关
新增内存后,系统经常发生崩溃现象,此类问题有可能是32位机器配置了超过12GB的内存,但没有使用 hugemem 核心导致,具体原因可参见第一节中的说明。
机器使用期限较长,某个硬件发生故障,也会导致系统崩溃的发生。
新配置的机器经常发生崩溃现象,有可能硬件较新,而驱动程序版本较低,一般可通过升级驱动解决,驱动一般集成在内核当中,常见的办法是升级内核版本。