实例

通过电子邮件自动报告崩溃故障

此示例处理libreport的配置,以发送完整的崩溃报告,包括 backtrace 通过来自自治系统的电子邮件服务。我们通常在自动测试环境中遇到这样的系统。让我们配置ABRT向发送通知电子邮件 devel@lists.project.org .

libreport的默认配置已经支持向本地系统上的root用户发送通知电子邮件。此功能存储在 /etc/libreport/events.d/mailx_event.conf 包含以下定义的文件 notifynotify-dup 活动:

EVENT=notify
    # do not rely on the default config nor on the config file
    Mailx_Subject="[abrt] a crash has been detected" \
    Mailx_EmailFrom="ABRT Daemon <DoNotReply>" \
    Mailx_EmailTo="root@localhost" \
    reporter-mailx --notify-only

EVENT=notify-dup
    # do not rely on the default config nor on the config file
    Mailx_Subject="[abrt] a crash has been detected again" \
    Mailx_EmailFrom="ABRT Daemon <DoNotReply>" \
    Mailx_EmailTo="root@localhost" \
    reporter-mailx --notify-only

备注

subject、sender和recipient通过环境变量传递,因为 reporter-mailx 在其命令行参数中不支持这些选项,并且将其放入其配置文件将破坏常规报告工作流。

检测到的问题类型可根据可用性分为两组 backtrace 在被发现的时候。第一组由Python、kerneloops、Ruby和Java问题类型组成,其中 backtrace 在检测时可用。第二组包括CCpp(过程崩溃,C/Cpp),其中 backtrace 必须从转储文件中提取。

的默认配置 notify 事件几乎可用于在检测时具有回溯的问题类型。我们可以通过一些调整重用默认配置。我们需要更新收件人的地址并删除 --notify-only 字符串来自 reporter-mailx 的命令行参数 reporters-mailx 从问题数据的最小子集合成消息,以避免在本地系统上浪费太多磁盘空间,在本地系统中,所有排除的数据都很容易访问。我们还需要将libreport配置为不将其用于CCpp问题,因为我们将提供自己的事件定义。

默认值 notify-dup 事件几乎可用于所有问题类型,因为它是针对单个问题的连续事件运行的 (notify 事件在第一次出现时运行,应创建所有必需的数据)。我们只需要更新收件人的地址,因为 --notify-only 这个论点对我来说很有意义 notify-dup 事件。

既然我们要用 repoter-mailx 在一些地方,我们不想重复我们自己,我们首先将静态电子邮件首选项(发件人和收件人)移动到 /etc/libreport/plugins/mailx.conf

Subject = [abrt] a crash has been detected
EmailFrom = ABRT Daemon <DoNotReply>
EmailTo = devel@lists.project.org

更新后的默认配置行如下所示:

EVENT=notify analyzer!=CCpp
    # full notify e-mail
    Mailx_Subject="[abrt] a crash has been detected" \
    reporter-mailx

EVENT=notify-dup
    # full notify-dup e-mail
    Mailx_Subject="[abrt] a crash has been detected again" \
    reporter-mailx --notify-only

"analyzer!=CCpp" 告诉libreport仅当 analyzer 文件不等于 "CCpp" 字符串。

我们已经完成了默认配置,现在我们要定义 notify CCpp事件。为了能够生成完整的GDB回溯,我们需要所有相关的调试数据。在类似Fedora的系统上,ABRT可以通过从中提取构建id来提供所需的调试数据 coredump 文件和解包rpm包,提供从提取的构建id生成的路径。

CCpp notify 事件行如下:

