如何使用Journalctl查看和操作Systemd日志

来自菜鸟教程
跳转至:导航、​搜索

介绍

systemd 的一些最引人注目的优势在于进程和系统日志记录。 当使用其他工具时,日志通常分散在整个系统中,由不同的守护进程和进程处理,并且当它们跨越多个应用程序时可能相当难以解释。 systemd 试图通过提供一个集中管理解决方案来记录所有内核和用户态进程来解决这些问题。 收集和管理这些日志的系统称为 journal

日志是用 journald 守护进程实现的,它处理内核、initrd、服务等产生的所有消息。 在本指南中,我们将讨论如何使用 journalctl 实用程序,该实用程序可用于访问和操作日志中保存的数据。

大概的概念

systemd 日志背后的推动力之一是集中管理日志,无论消息来自何处。 由于大部分启动过程和服务管理由 systemd 进程处理,因此标准化收集和访问日志的方式是有意义的。 journald 守护程序从所有可用来源收集数据并将它们以二进制格式存储,以便于动态操作。

这给我们带来了许多显着的优势。 通过使用单个实用程序与数据交互,管理员能够根据需要动态显示日志数据。 这可以像查看三个引导前的引导数据一样简单,或者将来自两个相关服务的日志条目按顺序组合以调试通信问题。

以二进制格式存储日志数据还意味着数据可以根据您目前的需要以任意输出格式显示。 例如,对于日常日志管理,您可能习惯于以标准 syslog 格式查看日志,但如果您决定稍后绘制服务中断图表,则可以将每个条目输出为 JSON 对象以使其可使用到您的绘图服务。 由于数据不是以纯文本形式写入磁盘,因此当您需要不同的按需格式时无需进行转换。

systemd 日志可以与现有的 syslog 实现一起使用,也可以根据您的需要替换 syslog 功能。 虽然 systemd 日志将涵盖大多数管理员的日志记录需求,但它也可以补充现有的日志记录机制。 例如,您可能有一个集中的 syslog 服务器,用于编译来自多个服务器的数据,但您也可能希望将来自单个系统上多个服务的日志与 systemd 日志交错. 您可以通过结合这些技术来完成这两项工作。

设置系统时间

使用二进制日志进行日志记录的好处之一是能够以 UTC 或本地时间随意查看日志记录。 默认情况下,systemd 会以当地时间显示结果。

因此,在开始使用日志之前,我们将确保正确设置时区。 systemd 套件实际上带有一个名为 timedatectl 的工具,可以帮助解决这个问题。

首先,查看 list-timezones 选项可以使用哪些时区:

timedatectl list-timezones

这将列出您系统上可用的时区。 当您找到与您的服务器位置匹配的那个时,您可以使用 set-timezone 选项进行设置:

sudo timedatectl set-timezone zone

要确保您的机器现在使用正确的时间,请单独使用 timedatectl 命令,或使用 status 选项。 显示将是相同的:

timedatectl status
Output               Local time: Fri 2021-07-09 14:44:30 EDT
           Universal time: Fri 2021-07-09 18:44:30 UTC
                 RTC time: Fri 2021-07-09 18:44:31
                Time zone: America/New_York (EDT, -0400)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

第一行应该显示正确的时间。

基本日志查看

要查看 journald 守护程序收集的日志,请使用 journalctl 命令。

单独使用时,系统中的每个日记帐分录都将显示在一个寻呼机中(通常为 less)供您浏览。 最旧的条目将在顶部:

journalctl
Output-- Logs begin at Tue 2015-02-03 21:48:52 UTC, end at Tue 2015-02-03 22:29:38 UTC. --
Feb 03 21:48:52 localhost.localdomain systemd-journal[243]: Runtime journal is using 6.2M (max allowed 49.
Feb 03 21:48:52 localhost.localdomain systemd-journal[243]: Runtime journal is using 6.2M (max allowed 49.
Feb 03 21:48:52 localhost.localdomain systemd-journald[139]: Received SIGTERM from PID 1 (systemd).
Feb 03 21:48:52 localhost.localdomain kernel: audit: type=1404 audit(1423000132.274:2): enforcing=1 old_en
Feb 03 21:48:52 localhost.localdomain kernel: SELinux: 2048 avtab hash slots, 104131 rules.
Feb 03 21:48:52 localhost.localdomain kernel: SELinux: 2048 avtab hash slots, 104131 rules.
Feb 03 21:48:52 localhost.localdomain kernel: input: ImExPS/2 Generic Explorer Mouse as /devices/platform/
Feb 03 21:48:52 localhost.localdomain kernel: SELinux:  8 users, 102 roles, 4976 types, 294 bools, 1 sens,
Feb 03 21:48:52 localhost.localdomain kernel: SELinux:  83 classes, 104131 rules

. . .

如果 systemd 已在您的系统上存在很长时间,您可能会有页面和页面要滚动浏览,这些数据可能长达数万或数十万行。 这显示了日志数据库中有多少数据可用。

习惯于标准 syslog 日志记录的人会熟悉该格式。 然而,这实际上比传统的 syslog 实现从更多的来源收集数据。 它包括来自早期引导过程、内核、initrd 和应用程序标准错误的日志。 这些都可以在期刊中找到。

您可能会注意到显示的所有时间戳都是本地时间。 既然我们在系统上正确设置了本地时间,这对每个日志条目都可用。 使用此新信息显示所有日志。

如果要以 UTC 显示时间戳,可以使用 --utc 标志:

journalctl --utc

按时间筛选日志

虽然访问如此庞大的数据集合肯定是有用的,但如此大量的信息可能难以或不可能手动检查和处理。 正因为如此,journalctl 最重要的功能之一就是它的过滤选项。

显示当前引导的日志

您可能每天都使用的最基本的是 -b 标志。 这将向您显示自最近一次重新启动以来收集的所有日记条目。

journalctl -b

这将帮助您识别和管理与当前环境相关的信息。

如果您没有使用此功能并且显示超过一天的引导,您将看到 journalctl 插入了如下所示的行:每当系统出现故障时:

Output. . .

-- Reboot --

. . .

这可用于帮助您在逻辑上将信息分离到引导会话中。

过去的靴子

虽然您通常希望显示当前引导的信息,但有时过去的引导也会有所帮助。 该日志可以保存许多以前的引导信息,因此可以轻松地使journalctl显示信息。

一些发行版默认启用保存以前的引导信息,而另一些则禁用此功能。 要启用持久启动信息,您可以通过键入以下内容来创建目录来存储日志:

sudo mkdir -p /var/log/journal

或者您可以编辑日志配置文件:

sudo nano /etc/systemd/journald.conf

[Journal] 部分下,将 Storage= 选项设置为“persistent”以启用持久日志记录:

/etc/systemd/journald.conf

. . .
[Journal]
Storage=persistent

在您的服务器上启用保存以前的引导时,journalctl 会提供一些命令来帮助您将引导作为一个分割单元进行工作。 要查看 journald 知道的靴子,请将 --list-boots 选项与 journalctl 一起使用:

journalctl --list-boots
Output-2 caf0524a1d394ce0bdbcff75b94444fe Tue 2015-02-03 21:48:52 UTC—Tue 2015-02-03 22:17:00 UTC
-1 13883d180dc0420db0abcb5fa26d6198 Tue 2015-02-03 22:17:03 UTC—Tue 2015-02-03 22:19:08 UTC
 0 bed718b17a73415fade0e4e7f4bea609 Tue 2015-02-03 22:19:12 UTC—Tue 2015-02-03 23:01:01 UTC

这将为每次启动显示一行。 第一列是引导的偏移量,可用于通过 journalctl 轻松引用引导。 如果您需要绝对引用,则引导 ID 在第二列中。 您可以通过最后列出的两个时间规范来判断引导会话所指的时间。

要显示来自这些引导的信息,您可以使用第一列或第二列中的信息。

例如,要查看上次引导的日志,请使用带有 -b 标志的 -1 相对指针:

journalctl -b -1

您还可以使用引导 ID 从引导中回调数据:

journalctl -b caf0524a1d394ce0bdbcff75b94444fe

时间窗口

虽然通过引导查看日志条目非常有用,但您通常可能希望请求与系统引导不匹配的时间窗口。 在处理运行时间较长且正常运行时间较长的服务器时尤其如此。

您可以使用 --since--until 选项按任意时间限制进行过滤,它们分别将显示的条目限制为给定时间之后或之前的条目。

时间值可以有多种格式。 对于绝对时间值,您应该使用以下格式:

YYYY-MM-DD HH:MM:SS

例如,我们可以通过键入以下内容查看自 2015 年 1 月 10 日下午 5:15 以来的所有条目:

journalctl --since "2015-01-10 17:15:00"

如果上述格式的组件被忽略,将应用一些默认值。 例如,如果省略日期,则假定为当前日期。 如果缺少时间部分,将替换为“00:00:00”(午夜)。 秒字段也可以保留为默认为“00”:

journalctl --since "2015-01-10" --until "2015-01-11 03:00"

该杂志还了解一些相对值和命名的快捷方式。 例如,您可以使用“昨天”、“今天”、“明天”或“现在”等词。 您可以通过在编号值前加上“-”或“+”或在句子结构中使用“之前”等词来计算相对时间。

要获取昨天的数据,您可以键入:

journalctl --since yesterday

如果您收到从上午 9:00 开始并持续到一小时前的服务中断报告,您可以键入:

journalctl --since 09:00 --until "1 hour ago"

如您所见,定义灵活的时间窗口来过滤您希望查看的条目相对简单。

按消息兴趣过滤

上面,我们学习了一些使用时间限制过滤日志数据的方法。 在本节中,我们将讨论如何根据您感兴趣的服务或组件进行过滤。 systemd 期刊提供了多种方法来执行此操作。

按单位

也许最有用的过滤方式是按您感兴趣的单位。 我们可以使用 -u 选项来过滤这种方式。

例如,要查看我们系统上 Nginx 单元的所有日志,我们可以输入:

journalctl -u nginx.service

通常,您可能还希望按时间过滤以显示您感兴趣的行。 例如,要检查服务今天的运行情况,您可以键入:

journalctl -u nginx.service --since today

当您利用期刊交错来自不同单位的记录的能力时,这种类型的焦点会变得非常有用。 例如,如果您的 Nginx 进程连接到 PHP-FPM 单元以处理动态内容,您可以通过指定两个单元来按时间顺序合并两者的条目:

journalctl -u nginx.service -u php-fpm.service --since today

这可以更容易地发现不同程序和调试系统之间的交互,而不是单个进程。

按进程、用户或组 ID

一些服务会产生各种子进程来完成工作。 如果您已经找出了您感兴趣的进程的确切 PID,您也可以通过它进行过滤。

为此,我们可以通过指定 _PID 字段进行过滤。 例如,如果我们感兴趣的 PID 是 8088,我们可以输入:

journalctl _PID=8088

在其他时候,您可能希望显示从特定用户或组记录的所有条目。 这可以通过 _UID_GID 过滤器来完成。 例如,如果您的 Web 服务器在 www-data 用户下运行,您可以通过键入以下内容找到用户 ID:

id -u www-data
Output33

之后,您可以使用返回的 ID 来过滤日志结果:

journalctl _UID=33 --since today

systemd 期刊有很多字段可用于过滤。 其中一些是从正在记录的进程传递的,而另一些是由 journald 使用它在记录时从系统收集的信息应用的。

前导下划线表示 _PID 字段属于后一种类型。 日志会自动记录并索引正在记录的进程的 PID,以供以后过滤。 您可以通过键入以下内容了解所有可用的日记帐字段:

man systemd.journal-fields

我们将在本指南中讨论其中的一些内容。 不过现在,我们将讨论一个更有用的选项,与这些字段的过滤有关。 -F 选项可用于显示给定日记帐字段的所有可用值。

例如,要查看 systemd 日记帐包含哪些组 ID,您可以键入:

journalctl -F _GID
Output32
99
102
133
81
84
100
0
124
87

这将显示日志为组 ID 字段存储的所有值。 这可以帮助您构建过滤器。

按组件路径

我们还可以通过提供路径位置进行过滤。

如果路径指向可执行文件,journalctl 将显示所有涉及相关可执行文件的条目。 例如,要查找涉及 bash 可执行文件的条目,您可以键入:

journalctl /usr/bin/bash

通常,如果一个单元可用于可执行文件,则该方法更清晰并提供更好的信息(来自关联子进程的条目等)。 然而,有时这是不可能的。

显示内核消息

内核消息,通常在 dmesg 输出中找到的那些,也可以从日志中检索。

要仅显示这些消息,我们可以在命令中添加 -k--dmesg 标志:

journalctl -k

默认情况下,这将显示来自当前引导的内核消息。 您可以使用前面讨论的正常引导选择标志指定替代引导。 例如,要获取五次前的消息,您可以键入:

journalctl -k -b -5

按优先级

系统管理员经常感兴趣的一种过滤器是消息优先级。 虽然以非常详细的级别记录信息通常很有用,但在实际消化可用信息时,低优先级日志可能会分散注意力和混淆。

通过使用 -p 选项,您可以使用 journalctl 仅显示指定优先级或更高优先级的消息。 这允许您过滤掉优先级较低的消息。

例如,要仅显示以错误级别或更高级别记录的条目,您可以键入:

journalctl -p err -b

这将向您显示所有标记为错误、严重、警报或紧急情况的消息。 日志实现标准的 syslog 消息级别。 您可以使用优先级名称或其对应的数值。 按照优先级从高到低的顺序,它们是:

  • 0:出现
  • 1:警报
  • 2:暴击
  • 3:错误
  • 4:警告
  • 5:通知
  • 6:信息
  • 7:调试

上述数字或名称可以与 -p 选项互换使用。 选择优先级将显示标记在指定级别及其之上的消息。

修改日志显示

上面,我们通过过滤演示了条目选择。 不过,还有其他方法可以修改输出。 我们可以调整 journalctl 显示以适应各种需要。

截断或扩展输出

我们可以通过告诉它缩小或扩大输出来调整 journalctl 显示数据的方式。

默认情况下,journalctl 将在寻呼机中显示整个条目,允许条目拖到屏幕右侧。 可以通过按右箭头键访问此信息。

如果您希望截断输出,在已删除信息的位置插入省略号,您可以使用 --no-full 选项:

journalctl --no-full
Output. . .

Feb 04 20:54:13 journalme sshd[937]: Failed password for root from 83.234.207.60...h2
Feb 04 20:54:13 journalme sshd[937]: Connection closed by 83.234.207.60 [preauth]
Feb 04 20:54:13 journalme sshd[937]: PAM 2 more authentication failures; logname...ot

你也可以反过来告诉 journalctl 显示它的所有信息,不管它是否包含不可打印的字符。 我们可以使用 -a 标志来做到这一点:

journalctl -a

输出到标准输出

默认情况下,journalctl 在寻呼机中显示输出以便于使用。 但是,如果您计划使用文本操作工具处理数据,您可能希望能够输出到标准输出。

您可以使用 --no-pager 选项执行此操作:

journalctl --no-pager

根据您的需要,这可以立即通过管道传输到处理实用程序或重定向到磁盘上的文件中。

输出格式

如果您正在处理日记帐分录,如上所述,如果数据格式更易于使用,您很可能会更轻松地解析数据。 幸运的是,期刊可以根据需要以多种格式显示。 您可以使用带有格式说明符的 -o 选项来执行此操作。

例如,您可以通过键入以下内容以 JSON 格式输出日记帐条目:

journalctl -b -u nginx -o json
Output{ "__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635", "__REALTIME_TIMESTAMP" : "1422990364739502", "__MONOTONIC_TIMESTAMP" : "27200938", "_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d", "PRIORITY" : "6", "_UID" : "0", "_GID" : "0", "_CAP_EFFECTIVE" : "3fffffffff", "_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee", "_HOSTNAME" : "desktop", "SYSLOG_FACILITY" : "3", "CODE_FILE" : "src/core/unit.c", "CODE_LINE" : "1402", "CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading", "SYSLOG_IDENTIFIER" : "systemd", "MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5", "_TRANSPORT" : "journal", "_PID" : "1", "_COMM" : "systemd", "_EXE" : "/usr/lib/systemd/systemd", "_CMDLINE" : "/usr/lib/systemd/systemd", "_SYSTEMD_CGROUP" : "/", "UNIT" : "nginx.service", "MESSAGE" : "Starting A high performance web server and a reverse proxy server...", "_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973" }

. . .

这对于使用实用程序进行解析很有用。 在将数据结构传递给 JSON 使用者之前,您可以使用 json-pretty 格式更好地处理数据结构:

journalctl -b -u nginx -o json-pretty
Output{
    "__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635",
    "__REALTIME_TIMESTAMP" : "1422990364739502",
    "__MONOTONIC_TIMESTAMP" : "27200938",
    "_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d",
    "PRIORITY" : "6",
    "_UID" : "0",
    "_GID" : "0",
    "_CAP_EFFECTIVE" : "3fffffffff",
    "_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee",
    "_HOSTNAME" : "desktop",
    "SYSLOG_FACILITY" : "3",
    "CODE_FILE" : "src/core/unit.c",
    "CODE_LINE" : "1402",
    "CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading",
    "SYSLOG_IDENTIFIER" : "systemd",
    "MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5",
    "_TRANSPORT" : "journal",
    "_PID" : "1",
    "_COMM" : "systemd",
    "_EXE" : "/usr/lib/systemd/systemd",
    "_CMDLINE" : "/usr/lib/systemd/systemd",
    "_SYSTEMD_CGROUP" : "/",
    "UNIT" : "nginx.service",
    "MESSAGE" : "Starting A high performance web server and a reverse proxy server...",
    "_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973"
}

. . .

以下格式可用于显示:

  • cat:仅显示消息字段本身。
  • export:适合传输或备份的二进制格式。
  • json:标准 JSON,每行一个条目。
  • json-pretty:JSON 格式更好的人类可读性
  • json-sse:JSON 格式输出包装以使添加服务器发送的事件兼容
  • short:默认的syslog样式输出
  • short-iso:默认格式增加以显示 ISO 8601 挂钟时间戳。
  • short-monotonic:带有单调时间戳的默认格式。
  • short-precise:默认格式,精度为微秒
  • verbose:显示可用于条目的每个日记帐字段,包括通常在内部隐藏的字段。

这些选项允许您以最适合您当前需求的任何格式显示日记帐分录。

主动过程监控

journalctl 命令模拟有多少管理员使用 tail 来监视活动或最近的活动。 此功能内置在 journalctl 中,允许您访问这些功能而无需通过管道连接到其他工具。

显示最近的日志

要显示一定数量的记录,您可以使用 -n 选项,其工作方式与 tail -n 完全相同。

默认情况下,它将显示最近的 10 个条目:

journalctl -n

您可以在 -n 之后用数字指定要查看的条目数:

journalctl -n 20

关注日志

要在写入日志时主动跟踪日志,可以使用 -f 标志。 同样,如果您有使用 tail -f 的经验,这将如您所料:

journalctl -f

要退出此命令,请键入 CTRL+C

日志维护

您可能想知道存储我们迄今为止看到的所有数据的成本。 此外,您可能会对清理一些旧日志和释放空间感兴趣。

查找当前磁盘使用情况

您可以使用 --disk-usage 标志找出日志当前在磁盘上占用的空间量:

journalctl --disk-usage
OutputArchived and active journals take up 8.0M in the file system.

删除旧日志

如果您希望缩小日志,可以通过两种不同的方式来实现(适用于 systemd 版本 218 及更高版本)。

如果您使用 --vacuum-size 选项,您可以通过指定大小来缩小日志。 这将删除旧条目,直到磁盘上占用的总日志空间达到请求的大小:

sudo journalctl --vacuum-size=1G

可以缩小日志的另一种方法是使用 --vacuum-time 选项提供截止时间。 超过该时间的任何条目都将被删除。 这允许您保留在特定时间之后创建的条目。

例如,要保留去年的条目,您可以键入:

sudo journalctl --vacuum-time=1years

限制期刊扩展

您可以配置您的服务器来限制日志可以占用多少空间。 这可以通过编辑 /etc/systemd/journald.conf 文件来完成。

以下项目可用于限制期刊增长:

  • SystemMaxUse=:指定日志在持久存储中可以使用的最大磁盘空间。
  • SystemKeepFree=:指定将日志条目添加到持久存储时日志应保留的可用空间量。
  • SystemMaxFileSize=:控制单个日志文件在轮换之前在持久存储中可以增长到多大。
  • RuntimeMaxUse=:指定可用于易失性存储的最大磁盘空间(在 /run 文件系统内)。
  • RuntimeKeepFree=:指定将数据写入易失性存储(在 /run 文件系统内)时留出的空间量以供其他用途。
  • RuntimeMaxFileSize=:指定单个日志文件在旋转之前可以在易失性存储(在 /run 文件系统内)中占用的空间量。

通过设置这些值,您可以控制 journald 如何消耗和保留服务器上的空间。 请记住,SystemMaxFileSizeRuntimeMaxFileSize 将针对归档文件以达到规定的限制。 在清理操作后解释文件计数时,记住这一点很重要。

结论

如您所见,systemd 日志对于收集和管理您的系统和应用程序数据非常有用。 大多数灵活性来自自动记录的大量元数据和日志的集中性。 journalctl 命令可以轻松利用日志的高级功能,并对不同的应用程序组件进行广泛的分析和关系调试。