在 Linux 中配置和管理core dump

1. 概述

在本教程中,我们将了解如何管理和配置coredump。我们将研究kernel.core_pattern然后我们将继续使用coredumpctl

2. 简介

coredump是程序崩溃后由 Linux 内核自动生成的文件。该文件包含应用程序崩溃时的内存、寄存器值和调用堆栈

3. 使用信号生成coredump

在本节中,我们将学习如何终止程序并强制其生成coredump。为此,我们将使用kill命令,它使用信号来终止应用程序。这些信号会产生coredump。

举个例子,让我们使用sleep作为无限期运行的程序:

bash 复制代码
$ sleep 500
[1] 5464
$ kill -s SIGTRAP $(pgrep sleep)
[1]+  Trace/breakpoint trap (core dumped) sleep 500

我们可以看到"core dumped"的信息表明coredump成功 。我们还注意到"Trace/breakpoint trap"表示SIGTRAP信号

现在我们已经有了这个框架,让我们看看如何配置coredump。

4. 配置coredump

有两种方法可以配置coredump。一种是通过管道传递coredump,另一种是将其存储在文件中。

主要配置参数是kernel.core_pattern 。这适用于基于文件和基于管道的coredump。除了此配置参数之外,基于文件的转储还有大小限制。我们可以使用ulimit配置此大小。

我们将在以下部分中介绍这两种配置类型。

4.1. 将coredump重定向到管道

让我们看看如何配置我们的系统以通过管道生成coredump。首先,我们需要一个示例程序来从管道中提取coredump。之后,我们将配置内核以提供程序名称作为参数并将coredump提供给我们的程序。

让我们编写一个程序,如果崩溃进程处于睡眠状态,则该程序只会生成coredump:

python 复制代码
#!/usr/bin/python2.7
# Filename: /tmp/core_dump_example.py
import sys

# Expect sys.argv to have %e configured in kernel.core_pattern
process_filename = sys.argv[1]

if process_filename == "sleep":
    with open("/tmp/sleep_core_dump", "wb") as core_dump:
        core_contents = bytearray(sys.stdin.read())
        core_dump.write(core_contents)

在这里,我们注意到程序检查第一个参数,并且仅在包含sleep时输出coredump。让我们将其存储在/tmp/core_dump_example.py下并为其授予可执行权限。

现在,我们希望操作系统在生成coredump时调用我们的脚本。通过阅读core的手册页,我们可以通过 使用sysctl配置kernel.core_patttern 属性 来实现这一点:

ini 复制代码
$ sudo sysctl -w kernel.core_pattern="|/tmp/core_dump_example.py %e"

模式开头的管道指示操作系统应通过 stdin 将coredump的内容传递到我们的脚本。

注意末尾的%e 。%e_是一个扩展为崩溃应用程序的进程名称的模板。还有更多可用的模板,在核心手册页中进行了描述。

让我们尝试创建一个coredump:

bash 复制代码
$ sleep 500 &
[1] 8828
$ kill -s SIGTRAP $(pgrep sleep)
[1]+  Trace/breakpoint trap (core dumped) sleep 500

让我们检查一下使用 python 脚本创建的文件的签名:

yaml 复制代码
$ file /tmp/sleep_core_dump
/tmp/sleep_core_dump: ELF 64-bit LSB core file, x86-64, version 1 (SYSV), SVR4-style, from 'sleep 500', real uid: 1000, effective uid: 1000, real gid: 1000, effective gid: 1000, execfn: '/usr/bin/sleep', platform: 'x86_64'

通过使用coredump上的文件,我们可以立即看到崩溃的程序是*/usr/bin/sleep。它还向我们展示了其他信息,例如启动此进程的 UID。

4.2. 将coredump重定向到文件

接下来,让我们配置我们的系统以生成coredump文件。为此, 我们将_kernel.core_pattern_设置为我们所需的文件名使用核心手册页中的模板,我们可以修饰coredump文件名。

首先,让我们设置coredump文件名:

ini 复制代码
$ sudo sysctl -w kernel.core_pattern="/tmp/%e_core_dump.%p"

当_睡眠应用程序崩溃时,我们期望__/tmp_下出现一个具有_sleep_core_dump.pid_模式的文件。其中_%e_是程序名称,_%p_是程序的 PID。

请注意,我们可以给出文件名,而不是绝对路径。这将在崩溃进程的当前工作目录中创建一个coredump文件。

接下来,我们需要检查使用ulimit施加的任何限制。默认情况下,coredump文件有一个限制设置ulimit****设置的这些限制不会影响基于管道的coredump处理程序

coredump大小的单位是_块_。让我们看看每个块有多少字节:

shell 复制代码
$ stat -fc %s .
4096

使用_每块 4096 字节_,我们将限制设置为 5 MB,因为我们不希望示例生成大于 5 MB 的coredump。这可以计算为_nblocks =desired_limit / block_size_,其中desired_limit 和 block_size 均以字节为单位。5 MB 相当于 1280 个块 = (5 * 1024 * 1024) / 4096。

默认情况下,coredump的硬限制设置为_0_。要设置限制,我们必须将以下两行添加到_/etc/security/limits.conf_:

yaml 复制代码
baeldung_user hard core 1280
baeldung_user soft core 1280

硬限制是系统范围的限制,软限制是基于用户的限制。软限制应小于相应的硬限制。此后我们需要重新启动。

让我们检查一下重启后coredump文件的大小限制:

shell 复制代码
$ ulimit -c
1280

太好了,已经生效了。让我们尝试创建一个coredump:

bash 复制代码
$ sleep 500 &
[1] 9183
$ kill -s SIGTRAP $(pgrep sleep)
[1]+  Trace/breakpoint trap (core dumped) sleep 500
$ ls /tmp/*_core_*
-rw------- 1 user user 372K Jun 26 23:31 /tmp/sleep_core_dump.1780

我们已经创建了具有所需模式的coredump文件。

5. 为正在运行的进程生成coredump

有时,为正在运行的进程生成coredump可能很有用。GDB可以捕获正在运行的进程的coredump,但它还附带一个名为\gcore的实用程序。gcore是一个命令行实用程序,可以捕获正在运行的进程的coredump。

让我们尝试使用gcore捕获coredump:

bash 复制代码
$ sleep 500 &
[1] 3000
$ sudo gcore -o sleep 3000
0x00007f975eee630e in clock_nanosleep () from /lib/x86_64-linux-gnu/libc.so.6
warning: target file /proc/3000/cmdline contained unexpected null characters
warning: Memory read failed for corefile section, 4096 bytes at 0xffffffffff600000.
Saved corefile sleep.3000
[Inferior 1 (process 3000) detached]

我们可以看到,启动了一个 PID 为 3000 的_sleep进程。随后,gcore被启动并附加到sleep进程中。结果,gcore随后生成了sleep.3000的coredump文件并自行分离。当gcore与进程分离后,进程将愉快地继续运行而不受影响。

注意:gcore_需要sudo才能附加到进程。我们可以使用sysctl将kernel.yama.ptrace_scope设置为0。这将允许gcore附加到没有sudo 的进程。但是,请注意,应谨慎使用,因为这存在安全风险。任何进程都可以使用ptrace系统调用并检查任何程序内部。

6.coredumpctl_简介

在本节中,我们将介绍一个名为coredumpctl的实用程序。与手动配置coredump相反,coredumpctl自动管理coredump。coredumpctl记录coredump本身并维护崩溃历史记录。

在以下部分中,我们假设系统上已安装coredumpctl 。

6.1. 配置coredumpctl

coredumpctl附带一个名为systemd-coredump 的服务。这是一项获取coredump,然后对其进行处理以从中提取元数据的服务。然后它将这些信息存储在/var/lib/systemd/coredump/ 下。

我们可以通过检查kernel.core_pattern来检查是否配置了该服务:

perl 复制代码
$ sysctl -n kernel.core_pattern
|/lib/systemd/systemd-coredump %P %u %g %s %t 9223372036854775808 %h

我们已确认kernel.core_pattern_设置为使用_systemd-coredump 这告诉内核将与coredump相关的任何信息传递给systemd-coredump。

要尝试coredumpctl,我们首先需要生成一个新的coredump:

bash 复制代码
$ sleep 500 &
[1] 2826
$ kill -s SIGTRAP $(pgrep sleep)
[1]+  Trace/breakpoint trap (core dumped) sleep 500
$ coredumpctl
TIME                            PID   UID   GID SIG COREFILE  EXE
Sun 2020-06-28 18:52:59 BST    2826  1000  1000   5 present   /usr/bin/sleep

这真的很酷。通过尝试coredumpctl,我们可以看到我们有崩溃历史!

要提取特定崩溃的coredump文件,我们可以使用 PID、可执行文件的名称或崩溃时间。作为示例,让我们尝试使用 PID保存sleep的coredump:

yaml 复制代码
$ coredumpctl dump 2826 --output=core.dump
           PID: 2826 (sleep)
           UID: 1000 (user)
           ...
                Stack trace of thread 2826:
                #0  0x00007f7ec62f730e __GI___clock_nanosleep (libc.so.6 + 0xe030e)
                #1  0x00007f7ec62fceb7 __GI___nanosleep (libc.so.6 + 0xe5eb7)
           ...

除了coredump文件之外,我们还可以看到简短的摘要和堆栈跟踪。这来自systemd-coredump对coredump的预处理。

6.3. 使用coredumpctl运行调试会话

让我们看看如何使用_debug_命令启动调试会话:

vbnet 复制代码
$ coredumpctl debug 2826
...
Reading symbols from /usr/bin/sleep...
(No debugging symbols found in /usr/bin/sleep)
[New LWP 2959]
Core was generated by `sleep 500'.
Program terminated with signal SIGTRAP, Trace/breakpoint trap.
...
(gdb)

请注意gdb如何在加载coredump文件的情况下自动打开。

要检查崩溃情况,我们输入"disassemble"。结果,我们可以看到以下反汇编结果:

ini 复制代码
Dump of assembler code for function __GI___clock_nanosleep:
<__GI___clock_nanosleep+80>
   0x00007fb71b22c307 <+39>:    mov    eax,0xe6
   0x00007fb71b22c30c <+44>:    syscall
=> 0x00007fb71b22c30e <+46>:    mov    edx,eax

我们可以看到,有" mov Wax,0xe6"后面跟着一条系统调用指令。查看系统调用列表,似乎 230 (0xe6) 是clock_nanosleep 系统调用。这是捕获coredump的点。

七、结论

在本教程中,我们探讨了如何配置coredump。后来,我们探索了实用程序oredumpctl,它使管理coredump变得更加容易。

相关推荐
matlab的学徒17 小时前
Web与Nginx网站服务(改)
linux·运维·前端·nginx·tomcat
Insist75317 小时前
prometheus安装部署与alertmanager邮箱告警
linux·运维·grafana·prometheus
盖世英雄酱5813618 小时前
Read timed out问题 排查
java·数据库·后端
BAGAE18 小时前
MODBUS 通信协议详细介绍
linux·嵌入式硬件·物联网·硬件架构·iot·嵌入式实时数据库·rtdbs
灿烂阳光g18 小时前
SELinux 策略文件编写
android·linux
xqlily18 小时前
Linux操作系统之Ubuntu
linux·运维·ubuntu
BXCQ_xuan18 小时前
软件工程实践二:Spring Boot 知识回顾
java·spring boot·后端
阿部多瑞 ABU18 小时前
《基于国产Linux的机房终端安全重构方案》
linux·安全
o0o_-_18 小时前
【go/gopls/mcp】官方gopls内置mcp server使用
开发语言·后端·golang
苏三说技术19 小时前
为什么不建议在 Docker 中跑 MySQL?
后端