通过电子邮件监控 systemd 日志

通过 journal-brief 获取每日电子邮件,其中包含来自您的 systemd 日志的值得注意的输出。
95 位读者喜欢这篇文章。
Note taking hand writing

Nguyen Nguyen,通过 Pexels CC0。

现代 Linux 系统通常使用 systemd 作为其 init 系统和作业以及许多其他功能的管理器。由 systemd 管理的服务通常将其输出(所有形式:警告、错误、信息性消息等)发送到 systemd 日志,而不是像 syslog 这样的传统日志系统。

除了服务之外,Linux 系统通常还有许多计划作业(传统上称为 cron 作业,即使系统不使用 cron 来运行它们),这些作业可能会将其输出发送到日志系统,或者允许作业调度程序捕获输出并通过电子邮件传递它。

在管理多个系统时,您可以安装和配置集中式日志捕获系统来监控它们的行为,但是集中式系统的复杂性会使它们难以管理。

一个更简单的解决方案是让每个系统直接通过电子邮件将“有趣的”输出发送给管理员。对于使用 systemd 的系统,可以使用 Tim Waugh 的 journal-brief 工具来完成。当我最近发现这个工具时,它几乎满足了我的需求,因此,以典型的开源方式,我贡献了各种补丁来为该项目添加电子邮件支持。Tim 与我合作将它们合并,现在我可以尽可能简单地使用该工具来监控我管理的 20 多个系统。

现在,每天清晨,我会收到 20 到 23 封电子邮件:其中大多数包含每个机器的整个 systemd 日志的过滤视图(包含警告或更严重的消息),但少数是由我用于备份的计划 ZFS 快照复制作业生成的日志。在本文中,我将向您展示如何设置类似的消息。

安装 journal-brief

尽管 journal-brief 在许多 Linux 软件包存储库中都可用,但打包版本将不包含电子邮件支持,因为这是最近才添加的。这意味着您需要从 PyPI 安装它;我将向您展示如何手动将其安装到 Python 虚拟环境中,以避免干扰已安装系统的其他部分。如果您有喜欢的工具来执行此操作,请随时使用它。

选择虚拟环境的位置;在本文中,为简单起见,我将使用 /opt/journal-brief

