3.4. 调试崩溃应用程序
有时,无法直接调试应用。在这些情况下,您可以在应用程序终止时收集有关应用程序的信息,然后对其进行分析。
3.4.1. 内核转储:它们是什么以及如何使用它们 复制链接链接已复制到粘贴板!
在应用程序停止工作时,核心转储是部分应用程序内存的副本,以 ELF 格式存储。它包含应用的所有内部变量和堆栈,可以检查应用的最终状态。使用相应的可执行文件和调试信息进行增强时,可以使用调试器以类似于分析正在运行的程序的方式分析核心转储文件。
如果启用了此功能,Linux 操作系统内核会自动记录内核转储。或者,您可以向任何正在运行的应用发送信号,以生成核心转储,而不考虑其实际状态。
某些限制可能会影响生成内核转储的功能。查看当前的限制:
ulimit -a
$ ulimit -a
3.4.2. 使用内核转储记录应用程序崩溃 复制链接链接已复制到粘贴板!
要记录应用程序崩溃,请设置核心转储保存并添加系统信息。
流程
要启用内核转储,请确保
/etc/systemd/system.conf文件包含以下行:DumpCore=yes DefaultLimitCORE=infinity
DumpCore=yes DefaultLimitCORE=infinityCopy to Clipboard Copied! Toggle word wrap Toggle overflow 您还可以添加注释,描述之前是否存在这些设置以及之前的值。如果需要,这将允许您稍后撤销这些更改。注释是以
#字符开头的行。更改文件需要管理员级别访问权限。
应用新配置:
systemctl daemon-reexec
# systemctl daemon-reexecCopy to Clipboard Copied! Toggle word wrap Toggle overflow 删除内核转储大小的限制:
ulimit -c unlimited
$ ulimit -c unlimitedCopy to Clipboard Copied! Toggle word wrap Toggle overflow 若要反转这一更改,可运行值为
0的 命令,而不运行无限值。安装
sos软件包,它提供用于收集系统信息的sosreport工具:yum install sos
# yum install sosCopy to Clipboard Copied! Toggle word wrap Toggle overflow -
当应用程序崩溃时,会生成核心转储并由
systemd-coredump进行处理。 创建 SOS 报告以提供有关系统的更多信息:
sosreport
# sosreportCopy to Clipboard Copied! Toggle word wrap Toggle overflow 这将创建一个包含您系统信息的
.tar存档,如配置文件的副本。找到内核转储:
coredumpctl list executable-name
$ coredumpctl list executable-nameCopy to Clipboard Copied! Toggle word wrap Toggle overflow 导出内核转储:
coredumpctl dump executable-name > /path/to/file-for-export
$ coredumpctl dump executable-name > /path/to/file-for-exportCopy to Clipboard Copied! Toggle word wrap Toggle overflow 如果应用多次崩溃,第一个命令的输出会列出更多捕获的核心转储。在这种情况下,使用其他信息为第二个命令构建更精确的查询。详情请查看 coredumpctl(1) 手册页。
将核心转储和 SOS 报告传送到要进行调试的计算机。如果已知,也传输可执行文件。
重要当可执行文件未知时,core 文件的后续分析会识别该文件。
- 可选:传输后删除核心转储和 SOS 报告,以释放磁盘空间。
3.4.3. 使用内核转储检查应用程序崩溃状态 复制链接链接已复制到粘贴板!
先决条件
- 您必须从发生崩溃的系统中有一个核心转储文件和 sosreport。
- 在您的系统上必须安装 GDB 和 elfutils。
流程
要识别发生崩溃的可执行文件,请使用核心转储文件运行
eu-unstrip命令:eu-unstrip -n --core=./core.9814
$ eu-unstrip -n --core=./core.9814Copy to Clipboard Copied! Toggle word wrap Toggle overflow 0x400000+0x207000 2818b2009547f780a5639c904cded443e564973e@0x400284 /usr/bin/sleep /usr/lib/debug/bin/sleep.debug [exe] 0x7fff26fff000+0x1000 1e2a683b7d877576970e4275d41a6aaec280795e@0x7fff26fff340 . - linux-vdso.so.1 0x35e7e00000+0x3b6000 374add1ead31ccb449779bc7ee7877de3377e5ad@0x35e7e00280 /usr/lib64/libc-2.14.90.so /usr/lib/debug/lib64/libc-2.14.90.so.debug libc.so.6 0x35e7a00000+0x224000 3ed9e61c2b7e707ce244816335776afa2ad0307d@0x35e7a001d8 /usr/lib64/ld-2.14.90.so /usr/lib/debug/lib64/ld-2.14.90.so.debug ld-linux-x86-64.so.2
0x400000+0x207000 2818b2009547f780a5639c904cded443e564973e@0x400284 /usr/bin/sleep /usr/lib/debug/bin/sleep.debug [exe] 0x7fff26fff000+0x1000 1e2a683b7d877576970e4275d41a6aaec280795e@0x7fff26fff340 . - linux-vdso.so.1 0x35e7e00000+0x3b6000 374add1ead31ccb449779bc7ee7877de3377e5ad@0x35e7e00280 /usr/lib64/libc-2.14.90.so /usr/lib/debug/lib64/libc-2.14.90.so.debug libc.so.6 0x35e7a00000+0x224000 3ed9e61c2b7e707ce244816335776afa2ad0307d@0x35e7a001d8 /usr/lib64/ld-2.14.90.so /usr/lib/debug/lib64/ld-2.14.90.so.debug ld-linux-x86-64.so.2Copy to Clipboard Copied! Toggle word wrap Toggle overflow 输出中包含一行中各个模块的详细信息,用空格分隔。此信息按以下顺序列出:
- 映射模块的内存地址
- 模块的 build-id 及其在内存中的位置
-
模块的可执行文件名称,如果未从文件加载为
- 时显示为 -when unknown 或 等。 -
调试信息源(如果可用时显示为文件名),如
包含在可执行文件本身中,或(如果根本不存在) -
主模块的共享库名称(soname)或
[exe]
在本例中,重要的详细信息是文件名
/usr/bin/sleep和 build-id2818b2009547f780a5639c904cded443e564973eon the text[exe]。使用此信息,您可以识别分析核心转储所需的可执行文件。获取崩溃的可执行文件。
- 如果可能,请从发生崩溃的系统中复制它。使用从 core 文件提取的文件名。
您也可以在系统上使用相同的可执行文件。在 Red Hat Enterprise Linux 上构建的每个可执行文件都包含带有唯一 build-id 值的备注。确定相关的本地可用可执行文件的 build-id:
eu-readelf -n executable_file
$ eu-readelf -n executable_fileCopy to Clipboard Copied! Toggle word wrap Toggle overflow 使用此信息将远程系统上的可执行文件与您的本地副本匹配。内核转储中列出的本地文件和 build-id 的 build-id 必须匹配。
-
最后,如果应用程序是从 RPM 软件包安装的,您可以从 软件包中获取可执行文件。使用
sosreport输出来查找所需软件包的确切版本。
- 获取由可执行文件使用的共享库。将与 相同的步骤用于 可执行文件。
- 如果应用程序以软件包形式分发,请在 GDB 中加载可执行文件,以显示缺少 debuginfo 软件包的提示。如需了解更多详细信息,请参阅 第 3.1.4 节 “使用 GDB 获取应用程序或库的 debuginfo 软件包”。
要详细检查核心文件,使用 GDB 加载可执行文件和核心转储文件:
gdb -e executable_file -c core_file
$ gdb -e executable_file -c core_fileCopy to Clipboard Copied! Toggle word wrap Toggle overflow 有关缺少文件和调试信息的更多消息可帮助您确定调试会话中缺少的内容。如果需要,返回到上一步骤。
如果应用的调试信息可作为文件而不是软件包提供,请使用 symbolic
-file命令加载这个文件到 GDB 中:(gdb) symbol-file program.debug
(gdb) symbol-file program.debugCopy to Clipboard Copied! Toggle word wrap Toggle overflow 使用实际文件名替换 program.debug。
注意可能不需要为核心转储中包含的所有可执行文件安装调试信息。这些可执行文件的大部分是应用代码使用的库。这些库可能不会直接导致您要分析的问题,您不需要为它们包含调试信息。
在应用崩溃时,使用 GDB 命令检查应用的状态。请参阅使用 GDB 检查应用内部状态。
注意分析核心文件时,GDB 未附加到正在运行的进程。控制执行的命令无效。
其他资源
- 使用 GDB 进行调试 - 2.1.1 Choosing Files
- 使用 GDB 进行调试 - 18.1 Commands to Specify Files
- 使用 GDB 进行调试 - 18.3 Debugging Information in Separate Files
3.4.4. 使用 coredumpctl 创建和访问内核转储 复制链接链接已复制到粘贴板!
systemd 的 coredumpctl 工具可显著简化崩溃机器中使用内核转储的工作。此流程概述了如何捕获未响应进程的内核转储。
先决条件
系统必须配置为使用
systemd-coredump 进行内核转储处理。验证这是正确的:sysctl kernel.core_pattern
$ sysctl kernel.core_patternCopy to Clipboard Copied! Toggle word wrap Toggle overflow 如果输出以以下内容开始,则配置是正确的:
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump
kernel.core_pattern = |/usr/lib/systemd/systemd-coredumpCopy to Clipboard Copied! Toggle word wrap Toggle overflow
流程
根据可执行文件名称的已知部分,查找挂起进程的 PID:
pgrep -a executable-name-fragment
$ pgrep -a executable-name-fragmentCopy to Clipboard Copied! Toggle word wrap Toggle overflow 此命令将以以下形式输出一行:
PID command-line
PID command-lineCopy to Clipboard Copied! Toggle word wrap Toggle overflow 使用 命令行 值验证 PID 是否属于预期进程。
例如:
pgrep -a bc
$ pgrep -a bcCopy to Clipboard Copied! Toggle word wrap Toggle overflow 5459 bc
5459 bcCopy to Clipboard Copied! Toggle word wrap Toggle overflow 向进程发送中止信号:
kill -ABRT PID
# kill -ABRT PIDCopy to Clipboard Copied! Toggle word wrap Toggle overflow 验证内核是否已由
coredumpctl捕获:coredumpctl list PID
$ coredumpctl list PIDCopy to Clipboard Copied! Toggle word wrap Toggle overflow 例如:
coredumpctl list 5459
$ coredumpctl list 5459Copy to Clipboard Copied! Toggle word wrap Toggle overflow TIME PID UID GID SIG COREFILE EXE Thu 2019-11-07 15:14:46 CET 5459 1000 1000 6 present /usr/bin/bc
TIME PID UID GID SIG COREFILE EXE Thu 2019-11-07 15:14:46 CET 5459 1000 1000 6 present /usr/bin/bcCopy to Clipboard Copied! Toggle word wrap Toggle overflow 根据需要进一步检查或使用 core 文件。
您可以根据 PID 和其他值指定内核转储。详情请查看 coredumpctl(1) 手册页。
显示核心文件的详细信息:
coredumpctl info PID
$ coredumpctl info PIDCopy to Clipboard Copied! Toggle word wrap Toggle overflow 加载 GDB 调试器中的核心文件:
coredumpctl debug PID
$ coredumpctl debug PIDCopy to Clipboard Copied! Toggle word wrap Toggle overflow 根据调试信息的可用性,GDB 将建议运行的命令,例如:
Missing separate debuginfos, use: dnf debuginfo-install bc-1.07.1-5.el8.x86_64
Missing separate debuginfos, use: dnf debuginfo-install bc-1.07.1-5.el8.x86_64Copy to Clipboard Copied! Toggle word wrap Toggle overflow 有关此过程的详情,请参考 第 3.1.4 节 “使用 GDB 获取应用程序或库的 debuginfo 软件包”。
导出核心文件以便在其他位置进行进一步处理:
coredumpctl dump PID > /path/to/file_for_export
$ coredumpctl dump PID > /path/to/file_for_exportCopy to Clipboard Copied! Toggle word wrap Toggle overflow 使用您要放置内核转储的文件替换 /path/to/file_for_export。
3.4.5. 使用 gcore转储进程内存 复制链接链接已复制到粘贴板!
内核转储调试的工作流允许分析程序的状态离线。在某些情况下,您可以将此工作流用于仍在运行的程序,例如难以通过 进程访问环境。您可以使用 gcore 命令转储仍在运行的任何进程的内存。
流程
查找进程 id(pid)。使用
ps、pgrep 和top 等工具:ps -C some-program
$ ps -C some-programCopy to Clipboard Copied! Toggle word wrap Toggle overflow 转储这个过程的内存:
gcore -o filename pid
$ gcore -o filename pidCopy to Clipboard Copied! Toggle word wrap Toggle overflow 这会创建 文件名,并转储其中的进程内存。在内存被转储时,进程的执行将被停止。
- 内核转储完成后,进程会恢复正常执行。
创建 SOS 报告以提供有关系统的更多信息:
sosreport
# sosreportCopy to Clipboard Copied! Toggle word wrap Toggle overflow 这将创建一个 tar 存档,其中包含系统的相关信息,如配置文件副本。
- 将程序的可执行文件、核心转储和 SOS 报告传送到要进行调试的计算机。
- 可选:传输后删除核心转储和 SOS 报告,以释放磁盘空间。
3.4.6. 使用 GDB 转储受保护的进程内存 复制链接链接已复制到粘贴板!
您可以将进程内存标记为不转储。这样可以节省资源并在进程内存包含敏感数据时确保额外的安全性:例如,银行或记帐应用程序或整个虚拟机上。内核内核转储(kdump)和手动内核转储(gcore,GDB)都不会转储以这种方式标记的内存。
在某些情况下,您必须转储进程内存的所有内容,无论这些保护如何。此流程演示了如何使用 GDB 调试器执行此操作。
流程
将 GDB 设置为忽略
/proc/PID/coredump_filter文件中的设置:(gdb) set use-coredump-filter off
(gdb) set use-coredump-filter offCopy to Clipboard Copied! Toggle word wrap Toggle overflow 将 GDB 设置为忽略内存页面标记
VM_DONTDUMP:(gdb) set dump-excluded-mappings on
(gdb) set dump-excluded-mappings onCopy to Clipboard Copied! Toggle word wrap Toggle overflow 转储内存:
(gdb) gcore core-file
(gdb) gcore core-fileCopy to Clipboard Copied! Toggle word wrap Toggle overflow 使用您要转储内存的文件名称替换 core-file。