EVENT=notify analyzer=CCpp
    # CCpp notify event sending e-mail with full gdb backtrace
    # extract build ids from coredump file and save them in 'build_ids' file
    abrt-action-analyze-core --core=coredump -o build_ids >>event_log 2>&1 &&
    # download and unpack rpm package for each id in 'build_ids' file
    abrt-action-install-debuginfo -y >>event_log 2>&1 &&
    # call gdb to generate backtrace with local variables, call arguments
    # disassembly, etc. and save it in 'backtrace' file
    abrt-action-generate-backtrace >>event_log 2>&1 &&
    # generate 'duphash', 'crash_function' and 'backtrace_rating'
    abrt-action-analyze-backtrace >>event_log 2>&1
    #
    # send e-mail
    Mailx_Subject="[abrt] a crash has been detected" \
    reporter-mailx

除了其他问题数据外,通知电子邮件还将包含 event_log (用于ABRT调试), backtrace_rating (基于分辨率和未分辨率帧比率的回溯质量度量值)和 duphash ABRT使用哪种方法来识别所有受支持的错误跟踪系统和所有机器(例如ABRT) "abrt_hash:$(cat duphash)" 字符串到Bugzilla错误报告的白板字段。)

提示1:

您可以添加 reporter-bugzilla -h $(cat duphash) >>bugzilla_bug_id 命令包含当前处理的崩溃的现有Bugzilla错误报告ID。这只适用于软呢帽。

提示2:

您可以使电子邮件的主题更具信息性。下面的脚本不是防弹的,但为C/Cpp问题生成了非常好的电子邮件主题:

Mailx_Subject="[abrt] $(cat package || cat executable): $(cat crash_function && echo "():") $(cat reason || (cat executable && echo " crashed"))"

从systemd coredumctl获取核心文件

默认情况下,ABRT通过注册的内核转储助手检测本地程序(C,C++)崩溃。 /proc/sys/kernel/core_pattern . 不幸的是,一次只能有一个core模式助手,因此ABRT core dump助手不能与之共存 systemd-coredumctl .

但是,可以关闭ABRT core dumper helper并关闭ABRT systemd-coredumpctl watcher可以用来通知ABRT本机程序的崩溃。

你所要做的就是禁用 abrt-ccpp.service 它取代了 core_pattern 通过配置 sysctl 与ABRT核心模式助手。如果服务正在运行,则 core_pattern 应该从 |/usr/libexec/abrt-hook-ccpp .

systemctl stop abrt-ccpp.service
systemctl disable abrt-ccpp.service