本教程中几乎所有命令都必须以 root 权限或等效权限执行(以 # 提示符表示)。但是,可以将软件安装在用户拥有的目录中,授予该用户从日志读取的权限,并将必要的单元作为 systemd user 单元安装,但这不在本文的讨论范围之内。

执行以下命令以创建虚拟环境并安装 journal-brief 及其依赖项

$ python3 -m venv /opt/journal-brief
$ source /opt/journal-brief/bin/activate
$ pip install ‘journal-brief>=1.1.7’
$ deactivate

按照顺序,这些命令将

  1. 创建 /opt/journal-brief 并在其中设置 Python 3.x 虚拟环境
  2. 激活虚拟环境,以便后续的 Python 命令将使用它
  3. 安装 journal-brief;请注意,单引号是必要的,以防止 shell 将 > 字符解释为重定向
  4. 停用虚拟环境,将 shell 返回到原始 Python 安装

此外,创建一些目录来存储 journal-brief 配置和状态文件,命令如下

$ mkdir /etc/journal-brief
$ mkdir /var/lib/journal-brief

配置电子邮件要求

虽然配置电子邮件客户端和服务器不在本文的讨论范围之内,但为了让 journal-brief 传递电子邮件,您需要配置并运行两种受支持的机制之一。

选项 1:mail 命令

许多系统都有一个 mail 命令,可以用来发送(和读取)电子邮件。如果您的系统上安装了这样的命令,您可以通过执行如下命令来验证它是否配置正确

$ echo "Message body" | mail --subject="Test message" {your email address here}

如果邮件到达您的邮箱,您就可以继续在 journal-brief 中使用这种类型的邮件传递。如果不是,您可以排查并纠正配置,或者使用 SMTP 传递。

要使用 mail 命令方法控制生成的电子邮件消息的属性(例如,“发件人”地址、“收件人”地址、“主题”),您必须在系统的邮件程序中使用命令行选项:journal-brief 只会构建消息正文并将其管道传输到邮件程序。

选项 2:SMTP 传递

如果您有一个可用的 SMTP 服务器,可以接受电子邮件并将其转发到您的邮箱,则 journal-brief 可以直接与其通信。除了纯 SMTP 之外,journal-brief 还支持传输层安全 (TLS) 连接和身份验证,这意味着它可以与许多托管电子邮件服务(如 Fastmail、Gmail、Pobox 等)一起使用。您需要获取一些信息来配置此传递模式

  • SMTP 服务器主机名
  • 用于消息提交的端口号(默认为端口 25,但常用端口 587)
  • TLS 支持(可选或必需)
  • 身份验证信息(用户名和密码/令牌,如果需要)

当使用此传递模式时,journal-brief 将在提交到 SMTP 服务器之前构建整个消息,因此“发件人”地址、“收件人”地址和“主题”将在 journal-brief 的配置中提供。

设置配置和游标文件

Journal-brief 使用 YAML 格式的配置文件;它为每种所需的过滤参数、传递选项和输出格式组合使用一个文件。对于本文,这些文件存储在 /etc/journal-brief 中,但您可以将它们存储在您喜欢的任何位置。

除了配置文件之外,journal-brief 还创建和管理游标文件,这使其能够跟踪其输出中的最后一条消息。为每个配置文件使用一个游标文件可确保不会丢失任何日志消息,这与基于时间的日志传递系统形成对比,后者可能会在计划的传递作业无法完成运行时错过消息。对于本文,游标文件将存储在 /var/lib/journal-brief 中(您可以将游标文件存储在您喜欢的任何位置,但请确保不要将它们存储在任何类型的临时文件系统中,否则它们将会丢失)。

最后,journal-brief 具有广泛的过滤和格式化功能;我将仅描述最基本的选项,您可以在 journal-brief 和 systemd.journal-fields 的文档中了解有关其功能的更多信息。

配置每日电子邮件,其中包含有趣的日志条目

此示例将设置每日电子邮件,从名为 storage 的服务器发送给名为 Robin 的系统管理员,地址为 robin@domain.invalid。Robin 的邮件提供商通过名为 mail.server.invalid 的服务器上的端口 587 提供 SMTP 消息提交,但不需要身份验证或 TLS。电子邮件将从 storage-server@domain.invalid 发送,以便 Robin 可以轻松地过滤收到的消息或从中生成警报。

Robin 很幸运地住在斐济,那里的工作日开始时间相当晚(大约上午 10:00),因此每天早上都有充足的时间阅读有趣的日志条目的电子邮件。此示例将在当地时区(太平洋/斐济)上午 8:30 收集条目并传递它们。

步骤 1:配置 journal-brief

/etc/journal-brief/daily-journal-email.yml 创建一个文本文件,内容如下

cursor-file: '/var/lib/journal-brief/daily-journal-email'
output:
  - 'short'
  - ‘systemd’
inclusions:
  - PRIORITY: 'warning'
email:
  suppress_empty: false
  smtp:
    to: '”Robin” <robin@domain.invalid>'
    from: '"Storage Server" <storage-server@domain.invalid>'
    subject: 'daily journal'
    host: 'mail.server.invalid'
    port: 587

此配置使 journal-brief 执行以下操作

  • 将游标存储在配置为 cursor-file 的路径
  • 使用 short 格式(每条条目一行)格式化日志条目,并提供任何处于 failed 状态的 systemd 单元的列表
  • 包含来自任何服务单元(甚至是 Linux 内核)的优先级为 warningerroremergency 的日志条目
  • 即使没有匹配的日志条目也发送电子邮件,以便 Robin 可以确保存储服务器仍在运行并且具有连接
  • 使用 SMTP 发送电子邮件

您可以通过执行 journal-brief 命令来测试此配置文件

$ journal-brief --conf /etc/journal-brief/daily-journal-email

Journal-brief 将扫描 systemd 日志中的所有新消息(是的,所有它以前从未见过的消息),识别任何与优先级过滤器匹配的消息,并将它们格式化为发送给 Robin 的电子邮件。如果存储服务器已经运行了数月(或数年),并且 systemd 日志从未被清除,这可能会产生非常大的电子邮件消息。除了 Robin 不喜欢如此大的消息之外,Robin 的电子邮件提供商可能也不愿意接受它,因此您可以通过执行以下命令生成较短的消息

$ journal-brief -b --conf /etc/journal-brief/daily-journal-email

添加 -b 参数告诉 journal-brief 仅检查最近一次系统启动以来的 systemd 日志条目,并忽略任何较旧的条目。

在 journal-brief 将电子邮件发送到 SMTP 服务器后,它会在游标文件中写入一个字符串,以便下次使用相同的游标文件运行时,它将知道从日志中的哪个位置开始。如果该过程由于任何原因(例如,日志条目收集、条目格式化或 SMTP 传递)失败,则游标文件将不会更新,这意味着下次使用游标文件时,原本应该包含在失败的电子邮件中的条目将包含在下一封电子邮件中。

步骤 2:设置 systemd 服务单元

/etc/systemd/system/daily-journal-email.service 创建一个文本文件,内容如下

[Unit]
Description=Send daily journal report

[Service]
ExecStart=/opt/journal-brief/bin/journal-brief --conf /etc/journal-brief/%N.yml
Type=oneshot

此服务单元将运行 journal-brief 并指定一个配置文件,该配置文件的名称与单元文件的名称相同,并删除了后缀,这是 %N 提供的。由于此服务将由计时器启动(请参阅步骤 3),因此无需启用或手动启动它。

步骤 3:设置 systemd 计时器单元

/etc/systemd/system/daily-journal-email.timer 创建一个文本文件,内容如下

[Unit]
Description=Trigger daily journal email report

[Timer]
OnCalendar=*-*-* 08:30:00 Pacific/Fiji

[Install]
WantedBy=multi-user.target

此计时器将在太平洋/斐济时区的每天上午 8:30 启动 daily-journal-email 服务单元(因为它的名称与计时器名称匹配)。如果未指定时区,则计时器将在 storage 服务器上配置的系统时区的上午 8:30 触发服务。

为了使此计时器在每次系统启动时都启动,它被 WantedBy 多用户目标。要启用并启动计时器

$ systemctl enable daily-journal-email.timer
$ systemctl start daily-journal-email.timer
$ systemctl list-timers daily-journal-email.timer

最后一个命令将显示计时器的状态,NEXT 列将指示计时器下次启动服务的时间。

要了解有关 systemd 计时器以及为其构建计划的更多信息,请阅读 使用 systemd 计时器代替 cronjobs

现在配置已完成,Robin 将收到每日电子邮件,其中包含有趣的日志条目。

监控特定服务的输出

storage 服务器在固态存储设备 (SSD) 上有一些文件系统,并运行 Fedora Linux。Fedora 有一个 fstrim 服务,计划每周运行一次(使用 systemd 计时器,如上面的示例所示)。Robin 希望看到此服务生成的输出,即使它没有生成任何警告或错误。虽然此输出将包含在每日日志电子邮件中,但它将与其他日志条目混合在一起,Robin 更希望将输出放在自己的电子邮件消息中。

步骤 1:配置 journal-brief

/etc/journal-brief/fstrim.yml 创建一个文本文件,内容如下

cursor-file: '/var/lib/journal-brief/fstrim'
output: 'short'
inclusions:
  - _SYSTEMD_UNIT:
    - ‘fstrim.service’
email:
  suppress_empty: false
  smtp:
    to: '”Robin” <robin@domain.invalid>'
    from: '"Storage Server" <storage-server@domain.invalid>'
    subject: 'weekly fstrim'
    host: 'mail.server.invalid'
    port: 587

此配置与之前的示例类似,不同之处在于它将包含与名为 fstrim.service 的 systemd 单元相关的所有条目,无论其优先级级别如何,并且将包含与该服务相关的条目。

步骤 2:修改 systemd 服务单元

与之前的示例不同,您不需要创建 systemd 服务单元或计时器,因为它们已经存在。相反,您希望使用 systemd “drop-in 文件”机制(以避免修改系统提供的单元文件)向现有服务单元添加行为。

首先,确保 EDITOR 环境变量设置为您首选的文本编辑器(否则您将获得系统上的默认编辑器),并执行

$ systemctl edit fstrim.service

请注意,这不会编辑现有的服务单元文件;相反,它会打开一个编辑器会话来创建一个 drop-in 文件(位于 /etc/systemd/system/fstrim.service.d/override.conf)。

将以下内容粘贴到编辑器中并保存文件

[Service]
ExecStopPost=/opt/journal-brief/bin/journal-brief --conf /etc/journal-brief/%N.yml

退出编辑器后,systemd 配置将自动重新加载(这是使用 systemctl edit 而不是直接创建文件的好处之一)。与之前的示例一样,此 drop-in 使用 %N 来避免重复服务名称;这意味着 drop-in 内容可以应用于系统上的任何服务,只要在 /etc/journal-brief 中创建了相应的配置文件。

使用 ExecStopPost 将使 journal-brief 在任何尝试运行 fstrim.service 之后运行,无论它是否成功。这非常有用,因为即使 fstrim.service 无法启动(例如,如果缺少 fstrim 命令或不可执行),也会生成电子邮件。

请注意,此技术主要适用于在退出之前运行完成的 systemd 服务(换句话说,不是后台或守护进程)。如果服务单元文件的 Service 部分中的 Typeforking,则 journal-brief 将在指定服务停止后(手动或通过系统目标更改,如关机)才会执行。

配置完成;Robin 将在每次尝试启动 fstrim 服务后收到一封电子邮件;如果尝试成功,则电子邮件将包含服务生成的输出。

无需额外努力即可监控

通过这种设置,您可以监控使用 systemd 的 Linux 系统的健康状况,而无需设置任何集中式监控或日志记录工具。我发现这种监控方法非常有效,因为它使我注意到我维护的服务器上的异常事件,而无需付出任何额外的努力。

特别感谢 Tim Waugh 创建了 journal-brief 工具,并愿意接受一个相当大的补丁来添加直接电子邮件支持,而不是通过 cron 运行 journal-brief。

接下来阅读什么

学习爱上 systemd

systemd 是所有进程之母,负责将 Linux 主机启动到可以进行高效工作的状态。

(通讯员)
2020 年 4 月 16 日
User profile image.
Kevin P. Fleming 拥有 25 年以上的编程经验,精通每种主要的编程语言。行业经验包括传统的客户端/服务器数据库应用程序、开源消息传递和网络以及大型机操作系统。Kevin 的主要技能是通过问题分析和解决方案设计,生成有效利用资源的解决方案。

2 条评论

非常有趣且有用的工具,我想知道在 # 评论中是否有配置文件示例。

我不确定我是否理解您的问题;journal-brief 的安装不会安装任何配置文件,因此没有地方包含任何示例。示例在 GitHub 存储库的文档中提供(以及在 pypi.org 上的项目页面上)。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.