系统和进程日志记录 只是最关键的两个优势,来自于 systemd。当日志分散在整个系统中、跨越多个应用程序并由不同的进程和守护进程处理时,解释它们可能会具有挑战性。Systemd 提供了一个集中式解决方案,用于在被称为 journal(日志)的编译介质中管理所有内核和用户空间进程日志。您可以在我们关于如何使用 systemctl 管理 systemd 服务和单元的教程中了解有关 systemd 的更多信息。日志中由服务、initrd、内核等生成的所有消息都由 journal 守护进程处理。本指南的目的是说明如何使用 journalctl 访问和操作日志的数据。
基本前提
无论消息可能源自何处,systemd 的主要宗旨之一就是允许对其进行集中管理。由于许多启动过程和大部分服务管理都由 systemd 进程负责,因此编译和访问日志的方式应该标准化。journald 将来自任何可用源的数据收集到一个包罗万象的工具中,并以二进制格式存储它们。这使得数据可以随时用于动态且简单的操作。
这种方法有几个关键优势。通过拥有一个收集所有数据的中心位置,管理员可以过滤并仅显示他们需要的数据。例如,人们可以查看三次系统启动前的启动数据。它还意味着可以按顺序记录相关服务的条目,并更有效地追踪它们之间的通信问题。
得益于二进制存储,数据可以根据用户当时的需求以各种输出格式显示。例如,每日日志可以以标准的 syslog 格式查看。但如果您需要以图表的形式展示服务中断趋势,则可以将该条目输出为 JSON 对象,使其适用于图表服务。当您需要根据具体需求更改格式时,不需要进行转换,因为数据是二进制的,而不是以纯文本形式写入磁盘。
根据个人的需求,您可以将 systemd 日志与现有的 syslog 一起实现,或者它可以替代该功能。Systemd 甚至可以补充现有的日志记录机制。例如,单个系统上的多个服务可以通过 systemd 日志将其编译的数据交织在单个系统上。
设置系统时间
默认情况下,systemd 将以本地时间显示结果,这是二进制日志记录在查看日志记录方面的一个好处。或者,也可以在 UTC 中查看它们。因此,在开始日志记录之前,确保正确设置时区非常重要。为此,systemd 配备了一个名为 timedatectl 的工具。我们首先通过使用 list-timezones 选项显示列表来查看有哪些时区可用:
|
1 |
timedatectl list-timezones |
在找到与您服务器位置匹配的时区后,可以使用 set-timezone 选项来设置时区:
|
1 |
sudo timedatectl set-timezone zone |
要测试并验证时区现在是否正常显示,您可以单独使用 timedatectl 命令,或者加上 ‘status:’

第一行描绘了本地时间。这一行应该包含您本地地区的正确时间。
常规日志查看
journalctl 命令将允许您查看 journald 守护进程收集的日志。当您使用 journalctl 时,系统中的每个日志条目都将显示在屏幕页面内,最旧的条目列在最上面。然而,完整的数据列表将长达数万行。
|
1 |
journalctl |

那些使用过标准 syslog 日志的人会觉得这种格式很熟悉,但需要记住的是,与 syslog 方法不同,这种数据汇编整合了来自许多源的信息。日志将包括早期启动过程、initrd 和内核,以及应用程序的标准错误。
现在本地时间已设置,所有条目都将以本地时间的时间戳开始,并且适用于当前存储在系统上的每个日志,所有逻辑都通过使用这些新信息来显示。然而,您并不局限于本地时间。使用 –utc 标志,您也可以显示 UTC 时间戳:
|
1 |
journalctl --utc |
按时间过滤日志
拥有如此多的可用数据是非常棒的,但是梳理并吸收这些数据,更不用说在脑海中进行处理,可能会是一项艰巨的任务。考虑到这一点,我们来到了 journalctl 功能最核心的部分:过滤。
显示当前启动的日志
如果您正在日志中寻找最新一次重启的数据,可以使用带有 -b 标志的 journalctl 功能。这将显示系统最近一次重启的所有相关日志信息。此命令将允许您查找和管理与当前工作环境最相关的信息:
|
1 |
journalctl -b |
如果查看者选择不评估每个单独的条目,journalctl 将显示超过一天的启动信息,并在 journalctl 中使用方便的“Reboot”分隔符进行显示。这有助于在逻辑上区分来自不同启动会话的信息以供审查:
|
1 2 3 |
. . . -- 重启 -- . . . |
历史启动信息
虽然显示当前的启动信息往往是最有用的,但在某些情况下,历史启动信息也会有所帮助。Journal 会保存多次先前启动的信息,因此 journalctl 可以轻松显示任何时间段的信息。
某些发行版禁用了保存历史启动信息的功能,而其他发行版则默认启用。要启用持久性启动信息,可以通过输入以下命令创建用于存储日志的目录:
|
1 |
sudo mkdir -p /var/log/journal |
或者,您也可以按以下方式编辑日志配置文件:
|
1 |
sudo nano /etc/systemd/journald.conf |
在 [Journal] 部分下将 Storage= 选项设置为“persistent”将启用持久性日志记录:

一旦启用此功能,journalctl 就会提供某些命令,帮助您将这些启动指定为划分单位。要查看 journald 中已记录的启动,您可以通过 journalctl 使用 –list-boots option 选项:
|
1 |
journalctl --list-boots |
![]()
如图所示,每次启动都将单独列在一行中,第一列按从最早到最新的顺序反映先前的启动。如果需要更绝对的参考,第二列包含启动标识。之后,列出了两个时间规范。第一列或第二列中的信息均可用于显示特定启动的日志信息。例如,您可以使用 -b 标志和相对启动指针 -1 来查看倒数第二次重启的信息:
|
1 |
journalctl -b -1 |
类似地,第二列中的启动 ID 也可以按这种方式使用:
|
1 |
journalctl -b 54342de612174d269b66f1d5eb098abb |
时间窗口
通过 ID 查看启动记录是一种选择,但通常更有用的是能够通过过去的时间窗口来引用先前的启动,这不一定与特定的启动对齐。例如,在处理不经常重启的长期运行服务器时,这就非常适用。时间限制的过滤可以使用任意时间限制来进行。这将仅显示落在特定时间窗口内的重启信息。该窗口的参数由 –since 和 –until 选项指定。时间选项有几种可用格式。绝对时间值格式如下:
|
1 |
YYYY-MM-DD HH:MM:SS |
因此,如果您想查看自 2015 年 1 月 10 日下午 5:15 以来的所有启动记录,请键入以下命令:
|
1 |
journalctl --since "2015-01-10 17:15:00" |
如果省略了任何部分,则有内置的默认值。此外,如果省略了日期,则默认为当前日期。如果缺少时间部分,则默认为午夜(00:00:00)。如果您在时间部分省略了秒,它们将默认为该分钟的起始点(00):
|
1 |
journalctl --since "2015-01-10" --until "2015-01-11 03:00" |
日志可以理解与时间相关的快捷方式,如“today”(今天)、“tomorrow”(明天)、“yesterday”(昨天)和“now”(现在)。像 ago(以前)这样的词,结合前置限定符“-”和“+”,可以用来构建句子类型的命令:
|
1 |
journalctl --since yesterday |
如果您收到通知,称服务中断始于 9:00,并且想要检查截至一小时前的日志,您可以使用以下命令进行操作:
|
1 |
journalctl --since 09:00 --until "1 hour ago" |
显而易见,定义一个灵活的时间窗口来查看所需的条目是非常简单的。
按感兴趣的消息过滤
除了通过时间限制过滤日志外,还可以根据感兴趣的服务组件来过滤数据。Systemd 提供了几种方法来实现这一点。
按单元
可以说,最实用的过滤参数是按感兴趣的单元过滤。要按单元过滤,可以利用 -u 选项。例如,如果您希望查看与 Nginx 单元相关的所有日志,请键入以下命令:
|
1 |
journalctl -u nginx.service |
在实际情况中,您会希望将其与时间过滤器结合使用,以便显示感兴趣的行。如果您想检查上述服务以及它今天的运行情况,可以执行以下操作:
|
1 |
journalctl -u nginx.service --since today |
当利用日志汇编来自多个单元(尤其是协作单元)的记录的能力时,这特别有用。如果 Nginx 进程连接到 PHP-FPN 单元以进行动态内容处理,则可以通过指定这两个单元按时间顺序合并条目:
|
1 |
journalctl -u nginx.service -u php-fpm.service --since today |
这可以极大地帮助记录程序交互,并使调试系统(而不是单个进程)变得更加容易。
按组 ID、进程或用户
许多服务会启动大量的子进程来执行特定的工作。如果已知特定进程的 ID,也可以通过指定 _PID 字段来进行过滤。如果感兴趣的 PID 是 8088,可以执行以下操作:
|
1 |
journalctl _PID=8088 |
您可能还想查看来自特定组或特定用户的日志条目。这可以通过使用 _GID and _UID 过滤器来实现。如果 Web 服务器在 www-data 用户下运行,以下命令可以找到所需的 ID:
|
1 |
id -u www-data |

