17 Kexec 和 Kdump #
Kexec 是一种可以从当前运行的内核引导进入另一内核的工具。您可以在不执行任何硬件初始化的情况下加快系统重引导速度。您还可以准备好系统,以便在系统崩溃的情况下引导进入另一内核。
17.1 简介 #
使用 Kexec 可将运行中的内核替换为另一内核,而无需硬性重引导。该工具非常有用,原因如下:
加快系统重引导速度
如果您需要频繁重引导系统,Kexec 可以帮您节省大量时间。
避免不可靠的固件和硬件
计算机硬件非常复杂,在系统启动期间可能会出现严重问题。您并不总能立即更换掉不可靠的硬件。Kexec 可将内核引导到已初始化硬件的受控环境。这样,就可以最大程度地减少系统启动失败的风险。
保存崩溃内核的转储
Kexec 可以保留物理内存的内容。在生产内核发生故障后,捕获内核(在预留内存范围内运行的附加内核)会保存有故障内核的状态。保存的映像可帮助您进行后续分析。
无需 GRUB 2 配置即可引导
当系统使用 Kexec 引导内核时,会跳过引导加载程序阶段。常规引导过程可能会由于引导加载程序配置中的错误而失败。使用 Kexec,您就不需要考虑引导加载程序配置是否有效。
17.2 所需的软件包 #
要在 SUSE® Linux Enterprise Server 上使用 Kexec 来加速重引导或避免潜在的硬件问题,请确保已安装 kexec-tools
软件包。该软件包包含名为 kexec-bootloader
的脚本,该脚本会读取引导加载程序配置,并使用与常规引导加载程序相同的内核选项来运行 Kexec。
要设置一个可在发生内核崩溃时帮助您获取调试信息的环境,请确保已安装 makedumpfile
软件包。
在 SUSE Linux Enterprise Server 中使用 Kdump 的首选方法是通过 YaST Kdump 模块来使用。要使用 YaST 模块,请确保已安装 yast2-kdump
软件包。
17.3 Kexec 内部结构 #
Kexec 中最重要的组件是 /sbin/kexec
命令。您可通过两种不同的方式使用 Kexec 装载内核:
将内核装载到某个生产内核的地址空间,以进行常规重引导:
root #
kexec
-l
KERNEL_IMAGE您可以稍后使用
kexec
-e
引导到此内核。将内核装载到预留的内存区域:
root #
kexec
-p
KERNEL_IMAGE当系统崩溃时,会自动引导此内核。
如果您希望在系统崩溃时引导另一内核并保留生产内核的数据,则需要预留一个系统内存专用区域。生产内核永远不会装载到此区域,因为生产内核必须始终可用。此区域用于捕获内核,以便可以保留生产内核的内存页。
要预留区域,请将选项 crashkernel
追加到生产内核的引导命令行。要确定 crashkernel
的所需值,请遵循第 17.4 节 “计算 crashkernel
分配大小”中的说明操作。
请注意,这不是捕获内核的参数。捕获内核不使用 Kexec。
捕获内核会装载到预留区域,并等待内核崩溃。然后,Kdump 会尝试调用捕获内核,因为生产内核在此阶段不再可靠。这意味着,甚至 Kdump 也有可能失败。
要装载捕获内核,需要添加内核引导参数。通常,会使用初始 RAM 文件系统进行引导。您可以使用 --initrd
=
FILENAME 指定该文件系统。使用 --append
=
CMDLINE 将选项追加到要引导的内核的命令行。
必须添加生产内核的命令行。您可以使用 --append
=
"$(cat /proc/cmdline)" 来简单地复制命令行,也可以使用 --append
=
"$(cat /proc/cmdline) more_options" 添加更多选项。
始终可以卸载先前装载的内核。要卸载通过 -l
选项装载的内核,请使用 kexec
-u
命令。要卸载通过 -p
选项装载的崩溃内核,请使用 kexec
-p
-u
命令。
17.4 计算 crashkernel
分配大小 #
要搭配捕获内核使用 Kexec 并以任何方式使用 Kdump,需要为捕获内核分配 RAM。分配大小取决于计算机的预期硬件配置,因此您需要指定此配置。
分配大小还取决于计算机的硬件体系结构。请确保遵循适合您系统体系结构的过程。
要获取计算机的基值,请运行以下命令:
root #
kdumptool
calibrate Total: 49074 Low: 72 High: 180 MinLow: 72 MaxLow: 3085 MinHigh: 0 MaxHigh: 45824所有值均以 MB 为单位。
请记下
Low
和High
的值。注意:Low
和High
值的重要性在 AMD64/Intel 64 计算机上,
High
值表示所有可用内存的内存预留量。Low
值表示 DMA32 区域中的内存预留量,即,所有内存不超过 4 GB 上限。SIZE_LOW 是仅支持 32 位的设备所需的内存量。内核将为 DMA32 回弹缓冲区分配 64M。如果您的服务器不包含任何仅支持 32 位的设备,为
SIZE_LOW
指定 72 M 的默认分配大小应可确保一切正常。一种可能的例外情况是,在 NUMA 计算机上,似乎需要更多的Low
内存。可以使用numa=off
引导 Kdump 内核,以确保常规内核分配不使用Low
内存。根据附加到计算机的 LUN 内核路径(储存设备的路径)数量调整上一步骤中的
High
值。可使用以下公式计算合理值(以 MB 为单位):SIZE_HIGH = RECOMMENDATION + (LUNs / 2)
此公式中使用了以下参数:
SIZE_HIGH:
High
的结果值。RECOMMENDATION:
kdumptool calibrate
建议的High
值。LUNs: 预期要在计算机上创建的最大 LUN 内核路径数。请从此数字中排除多路径设备,因为会忽略这些设备。
如果设备驱动程序在 DMA32 区域中预留了大量的内存,则还需要调整
Low
值。但是,没有任何简单公式可以计算这些值。因此,找到适当大小可能需要经历一个反复试验的过程。一开始,请使用
kdumptool calibrate
建议的Low
值。现在,需要在正确的位置设置值。
- 如果您直接更改内核命令行
请将以下内核选项追加到引导加载程序配置:
crashkernel=SIZE_HIGH,high crashkernel=SIZE_LOW,low
请将占位符 SIZE_HIGH 和 SIZE_LOW 替换为前面步骤中的相应值,并追加字母
M
(表示 MB)。例如,以下设置有效:
crashkernel=36M,high crashkernel=72M,low
- 如果您使用的是 YaST GUI:
将
设置为已确定的Low
值。将
设置为已确定的High
值。- 如果您使用的是 YaST 命令行界面:
使用以下命令:
root #
yast kdump startup enable alloc_mem=LOW,HIGH请将 LOW 替换为已确定的
Low
值。请将 HIGH 替换为已确定的HIGH
值。
要获取计算机的基值,请在终端中运行以下命令:
root #
kdumptool
calibrate此命令会返回值列表。所有值均以 MB 为单位。
请记下
Low
的值。根据附加到计算机的 LUN 内核路径(储存设备的路径)数量调整上一步骤中的
Low
值。可使用以下公式计算合理值(以 MB 为单位):SIZE_LOW = RECOMMENDATION + (LUNs / 2)
此公式中使用了以下参数:
SIZE_LOW:
Low
的结果值。RECOMMENDATION:
kdumptool calibrate
建议的Low
值。LUNs: 预期要在计算机上创建的最大 LUN 内核路径数。请从此数字中排除多路径设备,因为会忽略这些设备。
现在,需要在正确的位置设置值。
- 如果您使用的是命令行
请将以下内核选项追加到引导加载程序配置:
crashkernel=SIZE_LOW
请将占位符 SIZE_LOW 替换为前一步骤中的相应值,并追加字母
M
(表示 MB)。例如,以下设置有效:
crashkernel=108M
- 如果使用的是 YaST
将
设置为已确定的Low
值。
根据可用设备的数量,crashkernel
内核参数指定的计算内存量可能并不足够。您可以不增大该值,而是限制内核可见的设备数量。这可以降低“crashkernel”设置所需的内存量。
要忽略设备,可以运行
cio_ignore
工具生成相应的节来忽略所有设备(当前活动的或使用中的设备除外)。tux >
sudo
cio_ignore -u -k cio_ignore=all,!da5d,!f500-f502当您运行
cio_ignore -u -k
时,黑名单将会激活,并立即替换任何现有黑名单。不会清除未使用的设备,因此它们仍会显示在通道子系统中。但若添加新通道设备(通过 z/VM 下的 CP ATTACH,或 LPAR 中的动态 I/O 配置更改),会将这些设备视为已加入黑名单。为防止这种情况,请保留原始设置,方法是先运行sudo cio_ignore -l
,然后运行cio_ignore -u -k
之后还原到该状态。也可将生成的节添加到常规内核引导参数。现在,将包含上述节的
cio_ignore
内核参数添加到/etc/sysconfig/kdump
中的KDUMP_CMDLINE_APPEND
,例如:KDUMP_COMMANDLINE_APPEND="cio_ignore=all,!da5d,!f500-f502"
通过重启动
kdump
激活该设置:systemctl restart kdump.service
17.5 Kexec 基本用法 #
要使用 Kexec,请确保相应的服务已启用并正在运行:
确保在启动系统时装载 Kexec 服务:
tux >
sudo
systemctl enable kexec-load.service确保 Kexec 服务正在运行:
tux >
sudo
systemctl start kexec-load.service
要校验您的 Kexec 环境是否正常工作,请尝试使用 Kexec 重引导到新的内核。确保当前没有任何用户登录,且没有任何重要服务正在系统上运行。然后运行以下命令:
systemctl kexec
先前已装载到旧内核的地址空间中的新内核会重新写入,并立即接管控制权。它会如常显示启动消息。当新内核引导时,会跳过所有硬件和固件检查。请确保未显示任何警告消息。
要使 reboot
使用 Kexec 而不是执行常规重引导,请运行以下命令:
ln -s /usr/lib/systemd/system/kexec.target /etc/systemd/system/reboot.target
随时可以通过删除 etc/systemd/system/reboot.target
来还原此设置。
17.6 如何为例程重引导配置 Kexec #
Kexec 通常用于频繁重引导。例如,如果运行整个硬件检测例程需要花费很长时间或者启动不可靠,则可以使用 Kexec。
请注意,使用 Kexec 重引导系统时,不会使用固件和引导加载程序。在计算机执行硬性重引导之前,对引导加载程序配置所做的任何更改都将被忽略。
17.7 Kdump 基本配置 #
可以使用 Kdump 保存内核转储。如果内核崩溃,将已崩溃环境的内存映像复制到文件系统会很有用。然后,您可以调试转储文件,以找出内核崩溃的原因。这称为“核心转储”。
Kdump 的工作方式与 Kexec 类似(请参见第 17 章 “Kexec 和 Kdump”)。运行中的生产内核崩溃后,会执行捕获内核。区别在于,Kexec 将生产内核替换成了捕获内核。使用 Kdump 时,仍可以访问已崩溃生产内核的内存空间。可以在 Kdump 内核的环境中保存已崩溃内核的内存快照。
在本地储存有限的环境中,需要设置通过网络进行内核转储。Kdump 支持配置指定的网络接口,并通过 initrd
启动该接口。LAN 和 VLAN 接口均受支持。通过 YaST 或者在 /etc/sysconfig/kdump
文件中使用 KDUMP_NETCONFIG
选项来指定网络接口和模式(DHCP 或静态)。
配置 Kdump 时,可以指定用于保存转储映像的位置(默认位置:/var/crash
)。必须在配置 Kdump 期间装入此位置,否则配置将会失败。
17.7.1 Kdump 手动配置 #
Kdump 从 /etc/sysconfig/kdump
文件中读取其配置。Kdump 的默认配置足以确保其可在您的系统上正常工作。要以默认设置使用 Kdump,请遵循以下步骤:
遵循第 17.4 节 “计算
crashkernel
分配大小”中的说明确定 Kdump 所需的内存量。确保设置内核参数crashkernel
。重新启动计算机。
启用 Kdump 服务:
root #
systemctl
enable kdump可以在
/etc/sysconfig/kdump
中编辑选项。阅读注释有助于了解各个选项的含义。使用
sudo systemctl start kdump
执行一次 init 脚本,或重引导系统。
使用默认值配置 Kdump 后,检查它是否按预期工作。确保当前没有任何用户登录,且没有任何重要服务正在系统上运行。然后遵循以下步骤:
使用
systemctl isolate rescue.target
切换到救援目标重启动 Kdump 服务:
root #
systemctl
start kdump使用以下命令卸载除根文件系统以外的所有磁盘文件系统:
root #
umount
-a以只读模式重新装入根文件系统:
root #
mount
-o remount,ro /使用 Magic SysRq 组合键的
procfs
接口调用“内核错误 (kernel panic)”:root #
echo
c > /proc/sysrq-trigger
KDUMP_KEEP_OLD_DUMPS
选项控制所保留内核转储的数量(默认值为 5)。在不压缩的情况下,转储大小最大可为物理 RAM 内存的大小。请确保 /var
分区上有足够的空间。
捕获内核将会引导,已崩溃内核的内存快照将保存到文件系统。保存路径由 KDUMP_SAVEDIR
选项指定,默认为 /var/crash
。如果 KDUMP_IMMEDIATE_REBOOT
设置为 yes
,系统会自动重引导生产内核。登录并检查是否已在 /var/crash
下创建了转储。
17.7.1.1 Kdump 的静态 IP 配置 #
如果已将 Kdump 配置为使用网络设备中的静态 IP 配置,则您需要将网络配置添加到 /etc/sysconfig/kdump
中的 KDUMP_COMMANDLINE_APPEND
变量。
配置了以下设置:
为 eth0 配置了静态 IP 地址
192.168.1.1/24
为 eth1 配置了静态 IP 地址
10.50.50.100/20
/etc/sysconfig/kdump
中的 Kdump 配置如下所示:KDUMP_CPUS=1 KDUMP_IMMEDIATE_REBOOT=yes KDUMP_SAVEDIR=ftp://anonymous@10.50.50.140/crashdump/ KDUMP_KEEP_OLD_DUMPS=5 KDUMP_FREE_DISK_SIZE=64 KDUMP_VERBOSE=3 KDUMP_DUMPLEVEL=31 KDUMP_DUMPFORMAT=lzo KDUMP_CONTINUE_ON_ERROR=yes KDUMP_NETCONFIG=eth1:static KDUMP_NET_TIMEOUT=30
如果使用此配置,当 Kdump 尝试向 FTP 服务器写入转储时将无法访问网络。要解决此问题,请将网络配置添加到 /etc/sysconfig/kdump
中的 KDUMP_COMMANDLINE_APPEND
。此操作的一般模式如下所示:
KDUMP_COMMANDLINE_APPEND='ip=CLIENT IP:SERVER IP:GATEWAY IP:NETMASK:CLIENT HOSTNAME:DEVICE:PROTOCOL'
对于示例配置将为:
KDUMP_COMMANDLINE_APPEND='ip=10.50.50.100:10.50.50.140:10.60.48.1:255.255.240.0:dump-client:eth1:none'
17.7.2 YaST 配置 #
要使用 YaST 配置 Kdump,需要安装 yast2-kdump
软件包。然后在 的 类别中启动 模块,或者以 root
身份在命令行中输入 yast2 kdump
。
在
窗口中选择 。
当您首次打开该窗口时,系统会自动生成 第 17.4 节 “计算 crashkernel
分配大小”中的说明操作。
如果您在计算机上设置了 Kdump,后来决定更改 Kdump 的可用 RAM 或硬盘容量,YaST 将继续显示并使用已过时的内存值。
要解决此问题,请根据第 17.4 节 “计算 crashkernel
分配大小”中所述再次确定所需内存。然后在 YaST 中手动设置内存。
在左窗格中单击
,然后检查要包含在转储中的页。无需包含以下内存内容即可调试内核问题:以零填充的页
缓存页
用户数据页
可用页
在
窗口中,选择转储目标的类型,以及要将转储保存到的 URL。如果您选择了 FTP 或 SSH 等网络协议,则还需要输入相关的访问信息。可以指定 Kdump 转储的保存路径,其他应用程序也可以在此路径中保存其转储。当 Kdump 清理其旧转储文件时,会安全忽略其他应用程序的转储文件。
如果您希望 Kdump 通过电子邮件将其事件通知给您,请填写
窗口信息,并在 窗口中微调 Kdump 后,单击 确认更改。现已配置 Kdump。17.7.3 Kdump 通过 SSH 传输 #
转储文件常常包含敏感数据,因此应防范未经授权透露这些数据。要允许通过不安全的网络传输此类数据,Kdump 可以使用 SSH 协议将转储文件保存到远程计算机。
目标主机身份对于 Kdump 必须是已知的。需要做到这一点才能确保永远不会向欺骗者发送敏感数据。当 Kdump 生成新的
initrd
时,会运行ssh-keygen -F TARGET_HOST
来查询目标主机的身份。仅当 TARGET_HOST 公共密钥已知时,才可完成此查询。实现该操作的一种简单方法是在 Kdump 主机上以root
身份与 TARGET_HOST 建立 SSH 连接。Kdump 必须能够对目标计算机进行身份验证。目前只能使用公共密钥身份验证。默认情况下,Kdump 使用
root
的私用密钥,但建议您为 Kdump 创建单独的密钥。可以使用ssh-keygen
创建该密钥:root #
ssh-keygen
-f ~/.ssh/kdump_key当系统提示输入通行口令时,请按 Enter(即,不使用任何通行口令)。
打开
/etc/sysconfig/kdump
并将KDUMP_SSH_IDENTITY
设置为 kdump_key。如果该文件不在~/.ssh
下,可以使用其完整路径。
设置 Kdump SSH 密钥以授权登录到远程主机。
root #
ssh-copy-id
-i ~/.ssh/kdump_key TARGET_HOST设置
KDUMP_SAVEDIR
。有两个选项:- 安全文件传输协议 (sftp)
SFTP 是通过 SSH 传输文件的首选方法。目标主机必须启用 sftp 子系统(默认为 SLE)。示例:
KDUMP_SAVEDIR=sftp://TARGET_HOST/path/to/dumps
- 安全外壳协议 (ssh)
其他某些发行套件使用 SSH 在目标主机上运行某些命令。SUSE Linux Enterprise Server 也可以使用此方法。目标主机上的 Kdump 用户必须具有一个可执行以下命令的登录外壳:
mkdir
、dd
和mv
。示例:KDUMP_SAVEDIR=ssh://TARGET_HOST/path/to/dumps
重启动 Kdump 服务以使用新配置。
17.8 分析崩溃转储 #
获取转储后,便可以开始对它进行分析了。系统提供了多个选项。
用于分析转储的初始工具为 GDB。您甚至可以在最新的环境中使用此工具,不过,它也存在一些缺点和限制:
GDB 并非专用于调试内核转储的工具。
GDB 不支持 32 位平台上的 ELF64 二进制文件。
GDB 不能识别除 ELF 转储以外的其他格式(无法调试压缩的转储)。
由于这些原因,我们实施的实用程序是 crash
。crash 能够分析崩溃转储,还能调试运行中的系统。它提供了专用于调试 Linux 内核的功能,更适合用于高级调试。
如果您想要调试 Linux 内核,需要额外安装其调试信息软件包。使用以下命令检查您的系统上是否已安装该软件包:
tux >
zypper
se kernel |grep
debug
如果您为系统订阅了联机更新,便可以在 SUSE Linux Enterprise Server 15 SP2 相关的 *-Debuginfo-Updates
联机安装储存库中找到 “debuginfo” 软件包。使用 YaST 启用该储存库。
要在生成转储的计算机上的 crash
中打开捕获的转储,请使用如下所示的命令:
crash
/boot/vmlinux-2.6.32.8-0.1-default.gz \
/var/crash/2010-04-23-11\:17/vmcore
第一个参数表示内核映像。第二个参数是 Kdump 捕获的转储文件。默认可在 /var/crash
下找到此文件。
SUSE Linux Enterprise Server 随附了 kdumpid
实用程序(包含在同名的软件包中)用于识别未知的内核转储。可以使用此实用程序来提取基本信息,例如体系结构和内核版本。它支持 lkcd、diskdump、Kdump 文件和 ELF 转储。使用 -v
开关调用此实用程序时,它会尝试提取额外信息,例如计算机类型、内核标题字符串和内核配置风格。
17.8.1 内核二进制文件格式 #
Linux 内核采用可执行与可链接格式 (ELF)。此文件通常名为 vmlinux
,是在编译过程中直接生成的。并非所有引导加载程序都支持 ELF 二进制文件,尤其是在 AMD64/Intel 64 体系结构上。SUSE® Linux Enterprise Server 支持的不同体系结构上存在以下解决方案。
17.8.1.1 AMD64/Intel 64 #
SUSE 提供的适用于 AMD64/Intel 64 的内核软件包中包含两个内核文件:vmlinuz
和 vmlinux.gz
。
vmlinuz
: 这是由引导加载程序执行的文件。Linux 内核由两个部分组成:内核本身 (
vmlinux
),以及由引导加载程序运行的设置代码。这两个部分关联在一起创建了vmlinuz
(请注意字母z
与x
的差别)。在内核源树中,该文件名为
bzImage
。vmlinux.gz
: 这是可由crash
和 GDB 使用的压缩 ELF 映像。在 AMD64/Intel 64 上,引导加载程序本身永远不会使用 ELF 映像。因此,只随附了一个压缩版本。
17.8.1.2 POWER #
POWER 上的 yaboot
引导加载程序也支持装载 ELF 映像,但不支持压缩的 ELF 映像。在 POWER 内核软件包中,有一个 ELF Linux 内核文件 vmlinux
。对于 crash
而言,POWER 是最简单的体系结构。
如果您决定在另一台计算机上分析转储,必须检查计算机的体系结构,以及调试所需的文件。
仅当另一台计算机运行相同体系结构的 Linux 系统时,才能在该计算机上分析转储。要检查兼容性,请在两台计算机上使用命令 uname
-i
并比较输出。
如果您要在另一台计算机上分析转储,还需要获取 kernel
和 kernel debug
软件包中的适当文件。
将内核转储、
/boot
中的内核映像以及/usr/lib/debug/boot
中的关联调试信息文件放到一个空目录中。此外,请将
/lib/modules/$(uname -r)/kernel/
中的内核模块以及/usr/lib/debug/lib/modules/$(uname -r)/kernel/
中的关联调试信息文件复制到名为modules
的子目录中。在包含转储、内核映像及其调试信息文件以及
modules
子目录的目录中,启动crash
实用程序:tux >
crash
VMLINUX-VERSION vmcore
不管您在哪台计算机上分析转储,crash 实用程序都会生成如下所示的输出:
tux >
crash
/boot/vmlinux-5.3.18-8-default.gz \ /var/crash/2020-04-23-11\:17/vmcore crash 7.2.1 Copyright (C) 2002-2017 Red Hat, Inc. Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation Copyright (C) 1999-2006 Hewlett-Packard Co Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited Copyright (C) 2006, 2007 VA Linux Systems Japan K.K. Copyright (C) 2005, 2011 NEC Corporation Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc. Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. This program is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Enter "help copying" to see the conditions. This program has absolutely no warranty. Enter "help warranty" for details. GNU gdb (GDB) 7.6 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". KERNEL: /boot/vmlinux-5.3.18-8-default.gz DEBUGINFO: /usr/lib/debug/boot/vmlinux-5.3.18-8-default.debug DUMPFILE: /var/crash/2020-04-23-11:17/vmcore CPUS: 2 DATE: Thu Apr 23 13:17:01 2020 UPTIME: 00:10:41 LOAD AVERAGE: 0.01, 0.09, 0.09 TASKS: 42 NODENAME: eros RELEASE: 5.3.18-8-default VERSION: #1 SMP 2020-03-31 14:50:44 +0200 MACHINE: x86_64 (2999 Mhz) MEMORY: 16 GB PANIC: "SysRq : Trigger a crashdump" PID: 9446 COMMAND: "bash" TASK: ffff88003a57c3c0 [THREAD_INFO: ffff880037168000] CPU: 1 STATE: TASK_RUNNING (SYSRQ)crash>
命令输出首先列显有用的数据:在内核崩溃时有 42 个任务正在运行。崩溃的原因是 PID 为 9446 的任务调用了 SysRq 触发器。此任务是一个 Bash 进程,因为使用的 echo
是 Bash 外壳的内部命令。
crash
实用程序是在 GDB 的基础上构建的,可提供许多额外的命令。如果您输入不带任何参数的 bt
,将列显在崩溃时正在运行任务的回溯:
crash>
bt
PID: 9446 TASK: ffff88003a57c3c0 CPU: 1 COMMAND: "bash" #0 [ffff880037169db0] crash_kexec at ffffffff80268fd6 #1 [ffff880037169e80] __handle_sysrq at ffffffff803d50ed #2 [ffff880037169ec0] write_sysrq_trigger at ffffffff802f6fc5 #3 [ffff880037169ed0] proc_reg_write at ffffffff802f068b #4 [ffff880037169f10] vfs_write at ffffffff802b1aba #5 [ffff880037169f40] sys_write at ffffffff802b1c1f #6 [ffff880037169f80] system_call_fastpath at ffffffff8020bfbb RIP: 00007fa958991f60 RSP: 00007fff61330390 RFLAGS: 00010246 RAX: 0000000000000001 RBX: ffffffff8020bfbb RCX: 0000000000000001 RDX: 0000000000000002 RSI: 00007fa959284000 RDI: 0000000000000001 RBP: 0000000000000002 R8: 00007fa9592516f0 R9: 00007fa958c209c0 R10: 00007fa958c209c0 R11: 0000000000000246 R12: 00007fa958c1f780 R13: 00007fa959284000 R14: 0000000000000002 R15: 00000000595569d0 ORIG_RAX: 0000000000000001 CS: 0033 SS: 002bcrash>
现在,发生的情况便一清二楚了:Bash 外壳的内部 echo
命令向 /proc/sysrq-trigger
发送了一个字符。相应的处理程序在识别此字符后,调用了 crash_kexec()
函数。此函数调用了 panic()
,且 Kdump 保存了转储。
除了基本的 GDB 命令以及 bt
的扩展版本以外,crash 实用程序还定义了与 Linux 内核结构相关的其他命令。这些命令可识别 Linux 内核的内部数据结构,并以直观易懂的格式显示这些内容。例如,您可以使用 ps
列出崩溃时正在运行的任务。使用 sym
可以列出包含相应地址的所有内核符号,或查询单个符号的值。使用 files
可以显示进程的所有打开文件描述符。使用 kmem
可以显示有关内核内存使用率的细节。使用 vm
可以检查进程的虚拟内存,甚至是在单个页映射级别。有用命令的列表很长,其中有许多命令都会接受各种各样的选项。
我们所提及的命令反映了常用 Linux 命令(例如 ps
和 lsof
)的功能。要使用调试程序找出确切的事件顺序,需要了解 GDB 的用法并具备强大的调试技能。这些知识超出了本文档的说明范围。此外,您需要了解 Linux 内核。本文档的末尾提供了多个有用的参考信息来源。
17.9 Kdump 高级配置 #
Kdump 的配置储存在 /etc/sysconfig/kdump
中。您也可以使用 YaST 来配置 Kdump。Kdump 配置选项在 中的 › 下提供。以下 Kdump 选项可能对您有用。
可以使用 KDUMP_SAVEDIR
选项更改内核转储的目录。请注意,内核转储大小可能会非常大。如果减去预估转储大小后的可用磁盘空间低于 KDUMP_FREE_DISK_SIZE
选项指定的值,Kdump 将拒绝保存转储。请注意,KDUMP_SAVEDIR
可识别 URL 格式 PROTOCOL://SPECIFICATION,其中 PROTOCOL 可为 file
、ftp
、sftp
、nfs
或 cifs
,specification
根据协议而定。例如,要在 FTP 服务器上保存内核转储,请使用以下 URL 作为模板:ftp://username:password@ftp.example.com:123/var/crash
。
内核转储通常是巨大的,包含许多分析所不需要的页。使用 KDUMP_DUMPLEVEL
选项可以省略此类页。该选项可接受 0 到 31 之间的数字值。如果指定 0,转储大小是最大的。如果指定 31,将生成最小的转储。有关可能值的完整表格,请参见 kdump
的手册页 (man 7 kdump
)。
有时,保持较小的内核转储大小会很有帮助。例如,如果您要通过网络传送转储,或者需要在转储目录中节省一些磁盘空间,可以采用这种做法。为此,可将 KDUMP_DUMPFORMAT
设置为 compressed
。crash
实用程序支持对压缩的转储进行动态解压缩。
对 /etc/sysconfig/kdump
进行手动更改后,始终需要执行 systemctl restart kdump
。否则,要到下一次重引导系统时这些更改才会生效。
17.10 更多信息 #
并没有一篇介绍 Kexec 和 Kdump 用法的综合性参考文档。但是,下面这些有用资源可帮助您了解某些特定方面:
有关 Kexec 实用程序的用法,请参见
kexec
的手册页 (man 8 kexec
)。IBM 在 http://www.ibm.com/developerworks/linux/linux390/development_documentation.html 上提供了有关如何在 IBM Z 体系结构中使用转储工具的综合性文档。
您可以在 http://www.ibm.com/developerworks/linux/library/l-kexec.html 上找到有关 Kexec 的一般信息。这些信息可能有点过时。
有关专用于 SUSE Linux Enterprise Server 的 Kdump 的更多细节,请参见 http://ftp.suse.com/pub/people/tiwai/kdump-training/kdump-training.pdf。
您可以在 http://lse.sourceforge.net/kdump/documentation/ols2oo5-kdump-paper.pdf 上找到 Kdump 内部结构的深入说明。
有关 crash
转储分析和调试工具的更多细节,请使用以下资源:
除 GDB 的信息页 (
info gdb
) 外,http://sourceware.org/gdb/documentation/ 上还提供了可打印的指南。crash 实用程序还提供有综合性的联机帮助。使用
help
COMMAND 可以显示command
的联机帮助。如果您具备所需的 Perl 技能,可以使用 Alicia 来简化调试。您可以在 http://alicia.sourceforge.net/ 上找到 crash 实用程序的此基于 Perl 的前端。
如果偏好使用 Python,则应安装 Pykdump。此软件包能够帮助您通过 Python 脚本控制 GDB,可从 http://sf.net/projects/pykdump 下载。
由 Daniel P. Bovet 和 Marco Cesati 发布的《Understanding the Linux Kernel》(了解 Linux 内核)(ISBN 978-0-596-00565-8) 中非常全面地概述了 Linux 内核的内部结构。