crash内核调试准备事项之二三事

简介: ### 引言 解决Linux系统上疑难问题的常见方案之一是使用crash工具调试系统转储(coredump), 进入内核分析、排查。但是此方案时常不可行。这一点在内核较新的系统上尤甚。而捕捉 系统转储也有不少值得留意之处。我们一并讨论下使用crash工具调试系统转储的准备 事项及其背后的原因,以便更有效的使用此方案,减少无用功。 ### crash的黑魔法 crash工具对

引言

解决Linux系统上疑难问题的常见方案之一是使用crash工具调试系统转储(coredump),
进入内核分析、排查。但是此方案时常不可行。这一点在内核较新的系统上尤甚。而捕捉
系统转储也有不少值得留意之处。我们一并讨论下使用crash工具调试系统转储的准备
事项及其背后的原因,以便更有效的使用此方案,减少无用功。

crash的黑魔法

crash工具对内核和gdb使用了很多黑魔法,而非其公开的API或者文档化的
features。比如,crash并不是使用了libGDB框架,也不是如
ddd等gdb前端那样采用C/S架构。当然也
没有使用在Emacs内嵌gdb支持时采用的
"通信协议" -- gdb的的annotate特性。

那么,crash是怎么使用gdb的呢?crash使用自带而非系统安装的gdb。对自带的gdb,crash对
其打了补丁。通过这种方式,crash把gdb收编了。两者共存于同一进程,crash通过函数调用就
可以使用gdb。通过修改gdb命令执行完毕后返回哪个函数,crash就接管了入口。不管命令来自
交互式界面还是批处理文件,都是crash接到输入,进而路由命令,而后由自身、shell或者gdb
三者之一来执行命令。

crash解析系统转储,对黑魔法的使用也不遑多让。

凭借黑魔法,crash功能可观,但是却也时常因之无能为力。如何解决crash不能正常工作的
问题呢?答案是做好规划和准备,简化目标环境,降低复杂度,收集辅助数据,增加对目标环境的
认知。这也有助于我们理解crash的工作过程和验证crash结果。

源码和调试符号

调试需要调试符号和源码,但是不同的发行版,对于调试符号和源码的处理方式是不一样的。

对于CentOS、Fedora之类RHEL-Like的发行版,其有专门的软件源提供发布软件包各个
版本的调试符号和源码。可以从软件源手工下载,也可以调整yum/dnf的配置,把有关
软件源补充进来即可。比如,对于CentOS,其对应的软件源在
debuginfo.centos.org

而debian及其衍生的发行版,比如Ubuntu,几乎只能找到部分最新版本软件的调试符号,而且这些
调试符号对应的源码也往往无法拿到。

因此,如果使用的是debian或者其衍生的发行版,应备份内核源码等关键组建源码,并准备好相应的
构建环境,以备不时之需。

为makedumpfile提供额外信息

ECS之类的计算节点配备的内存越来越大,甚至内存大小都超出了其配备的磁盘空间。这种
情况下makedumpfile能够通过过滤和压缩产生较小系统转储,这个功能对存储和传递
系统转储无疑提供了便利。

但是便利并非没有成本。makedumpfile需要调试符号信息,以分析和判断哪些内存页需要压缩,
那些内存页可以丢弃。就是说在做系统转储时,需要有内核调试符号。变通之处是在有内核
调试符号的系统中,makedumpfile工具可以生成vmcoreinfo文件。这个文件在做系统
转储时可以替代内核调试符号使用。但是这个变通之处并非处处可行。比如qemu
虚机的monitor命令,其子命令dump-guest-memory就没有vmcoreinfo有关的选项。

但是,几乎所有的发行版,其提供的内核都开启了地址随机化(KASLR,
kernel address space layout randomization)。在没有关闭kaslr的情况下,
vmcoreinfo提供了系统的运行时信息,对于crash调试都是有益的。因此,在可能的情况下,
建议提供系统转储的同时,也提供vmcoreinfo文件。

使用内核命令行参数nokaslr即可关闭内核地址随机化。

使用kdump捕捉系统转储

在宿主机上我们可以把qemu进程视之为普通进程来做coredump;也可以使用qemu虚机的
monitor命令来保存虚拟机内存的方式来制作虚拟机的系统转储。这两种方案都有其应用
场景和便利之处。比如因为进程pid耗尽导致无法登陆或者业务进程无法启动的场景。但
这两种方案,即要在宿主机上有相应的权限,还缺少对虚拟机内部的知识,可用的
机制也不够灵活。

接下来我们讨论一个有竞争力的系统转储方案:基于kexec技术的Kdump。

kexec: 运行时启动新内核

kexec能够在运行时启动新内核。即在当前运行的Linux系统上,kexec能够让我们加载和
启用一个新的内核,代替老的内核来运行。这就带来了一种新的、生成系统转储的方案。

在Linux系统上,加载一个新的内核但不启动之。这时系统上就有了两个内核。一个是当前
在运行的内核,我们称之为生产内核;一个是刚刚加载但是没有运行的内核,我们称之为
捕获内核。然后把系统配置为生产内核panic时启动捕获内核。正如其名字所示的,捕获内核
负责为生产内核捕捉系统转储。

kdump怎么使用kexec?

预留内存

kdump要为捕获内核预留内存,这需要配置crashkernel内核命令行参数。RHEL-Like发行版
默认配置了这个参数,但是debian及其衍生版则未必。

持久化的配置内核命令行参数,需要调整GRUB的设定并刷新之,而后重启生效。因此,在
debian及其衍生版上部署kdump,如果新配置或者调整了内核命令行参数,需要重启系统。