使用该 ID,您就可以查看符合条件的日志结果:
|
1 |
journalctl _UID=33 --since today |
Systemd 提供了许多可用于过滤的字段。其中一些字段是由 journald 根据在记录日志时从系统收集的信息自动应用的,而另一些字段则是从当前正在记录日志的进程中传入的。
前缀修饰符 _PID 表示该信息是在记录日志时从系统中收集的。日志系统在记录日志的过程中会自动记录并索引 PID,以便日后进行过滤。要了解可用的日志字段,您可以输入:
|
1 |
man systemd.journal-fields |
我们将在本指南的后面部分讨论其中一些字段,但现在,我们将简要介绍与这些字段相关的其他一些有用选项。如果您想查看特定日志字段的所有可用值,可以使用 -F 选项。如果您想查看 systemd 日志中包含哪些组 ID,可以执行以下操作:
|
1 |
journalctl -F _GID |

这可以通过提供日志组 ID 字段已存储的完整值列表,来协助构建过滤器。
按组件路径
也可以通过提供路径位置来进行过滤。如果该路径指向一个可执行文件,则 journalctl 中涉及该可执行文件的条目将被显示。如果感兴趣的可执行文件是 ‘bash’,您可以输入:
|
1 |
journalctl /bin/bash |
虽然有时无法做到这一点,但如果该可执行文件的单元(unit)可用,它可以提供一种更清晰、包含更多信息的过滤方法。
显示内核消息
通常在 dmesg 输出中找到的内核消息也可以从日志中检索。为了仅显示这些消息,我们在命令中使用 -k 或 -dmesg 标志:
|
1 |
journalctl -k |
默认情况下将显示当前启动的消息,但也可以像前面提到的那样使用选择标志来指定之前的启动。如果您正在寻找五次启动前的消息,输入以下内容将获得所需的结果:
|
1 |
journalctl -k -b 5 |
按优先级
系统管理员通常更喜欢按优先级进行过滤。低优先级的日志虽然通常对查看很有用,但可能会令人困惑并包含许多干扰,从而降低分析时的可读性。在 journalctl 中使用 -p 选项将仅显示指定优先级的消息,过滤掉任何其他优先级。如果您希望显示错误级别或以上的条目,请输入以下内容:
|
1 |
journalctl -p err -b |
该命令将返回所有被标记为错误(error)、警报(alert)、紧急(emergency)或严重(critical)的消息,日志使用的是标准的 syslog 消息级别。优先级级别根据数值定义,从最高到最低排序:
- 0: emerg
- 1: alert
- 2: crit
- 3: err
- 4: warning
- 5: notice
- 6: info
- 7: debug
上述任何一项都可以与 -p 选项互换使用。选择上述任何一个优先级都将筛选出该级别及以上的所有优先级。
修改日志中的显示
除了使用过滤来进行条目选择之外,我们还有其他修改输出的方法,以定制 journalctl 的显示来满足我们的需求。
截断/展开输出
我们可以通过调整 journalctl 是收缩还是展开数据来调整输出的视图。journalctl 的默认设置是显示完整条目,将较长的条目延伸到屏幕右侧。您可以通过向右方向键滚动来查看完整条目。用户可能希望截断输出,在超出屏幕的行上用省略号表示。为此,可以使用 –no-full 选项:
|
1 |
journalctl --no-full |

或者,您也可以通过使用 -a 标志,允许显示所有内容,而不考虑长度或是否包含不可打印字符:
|
1 |
journalctl -a |
输出到标准输出
Journalctl 默认将输出显示在分页器中,但如果您希望使用文本编辑工具处理数据,您可能需要将输出生成到标准输出选项。您可以使用 –no-pager 选项来实现这一点:
|
1 |
journalctl --no-pager |
根据用户的需求,这可以重定向到磁盘上的文件或处理实用程序。
输出格式
当以更易于使用的格式呈现时,数据总是更容易解析。日志提供了多种显示选项,使用 -o 限定符后跟特定指定的格式。
如果您希望将日志条目输出为 JSON 格式,可以通过以下方式进行:
|
1 |
journalctl -b -u nginx -o json |
![]()
这种策略在解析实用程序时特别有用。在将数据结构传递给 JSON 消费者之前,json-pretty 格式可以更好地显示数据结构:
|
1 |
journalctl -b -u nginx -o json-pretty |

