ubuntu内核转储分析——kdump和crash的下载和使用

ubuntu内核转储分析------kdump和crash的下载和使用

内存转储机制

需要用到的工具

kexec

kexec是一个快速启动机制,允许通过已经运行的内核的上下文启动一个Linux内核,不需要经过BIOS。BIOS可能会消耗很多时间,特别是带有

众多数量的外设的大型服务器。这种办法可以为经常启动机器的开发者节省很多时间。Kexec是实现kdump机制的关键,它包括2个组成部分:

一是内核空间的系统调用kexec_load,负责在生产内核(production kernel 或 first kernel)启动时将捕获内核(capture kernel或sencond kernel)

加载到指定地址。

二是用户空间的工具kexec-tools,他将捕获内核的地址传递给生产内核,从而在系统崩溃的时候能够找到捕获内核的地址并运行。

没有kexec就没有kdump。先有kexec实现了在一个内核中可以启动另一个内核,才让kdump有了用武之地。

kdump

kdump是一种在linux内核崩溃时获取内存转储的方法,它的主要原理是为系统配置两个内核,其中用于运行正常业务的内核称为生产内核 ,而在内核崩溃时用于转储信息的内核被称为捕获内核(crash kernel)。最初系统通过生产内核启动,并在启动过程中为捕获内核保留其运行所需的内存。当系统启动完成后,它将通过应用层服务,将捕获内核镜像加载到其对应的保留内存中。此后,生产内核就可像其它系统一样,正常地处理相关的业务。

若内核在运行中发生崩溃,且已设置了捕获内核,则生产内核则会首先准备好转储文件,然后启动捕获内核。捕获内核启动以后,将会生成转储文件vmcore。

crash

当 linux 系统内核发生崩溃的时候,生成了转储文件 vmcore。而后通过分析该 vmcore 文件就可以诊断出内核崩溃的原因,从而进行操作系统的代码改进。而 crash 就是一个被广泛使用的内核崩溃转储文件分析工具。

安装kdump

bash 复制代码
sudo apt install linux-crashdump

修改kexec-tools

|------------------------| Configuring kexec-tools |-------------------------------------|

| |

| |

| If you choose this option, a system reboot will trigger a restart into a |

| kernel loaded by kexec instead of going through the full system boot |

| loader process. |

| |

| Should kexec-tools handle reboots (sysvinit only)? |

| |

| |

| |

|------------------------------------------------------------------------------------------------|

安装成功后,将会在/etc/init.d中多了几个文件

kdump-tools

kexec

kexec-load

如果选择了No,也可以手动启动

bash 复制代码
sudo dpkg-reconfigure kexec-tools

这将修改/etc/init.d/kexec中的LOAD_KEXEC ,LOAD_KEXEC=true

确认kdump-tool是否启用

bash 复制代码
sudo kdump-config show

如果未安装kdump,将会提示

kdump-config: command not found

如果安装了kdump-config, 将会提示:

  • /etc/default/kdump-tools: USE_KDUMP is not set or zero
  • no crashkernel= parameter in the kernel cmdline
    dpkg-query: package 'kdump-tools' is not installed and no information is available

修改USER_KDUMP

这个参数默认是0,有文章说可以通过下面命令修改/etc/default/kdump-tools 文件中的 USE_KDUMP 参数为 1,表示启用了这个功能。

bash 复制代码
sudo dpkg-reconfigure kdump-tools

经过实测(包括重启)并没有什么效果,不清楚是什么原因。因此只能手动修改该参数

bash 复制代码
sudo vim /etc/default/kdump-tools
USE_KDUMP=1

配置以后再次执行

bash 复制代码
sudo kdump-config show

将不会提示 * /etc/default/kdump-tools: USE_KDUMP is not set or zero

修改crashkernel

如果存在/etc/default/grub.d/kdump-tools.cfg这个文件,执行

bash 复制代码
sudo vi /etc/default/grub.d/kdump-tools.cfg

否则,执行

bash 复制代码
sudo vi /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT=""中的参数修改为
GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT crashkernel=384M-:512M"