提供守护进程

捕获内核依赖守护进程实现系统转储功能,这个守护进程需要kdump部署。这样捕获内核启动
后运行此守护进程即可。

那么,kdump是怎么通知捕获内核运行哪个守护进程的呢?答案是kdump提供了第二个守护进程。
这个守护进程运行在生产内核场景下,其职能就是实现某种机制用以告知捕获内核哪一个守护进程
是捕获进程(这里用进程不甚恰当,捕获进程不会在生产内核下运行)。这第二个守护进程
也负责处理内核有更新时的场景。

就是说,kdump提供了两个守护进程。一个运行在生产内核下,功能是告知捕获内核谁是捕获
进程;一个运行在捕获内核下,负责系统转储。

题外话,RHEL-Like发行版和debian及其衍生版实现上述功能采用了差异颇大的技术栈。

kdump的灵活性

可以充分借用makedumpfile的功能

捕获进程是单独的守护进程,使用的工具是makedumpfile。因之可以灵活的按需配置。比如说
把系统转储直接通过网络投递出去、过滤掉更多无用的内存页等等。更多细节请参考
makedumpfile的文档。

调配触发配置,扩大使用场景

生产内核panic时kdump才会生成系统转储。因此,可以按需调整系统,让其在特定条件下
panic,这样我们就能得到系统转储。

这里讨论两种情况。

调整内核参数

内核有参数控制某些情况出现时内核是否panic。比如vm.panic\_on\_oom参数。将之设定
为1则oom时会触发panic。其他类似的参数还有kernel.hung\_task\_panic
kernel.panic\_on\_rcu\_stall等。

灵活使用魔术键

使用魔术键
可以手工触发或者在脚本中触发内核panic。了解这一点,则可以在生产内核场景下部署脚本,检测
到问题复现则触发内核panic。

如何部署kdump?

根据上面的讨论,部署需要:

  1. 部署软件包:

    • RHEL-Like的发行版部署kexec-tools。除非必要,否则不必让kexec负责重启功能。
    • debian及其衍生版需要部署kexec-tools和kdump-tools
  2. 检查grub配置,核实为捕获内核预留了内存
  3. 如果调整了内核命令行参数,则重启系统
  4. 验证守护进程运行了
  5. (可选)通过魔术键测试kdump工作。

小结

crash调试系统转储,源码、调试符号和转储内容,三者缺一不可。提前做好规划和准备,使用crash
解决疑难问题,会更加便利和有效。

参考

  • 常见Linux发行版:CentOS

Fedora
RHEL
debianUbuntu

initramfs-tools,CentOS、Fedora之类
RHEL-Like的发行版使用dracut

dpkg/
apt/
aptitude,CentOS、Fedora之类
RHEL-Like的发行版使用rpm/
yum/dnf

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
17天前
|
网络协议 NoSQL Anolis
开局一张图,debug全靠瞪|内核问题定位与静态分析实战
本文描述了一个在AnolisOS 8.8操作系统上遇到的内核崩溃问题的调试过程。
|
2月前
|
监控 Linux
Linux脚本之监控系统内存使用情况并给予警告
Linux脚本之监控系统内存使用情况并给予警告
|
NoSQL Ubuntu
麟系统开发笔记(十):在国产麒麟系统上使用gdb定位崩溃异常方法流程以及测试Demo
本篇就适合代码崩溃的方法,可以定位到代码崩溃原因,测试Demo。
麟系统开发笔记(十):在国产麒麟系统上使用gdb定位崩溃异常方法流程以及测试Demo
|
Java
如何排查Java内存泄露(内附各种排查工具介绍)
今天刚刚才加一个故障review会议, 故障非常典型, 在google也可以找到相似案例介绍。 在排查问题的过程中,使用了大量的工具, 发现有问题的地方还不只一个,总结一下. (本篇文章不会重点描述案例本身,重点会介绍个人对java内存泄露问题的排查思路和各种工具的使用)。
22029 0
|
Web App开发 关系型数据库 项目管理
|
安全 Windows
Win系统 - 更新后,竟有这么“严重”的后果?
Win系统 - 更新后,竟有这么“严重”的后果?
149 0
Win系统 - 更新后,竟有这么“严重”的后果?
|
测试技术 Python
生成Airtest报告总出错?这份总结收好了
生成Airtest报告总出错?这份总结收好了
386 0
|
缓存 负载均衡 架构师
PyHubWeekly | 第四期:清理无效代码,给你的项目瘦瘦身吧!
当我们开发一个项目过程中,会不断的对某些部分进行增删、修改,这个过程中会产生很多无用的引用和代码。当这个工程代码量逐渐增多时,我们用人眼挨个去寻找无用代码自然是不现实的,本文就来介绍一款能够瞬间查找、修改项目中无效代码的工具,给你的项目瘦瘦身。
PyHubWeekly | 第四期:清理无效代码,给你的项目瘦瘦身吧!
|
移动开发 监控 前端开发
APM实战——让Bug无处可藏
通过日志很快的定位了崩溃页面,postman看一下接口返回数据,原来有一个String类型返回了null,同时客户端正好也刚改用Gson没有做好兼容导致崩溃(虽然bean有设默认值,但是Gson解析是直接通过反射完成,跨过了kotlin的默认值)。于是通知后端紧急修复先确保线上不报错。随后客户端通过自定义Gson TypeAdapter方式做了兼容。凭借U-APM监控告警+Bug追踪,从收到告警到fix bug用时十分钟,阻止了影响进一步扩大。
APM实战——让Bug无处可藏