有几种格式可供您用于显示:
- cat:仅显示消息字段本身。
- export:适用于传输或备份的二进制格式。
- json:标准 JSON,每行一个条目。
- json-pretty:格式化为更易于人类阅读的 JSON
- json-sse:包装为与服务器发送事件(server-sent event)兼容的 JSON 格式输出
- short:默认的 syslog 样式输出
- short-iso:增强的默认格式,用于显示 ISO 8601 挂钟时间戳。
- short-monotonic:带有单调时间戳的默认格式。
- short-precise:具有微秒级精度的默认格式
- verbose:显示该条目可用的每个日志字段,包括通常在内部隐藏的字段。
上述选项允许日志以您首选的格式显示。
活动进程监控
日志允许访问监控活动或近期活动的功能,而无需引入其他工具。您可以使用带有 ‘tail’ 功能的 journalctl 命令来实现这一点。
-
显示最近的日志
显示 -n 选项(其工作方式与 tail-n 命令类似),将允许显示一定数量的记录:
|
1 |
journalctl -n |
您希望显示的条目数量可以通过 -n 限定符后的特定数字来指定:
|
1 |
journalctl -n 20 |
-
跟踪日志
您还可以使用 -f 标志在日志写入系统时主动跟踪它们。这与 tail -f 命令的工作方式相同:
|
1 |
journalctl -f |
日志维护
日志确实会占用空间。这值得探讨,可能需要清除一些较旧的日志以释放空间。
查找当前磁盘占用情况
The –disk-usage 标志可以帮助确定日志当前在磁盘上占用了多少空间:
|
1 |
journalctl --disk-usage |

删除旧日志
在 systemd 版本 218(及后续版本)中,您可以通过两种不同的方式收缩日志。一种是 –vacuum-size 选项。这可以通过指定大小来收缩日志。换句话说,较旧的条目将从日志中清除,直到占用的空间达到要求的参数:
|
1 |
sudo journalctl --vacuum-size=1G |
–vacuum-time 选项可以通过指定截止时间来收缩日志占用的空间,超过该时间的任何条目都将被删除,而在指定时间之后创建的条目将被保留。如果您只想保留过去一个日历年内的条目,可以使用:
|
1 |
sudo journalctl --vacuum-time=1years |
限制日志膨胀
您还可以限制日志占用的空间量。这可以通过编辑 /etc/systemd.journald.conf 文件来实现。可以使用以下任何方法来限制日志的增长:
- SystemMaxUse=: 表示允许日志在持久存储中使用的最大磁盘空间。
- SystemKeepFree=: 表示在持久存储中添加日志实体时应保留多少空闲空间。
- SystemMaxFileSize=: 指定在持久存储中进行轮转之前,日志文件允许增长到的最大大小。
- RuntimeMaxUse=: 指定在易失性存储(在 /run 文件系统内)中允许使用的最大磁盘空间量。
- RuntimeKeepFree=: 在向易失性存储写入数据时,此功能表示必须留作其他用途的空间量(在 /run 文件系统内)。
- RuntimeMaxFileSize=: 表示在需要进行轮转之前,单个日志文件在易失性存储(在 /run 文件系统内)中可以占用的最大空间量。
这些选项都可以帮助控制日志所消耗的存储空间。需要注意的一个重要事实是,SystemMaxFileSize 和 RuntimeMaxFileSize 选项将针对已归档的文件来达到指定的限制。在解释清理(vacuuming)操作后的文件数量时,务必牢记这一重要事实。
结论
显而易见,systemd 日志是一个非常实用的工具,其大部分优势源于日志的集中化特性以及记录的大量元数据。通过使用 journalctl 命令,可以充分利用日志的丰富功能,从而为执行应用程序组件的关系调试以及广泛的系统分析提供更简便的方法。
祝您使用愉快!
评论
暂无评论。发表第一条评论吧。