这个参数的格式是crashkernel=[总内存范围]:[保留内存大小]

  • [总内存范围]可以是一个具体的内存大小,也可以是一个范围。例如,384M-表示总内存大小在384M以上。
    [保留内存大小]则是你想要保留的内存大小。这部分内存将在系统启动时被预留出来,用于在系统崩溃时保存内核转储。

所以384M-:512M这个参数的意思是,对于总内存大小在384M以上的系统,保留512M的内存用于内核转储。

更新grub配置

bash 复制代码
sudo update-grub

重启系统以使配置生效

bash 复制代码
sudo reboot

手动触发内核崩溃,生成转储文件

第一步:

bash 复制代码
sudo sh -c "echo 1 > /proc/sys/kernel/sysrq"

第二步:

bash 复制代码
sudo sh -c "echo c > /proc/sysrq-trigger"

这里不直接使用sudo echo x > /proc/xxx/xxx/xxx的原因是使用它会报错Permission denied,是因为重定向符号 ">" 也是 bash 的命令。sudo 只是让 echo 命令具有了 root 权限,但是没有让 ">" 命令也具有root 权限,所以 bash 会认为这个命令没有写入信息的权限。

其中echo 1 > /proc/sys/kernel/sysrqecho c > /proc/sysrq-trigger是用来触发SysRq功能的命令。SysRq功能是一种种魔术系统请求键,可以让用户向内核发送一些特殊的命令,以获取或控制系统的信息或状态。

echo 1 > /proc/sys/kernel/sysrq向sysrq文件中写入1是为了开启SysRq功能(写入0是关闭SysRq功能),但是这需要内核支持(CONFIG_MAGIC_SYSRQ选项),它会让内核响应用户输入的任何操作,只要内核没有挂掉。此功能只是临时开启,重启后SysRq会自动关闭。如果想让此功能一直生效,在/etc/sysctl.conf里面设置kernel.sysrq的值为1. 重新启动以后,此功能将会自动打开。

echo c > /proc/sysrq-trigger是用来触发故意让系统统崩溃(crash)命令的命令,它会让内核立即即崩溃,并且不会管你有没有数据没有写回回磁盘,也不卸载载磁盘,而是完完全全地关机。

执行后,等待系统重启,在/var/crush中会生成几个文件,

root@ubuntu10:/var/crash# tree .

.

├── 202401021909

│ ├── dmesg.202401021909

│ └── dump.202401021909

├── kexec_cmd

└── linux-image-3.13.0-24-generic-202401021909.crash

其中

  • kexec_cmd是默认就有的
  • dmesg.202401021909:这个文件是系统内核崩溃时的内核日志,它记录了内核崩溃的原因和上下文信息,可以用来分析内核崩溃的原因和过程。
  • dump.202401021909:这个文件是系统内核崩溃时的内核内存转储文件,它包含了内核崩溃时的内存状态,可以用来分析内核崩溃的现场和数据。
  • linux-image-3.13.0-24-generic-202401021909.crash:这个文件是系统内核崩溃时,使用apport命令来生成的崩溃报告文件,它包含了系统内核的版本和配置信息,以及内核崩溃的时间和环境信息,可以用来报告和追踪内核崩溃的问题。

补充知识一:sysrq的参数

  • b - 即时重新启动系统
  • o - 即时关机
  • s - 即时同步所有挂载的文件系统
  • u - 即时重新挂载所有的文件系统为只读
  • p - 导出当前CPU寄存器信息和标志位的信息
  • t - 导出线程状态信息
  • m - 导出关于内存分配的信息
  • c - 故意让系统统崩溃(在使用netdump或diskdump的时候有用)
  • e - 杀死所有进程除了init使用SIGTERM
  • i - 杀死所有进程除了init使用SIGKILL

当一个sysrq命令被触发,内核将会打印信息到内核的环形缓冲并输出到系统控制台。此信息一般也会通过syslog输出到/var/log/messages/var/log/syslog。有时候,可能系统已无法响应,syslogd可能无法记录此信息。在这种情况下,建议你设置一个串口终端来收集这个信息。

补充知识二:CONFIG_XXX参数一般不需要修改