一旦你停止并禁用 abrt-ccpp.service , the core_pattern 变量应以开头 |/usr/lib/systemd/systemd-coredump . 如果没有,请检查文件 /usr/lib/sysctl.d/50-coredump.conf 存在并确保没有其他文件设置 kernel.core_pattern (见 man 5 sysctl.d

最后两件事你需要做的是启用和启动 abrt-journal-core.service .

systemctl enable abrt-journal-core.service
systemctl start abrt-journal-core.service

当前版本的 abrt-journal-core.service 需要复制数据,ABRT需要能够在bug跟踪工具中打开报告并离开 systemd-coredumpctl 数据未被触及。这意味着您不能使用ABRT日志核心服务来清理 systemd-coredumpctl 最终你会得到两份核心文件,一份在 systemd-coredumpctl 的子目录中 /var/spool/abrt/ .

为特定包的崩溃收集额外的日志文件

ABRT试图为维护人员提供尽可能多的信息。问题详细信息的好来源可以是日志文件。因此,一旦检测到崩溃的进程,ABRT就会遍历系统日志,并将看起来与崩溃进程相关的行复制到一个名为 var_log_messages 在问题目录中。可以在ABRT/libreport打开的bug报告中找到该文件。

但是,由于各种原因,应用程序可能不会选择登录到系统日志。在这种情况下,ABRT可以配置为将日志文件复制到问题数据目录,libreport会自动将它们附加到bug报告中。

假设我们有一个叫做 foo 我们要复制在用户数据库中创建的日志文件 /var/run/ 目录。应用程序运行多个并发进程,每个进程将调试消息写入自己的日志文件(由进程的PID表示)。

要获取这些日志文件,我们需要创建一个新的libreport事件配置文件,并指示ABRT在foo的可执行文件出现崩溃后运行它。默认情况下,ABRT运行 post-createnotifynotify-dup 新问题检测事件。我们不能使用 post-create 因为那时崩溃的可执行文件包可能还不知道。 notify-dup 不适合,因为执行事件是为了重新出现问题,因此应该已经捕获日志文件。因此,我们必须定义新的 notify 事件。

EVENT=notify pkg_name=foo
    # Copy log files of crashed process to foo.log
    cp /var/run/$(cat uid)/foo.$(cat pid).log foo.log

这个 pkg_name=foo 字符串告诉ABRT运行上面的行,查找 foo 包裹。您可以根据需要添加任意多的条件。第一行下面的行由 /bin/sh 当前工作目录包含ABRT捕获的所有问题数据。

代码必须放在 /etc/libreport/events.d/ 目录。包裹通常遵循 ${{package name}}_event.conf 这些文件的规则。

忽略旧版本ABRT中钩子级别的特定二进制文件

在ABRT版本2.1.11-36的RHEL7.3、版本2.0.8-37的RHEL6.8和ABRT版本2.8.1的Fedora中引入了忽略钩子级特定二进制文件的崩溃。期权 IgnoredPaths 在conf文件中 /etc/abrt/plugins/CCpp.conf .

即使在旧版本的ABRT中也可以忽略钩子级的崩溃吗?

是的,是的。你可以自己写 core_pattern 过滤/忽略二进制文件并作为abrt hook ccpp的包装器工作的脚本,abrt hook ccpp不能进行过滤。有关更多细节,请参阅内核文档 [1].

如何执行此操作的示例:

创建 core_pattern 脚本(例如 /etc/my_abrt_ccpp_hook.sh )包括以下内容:

#!/bin/bash

# kernel.core_pattern = |/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t %e
#                                                    $1 $2 $3 $4 $5 $6 $7
# You want to filter %e - executable filename (without path prefix), so parameter $7

# Is it the particular binary you want to ignore?
if [[ $7 == "EXECUTABLE_YOU_WANT_TO_IGNORE" ]]
then
    # Do what you want
else
    # In other cases use ABRT's hook in standard way
    cat /dev/stdin |/usr/libexec/abrt-hook-ccpp $1 $2 $3 $4 $5 $6 $7
fi

设置新的 kernel.core_pattern 使用 sysctl (基本上是改变 /usr/libexec/abrt-hook-ccpp/etc/my_abrt_ccpp_hook.sh ):

# sysctl kernel.core_pattern
kernel.core_pattern = |/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t %e
# sysctl kernel.core_pattern="|/etc/my_abrt_ccpp_hook.sh  %s %c %p %u %g %t %e"
kernel.core_pattern = |/etc/my_abrt_ccpp_hook.sh %s %c %p %u %g %t %e

是否可以忽略来自具有特定UID的程序的崩溃?

是的,是这样的。您可以在中修改文件 /etc/libreport/events.d/ 并将您自己的bash代码片段添加到其中。在事件中 post-create (例如,请参阅 /etc/libreport/events.d/python3_event.conf 对于Python 3崩溃或 /etc/libreport/events.d/ccpp_event.conf 对于C和C++崩溃),您可以访问 /proc/PID/status 崩溃的进程的文件。

C和C++程序中UID小于1000时过滤崩溃示例:~

打开 /etc/libreport/events.d/ccpp_event.conf 并将此代码段添加到 EVENT=post-create 部分:

# Parse Uid from  proc_pid_status
uid=`grep '^Uid:' proc_pid_status | sed 's/^Uid:[[:space:]]*\([0-9]*\).*/\1/'`

if [ 1000 -lt "$uid" ]; then
    # If Uid is less then 1000 abrt will remove the problem directory
    exit 1
fi