手动添加kdump
背景:
Linux嵌入式设备内核挂死后,无法自动重启,需要手动重启。而且如果当时没有连串口的话,就无法记录内核挂死时的堆栈,所以需要添加一种方式来记录内核挂死信息方便以后调试使用。设备中增加kdump功能,可以将内核挂死的堆栈信息记录下来,供后期分析。
操作步骤:
1、添加kdump所需的程序及配置文件
方法:目前所分析得知需要如下文件/sbin/kdump /sbin/kexec /bin/kdumpctl /etc/kdump.conf /etc/sysconfig/kdump,然后编辑etc目录下的两个配置文件;修改kdump中KDUMP_BOOTDIR="/mnt",KDUMP_COMMANDLINE_APPEND="1 irqpoll maxcpus=1",KDUMP_IMG="kernel.img";修改kdump.conf内容为path /mnt/workdir/log;还需要修改kdumpctl中有关kdump和kexec的路径;将这些文件放到设备的mnt目录下然后重启,重启后执行kexec -l /mnt/kernel.img --initrd=/mnt/rootfs.img --command-line="`cat /proc/cmdline` 1 irqpoll maxcpus=1";kexec -e 查看是否添加成功。
2、问题:各种工具、配置文件均添加成功,但是执行kdumpctl start命令时,依然报错 BUG: unable to handle kernel paging request at ffff880001497000,或者不打印堆栈信息直接提示killed。
解决方法:经过测试,将添加到grub.cfg中的crashkernel=128M@16M改成crashkernel=128M,完全省略“@Y”这一部分,这样,kernel 会为我们自动选择一个起始地址。这样就不会出现起始地址错误等问题了。在测试kexec时,最好加上-d选项,将debug信息打印出来。
3、问题:经测试,按照第二步中的操作方法,kexec -e执行完成后,内核打完堆栈之后并未重启,而是直接卡死了。
解决方法:分析之后才发现,因为在/etc/sysconfig/kdump配置文件KDUMP_COMMANDLINE_APPEND字段添加了reset_devices,所以导致kdump内核无法重启。将KDUMP_COMMANDLINE_APPEND选项内容中reset_devices这个值删掉就可以了。
4、问题:内核panic错误发生后,内核重启,但是只进入到了新解压后的rootfs中,而系统的inittab根本就未被执行,导致后续的脚本没有执行。
解决方法:经过查找相关资料发现,linux在内核加载完成后,会解压initrd成rootfs根文件系统,随后执行根文件系统中的linuxrc或者init来初始化inittab配置文件,然后进行一系列的脚本初始化操作。根据现象发现,inittab确实没有被执行过,所以就开始查找inittab未被执行的原因。然后修改/etc/sysconfig/kdump文件中的KDUMP_COMMANDLINE_APPEND的值为"1 irqpoll maxcpus=1 init=/linuxrc",然后就可以执行成功了。
5、问题:由于采用原有的rootfs会造成设备启动许多不必要的程序、服务,所以应该重新定制一个kdump专用的rootfs。
解决方法:下载新版的busybox,然后编译、安装生成_install目录,该目录下就是部分文件系统,然后在创建dev,etc,lib,lib64,var,proc,tmp,mnt,sys这些系统所需的目录以及设备所需的workdir,mnt目录。由于编译busybox时,采用静态编译出错,所以没有采用静态编译的方式,因而需要用ldd busybox查看busybox所需的动态库,然后将这些动态库拷贝到创建好的/lib64目录中。由于linuxrc需要初始化系统,因而需要在/etc目录下添加fstab、inittab以及init.d/rcS这三个必备文件,由于fstab和inittab只跟系统有关,所以可以借用原来rootfs的对应文件,rcS系统程序的初始化脚本,可以将自己所需要实现的命令添加到rcS中,还需要在dev目录中添加相关设备节点,用mknod命令添加console, null等设备以及shm,pts目录作为挂载点。由于kdump重启后的系统中生成的vmcore过大,CF卡存储不下,只能用vmcore-dmesg /proc/vmcore命令提取内核崩溃日志,所以rcS就简单实现了挂载文件系统、CF卡、提取内核崩溃信息,然后重启系统的功能。由于新的rootfs是在kdump过程中使用,与原有的rootfs独立,所以提取内核崩溃日志的相关程序就需要预先添加到新的rootfs相关的目录中。整个rootfs目录文件添加完成之后,就在_install目录下执行find . | cpio -H newc --quiet -o | gzip -9 >~/rootfs.img,将这些文件夹打包并压缩生成rootfs.img放到当前用户的home目录。
6、问题:kdumpctl启动kdump服务时,要求内核以及initrd的名称格式,而且需要修改boot.cfg启动配置文件。
解决方案:最开始向采用修改安装包的方式,向安装包中添加kdump需要的内核以及initrd文件,但是经过尝试无法将这些文件打到vsos.bin中,后来发现是package.ini文件的配置,修改package.ini的配置后,可以将对应的文件添加到vsos.bin中了。但是在设备安装的时候,依然没有安装新添加的文件。由于对设备解包安装的过程不太熟悉,所以就采取折衷的方式:将新的initrd(即kdump需要的rootfs文件)添加到/mnt/system目录下,然后在开机启动脚本start.sh中,添加修改boot.cfg的功能,并将新的rootfs文件移至/mnt目录下,同时新建一个对原有内核文件的软连接供kdump使用,由于kdumpctl会检查内核文件、initrd文件、以及kdump的配置文件的时间戳,如果initrd文件的时间戳早于其他文件,kdumpctl尝试重新生成initrd文件,这个过程中很有可能报错,所以在移动文件结束后,就会用touch命令更新initrd文件的时间到最新。
7、问题:CF卡的磁盘编号有时不是/dev/sda1,导致kdump重启后按照/dev/sda1挂载失败
解决方法:用这个命令fdisk -l | grep "83" | grep "\*" | grep dev | awk '{print $1}'来获取CF卡的设备号。
内容汇总
kexec -l选项是直接加载内核,然后配置kexec -e命令启动新内核;而kexec -p选项则是指明当前内核遇到panic时,要启用的内核。需要echo c>/proc/sysrq-trigger,手动触发内核panic。
其实完全可以用kexec取代kdumpctl,这样就可以直接用老的内核名称,而且也不用考虑对kernel、initrd及配置文件的时间戳问题,而且由于采用的是新的rootfs系统,通过修改rcS脚本自己手动实现的内核崩溃信息保存,完全可以脱离对kdump相关配置文件的依赖,这样做是最简单的。但是考虑到标准linux中启动kdump的方式兼容,方便后续人员维护,就采用了kdumpctl的方式启动kdump服务。
由于在svn上提交的是一个封装好的img文件,所以要想对修改img文件中的内容,则需要先将img文件拷贝到一个新的文件夹下,然后执行:mv rootfs.img rootfs.img.gz; gzip -d rootfs.img.gz; cpio -id 还原出整个文件系统,然后按照需求进行修改,随后执行find . | cpio -H newc --quiet -o | gzip -9 >~/rootfs.img重新生成img文件。上述重新生成img文件的命令中,最后img文件的位置不能在当前目录。
得失分析:
由于对内核相关内容不太熟悉,所以前期只能通过从网上找相关资料,一点点尝试。虽然这个过程难了点儿,但是自己从中还是学到了很多东西,诸如Linux启动过程的详细过程之类的,学会了裁剪内核以及busybox,可以搭建一个小的迷你linux。
由于时间限制,并未进一步实现提取vmcore的功能。不过在现在有工作的基础之上应该很容易添加获取vmcore的功能。
手动添加kdump的更多相关文章
- IOS手动添加CoreData
手动添加coreData: 1.在target-build phrase-Link binary with libraries里增加CoreData Framework 2.加入数据模型:comman ...
- 如何手动添加Windows服务和如何把一个服务删除
windows 手动添加服务方法一:修改注册表 在注册表编辑器,展开分支"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services" ...
- Windows服务的手动添加和删除方法
Windows服务的手动添加和删除方法 服务,是指执行指定系统功能的程序.例程或进程,以便支持其他程序,尤其是低层(接近硬件)程序.其实,服务就是一种特殊的应用程序,它从服务启动开始就一直处于运行状态 ...
- 解决 Cocos2d-x 中 Android.mk 手动添加源文件
转自:http://blog.csdn.net/ypfsoul/article/details/8909178 Makefile Android.mk 引发的思索 在我们编写 Android 平台 c ...
- 仅仅需手动添加一行代码就可以让Laravel4执行在SAE (v. 1.0.0)
Github:https://github.com/chariothy/laravel4-sae (已更新至v1.1.0) laravel4-sae (v. 1.0.0) 仅仅需手动添加一行代码就可以 ...
- elasticsearch中国字(mmseg)——手动添加字典
elasticsearch中国文字本身并不是一个理想的插件效果.手动添加字典可以补偿在一定程度上. 后发现了几个实验,mmseg分段机制采用正向最长匹配算法.例如,抵抗"小时报"这 ...
- 将下载的本地的jar手动添加到maven仓库
将下载到本地的JAR包手动添加到Maven仓库 常用Maven仓库网址:http://mvnrepository.com/http://search.maven.org/http://reposito ...
- Maven 手动添加selenium JAR 包到本地仓库
安装Maven后我们会在用户目录下发现.m2 文件夹.默认情况下,该文件夹下放置了Maven本地仓库.m2/repository. 在intellij中创建maven项目时,添加 selenium 依 ...
- Maven手动添加jar包
有的jar在Maven中找不到则需要手动添加(如ojdbc14.jar) 方法如下: 一.将你要添加的jar包放到指定目录(在该目录下打开命令窗口) 二.输入指令:mvn install:instal ...
随机推荐
- 微信小程序开发心得
微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...
- ABP框架 - Swagger UI 集成
文档目录 本节内容: 简介 Asp.net Core 安装 安装Nuget包 配置 测试 Asp.net 5.x 安装 安装Nuget包 配置 测试 简介 来自它的网页:“...使用一个Swagger ...
- Javascript实用方法
这篇我主要记录一些在工作中常用的.实用的方法. String trim 字符串方法中的trim主要用来去空格使用,很多时候,在后台做参数处理的时候,我们都会使用该方法,比如在获取用户输入的账户时 va ...
- ASP.NET WebApi OWIN 实现 OAuth 2.0
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. OAuth 允许用户提供一个令牌, ...
- C++标准库实现WAV文件读写
在上一篇文章RIFF和WAVE音频文件格式中对WAV的文件格式做了介绍,本文将使用标准C++库实现对数据为PCM格式的WAV文件的读写操作,只使用标准C++库函数,不依赖于其他的库. WAV文件结构 ...
- 代码的坏味道(21)——中间人(Middle Man)
坏味道--中间人(Middle Man) 特征 如果一个类的作用仅仅是指向另一个类的委托,为什么要存在呢? 问题原因 对象的基本特征之一就是封装:对外部世界隐藏其内部细节.封装往往伴随委托.但是人们可 ...
- java统计字符串单词的个数
在一些项目中可能需要对一段字符串中的单词进行统计,我在这里写了一个简单的demo,有需要的同学可以拿去看一下. 本人没怎么写个播客,如果有啥说的不对的地方,你来打我啊 不说废话了直接贴代码: 实现代码 ...
- jQuery radio的取值与赋值
取值: $("input[name='radioName']:checked").val(); 赋值: $("input[name='radioName'][value= ...
- 在Ubuntu下安装ovs-dpdk
在Ubuntu下安装ovs-dpdk 参考资料:https://software.intel.com/zh-cn/articles/using-open-vswitch-with-dpdk-on-ub ...
- 用ProGet搭建内部的NuGet服务器
最近团队内部用的一个很简陋的NuGet服务器出问题了,nuget push发包,客户端显示发布成功,服务器上就是没有.懶得再去排查这个问题,早就想换掉这个过于简陋的NuGet服务器,借此机会直接弃旧迎 ...