有的文章linux内核调试(四)内核转储kdump说,在安装kdump后,需要修改这几个参数,来支持kexec

CONFIG_KEXEC=y

CONFIG_SYSFS=y

CONFIG_DEBUG_KERNEL=y

CONFIG_CRASH_DUMP=y

CONFIG_PROC_VMCORE=y

CONFIG_DEBUG_INFO=y

这些针对的是高阶用户的,实际上除了CONFIG_DEBUG_INFO外,其他几个参数默认都是y,可以通过下面的命令查看。

bash 复制代码
sudo vim  /usr/src/linux-headers-$(uname -r)/.config

据说CONFIG_DEBUG_INFO开启后,会使得编译出的内核和模块文件的大小大大增加,所以一般也不需要选。

设置内核崩溃系统自动重启

打开sysctl.conf文件:

bash 复制代码
sudo vim /etc/sysctl.conf

在文件末尾添加以下行以配置内核崩溃后自动重启:
kernel.panic = 10

这将设置系统在内核崩溃后等待10秒后自动重启。您可以根据需要调整等待时间。

运行以下命令以使更改生效:

bash 复制代码
sudo sysctl -p

使用crash调试

查看是否存在vmlinux

bash 复制代码
ls //usr/lib/debug/boot

下载namelist:

namelist是一个包含了内核调试符号的vmlinux内核镜像文件

内核调试符号是指包含了调试信息的内核镜像文件,它可以帮助开发者或者分析者定位内核的错误或者性能问题。

添加一个新的源到/etc/apt/sources.list.d

bash 复制代码
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-security main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list

执行更新源

bash 复制代码
sudo apt update

如果报错The following signatures couldn't be verified because the public key is not available: NO_PUBKEY C8CAB6595FDFF622

添加软件源公钥

bash 复制代码
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C8CAB6595FDFF622

这里的keys后面的值,填写报错信息里面信息里面NO_PUBKEY后的值

再次执行

bash 复制代码
sudo apt update

下载vmlinux

bash 复制代码
sudo apt-get install linux-image-$(uname -r)-dbgsym

再次执行

bash 复制代码
ls /usr/lib/debug/boot

就能看到下载好的文件

下载指定的vmlinux内核镜像如果上面的方法行不通,还有其他两种方法,参见Ubuntu安装上的vmlinux在哪里?

使用crash命令查看内核转储文件

命令格式

bash 复制代码
crash [options] namelist [dumpfile] [modpath]

其中

  • namelist是一个包含了内核调试符号的内核镜像文件
  • dumpfile是一个内核崩溃数据文件或者实时系统的设备名
  • modpath是一个包含了内核模块的目录

例如:

bash 复制代码
crash /usr/lib/debug/boot/vmlinux-3.13.0-24-generic /var/crash/202401021909/dump.202401021909
相关推荐
vvw&2 小时前
如何在 Ubuntu 22.04 上安装 Ansible 教程
linux·运维·服务器·ubuntu·开源·ansible·devops
gs801403 小时前
ubuntu下 如何将 NVIDIA 内核驱动 升级到特定版本 如550.127
ubuntu·gpu·nvidia
1LOVESJohnny3 小时前
Linux | scp指令基于WSL在Windows/Ubuntu系统间传输文件
linux·ubuntu·wsl·文件传输
vvw&3 小时前
如何在 Ubuntu 22.04 上安装 Graylog 开源日志管理平台
linux·运维·服务器·ubuntu·开源·github·graylog
o(╥﹏╥)3 小时前
在 Ubuntu 上安装 VS Code
linux·运维·vscode·ubuntu·vs
Joyner20185 小时前
【Linux】ubuntu通过远程命令行启动桌面应用
linux·服务器·ubuntu
Eric.Lee20215 小时前
ubuntu paddle ocr 部署bug问题解决
ubuntu·ocr·paddle
御风_217 小时前
Linux——字符设备驱动控制LED
linux·ubuntu·linux驱动
明 庭15 小时前
Ubuntu下通过Docker部署NGINX服务器
服务器·ubuntu·docker
猿小蔡-Cool15 小时前
ubuntu20.04安装imwheel实现鼠标滚轮调速
ubuntu