在Linux上使用的传统日志系统是rsyslog,它是传统syslog的现代版本。
Systemd引入了自己的日志系统:它由一个守护进程journald实现,该守护进程以二进制格式将日志存储到“日志”中,journalctl实用程序可以查询该日志。
查询日志
我们可以用来检查系统日志和查询systemd日志的工具是“journalctl”。如果在没有其他参数的情况下调用该命令,将显示日志的所有内容。幸运的是,可以实现几种策略来过滤日志。
按单位筛选消息
我们可以传递给“journalctl”的最有用的选项之一是“-u”,它是“-unit”的简短版本。使用此选项,我们可以过滤日志的内容,以便只返回作为选项参数传递的特定systemd单元的消息。例如,要仅显示来自“NetworkManager.service”单元的消息,我们可以运行:
$journalctl -u NetworkManager -- Logs begin at Wed 2016-07-01 21:47:23 CEST, end at Sat 2016-07-25 15:26:59 CEST. - Jan 01 21:48:07 eru systemd[1]: Starting Network Manager... Jan 01 21:48:07 eru NetworkManager[1579]: <info> [1593632887.7408] NetworkManager (version 1.22.10-1.fc32) is starting... (for the first time) Jan 01 21:48:07 eru NetworkManager[1579]: <info> [1593632887.7413] Read config: /etc/NetworkManager/NetworkManager.conf Jan 01 21:48:07 eru systemd[1]: Started Network Manager.
此外,特定选项专用于仅过滤内核消息:-k,这是--dmesg的短形式。
按日期过滤日志
如果我们想要过滤存储在期刊中的消息,我们可以使用两个专用选项:-s(scsince)和-u(subs -until)。
这两个选项都接受格式的日期yyyy-mm-dd hh:mm:ss。
可以省略“时间”部分,并且在这种情况下,假设“00:00:00即00”。
假设我们要从当前日期开始过滤日志;我们将运行以下命令:
$journalctl --since 2016-07-25
要进一步限制时间从'16:04:21'到'16:04:26'的日志,请执行以下操作:
$journalctl --since "2016-07-25 16:04:21" --until "2016-07-25 16:04:26"
还有一些别名:它们可以用来代替普通日期:
| String | 说明 |
|---|---|
| “yesterday” | 昨天00:00:00 |
| “today” | 今天 |
| “tomorrow” | 明天 |
| “now” | 当前时间 |
仅显示最新日志
如果我们使用-f(--follow)选项启动journalctl命令,那么我们只能可视化最新接收到的日志,并且仍然可以观察到新日志被附加到日志中(这基本上类似于使用-f选项调用tail)。另一方面,如果我们只想可视化日志的结尾,我们可以使用“-e”选项(“--pager end”)。
格式化journalctl输出
我们在使用“journalctl”时收到的输出可以通过一个专用选项轻松格式化:-o,或者它的长版本--output。
选项的其他设置有:
- short
- verbose
- json-pretty
默认为“short”格式:在与传统syslog类似的输出中,每个条目显示一行:
Jan 01 21:48:07 eru systemd[1]: Starting Network Manager...
相反,“verbose”格式将显示条目的所有字段:
Wed 2016-07-01 21:48:07.603130 CEST [s=d61cdf3710e84233bda460d931ebc3bb;i=6be;b=1c06b8c553624a5f94e1d3ef384fb50d;m=2e82666;t=5a966922b0155;x=6668aad5e895da03]
PRIORITY=6
_BOOT_ID=1c06b8c553624a5f94e1d3ef384fb50d
_MACHINE_ID=afe15f1a401041f4988478695a02b2bf
_HOSTNAME=eru
SYSLOG_FACILITY=3
SYSLOG_IDENTIFIER=systemd
_UID=0
_GID=0
_TRANSPORT=journal
_CAP_EFFECTIVE=3fffffffff
CODE_FILE=src/core/job.c
CODE_LINE=574
CODE_FUNC=job_log_begin_status_message
JOB_TYPE=start
MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5
_PID=1
_COMM=systemd
_EXE=/usr/lib/systemd/systemd
_SYSTEMD_CGROUP=/init.scope
_SYSTEMD_UNIT=init.scope
_SYSTEMD_SLICE=-.slice
_SELINUX_CONTEXT=system_u:system_r:init_t:s0
_CMDLINE=/usr/lib/systemd/systemd --switched-root --system --deserialize 34
MESSAGE=Starting Network Manager...
JOB_ID=243
UNIT=NetworkManager.service
INVOCATION_ID=6416439e51ff4543a76bded5984c6cf3
_SOURCE_REALTIME_TIMESTAMP=1593632887603130
“json pretty”格式以人类可读的方式将条目显示为json对象。在此格式中,条目由换行符分隔:
{
"__REALTIME_TIMESTAMP" : "1593632887603541",
"PRIORITY" : "6",
"_SYSTEMD_UNIT" : "init.scope",
"_SYSTEMD_CGROUP" : "/init.scope",
"_UID" : "0",
"_COMM" : "systemd",
"_SYSTEMD_SLICE" : "-.slice",
"_CAP_EFFECTIVE" : "3fffffffff",
"_BOOT_ID" : "1c06b8c553624a5f94e1d3ef384fb50d",
"_SELINUX_CONTEXT" : "system_u:system_r:init_t:s0",
"__CURSOR" : "s=d61cdf3710e84233bda460d931ebc3bb;i=6be;b=1c06b8c553624a5f94e1d3ef384fb50d;m=2e82666;t=5a966922b0155;x=6668aad5e895da03",
"_HOSTNAME" : "eru",
"_PID" : "1",
"MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5",
"CODE_FUNC" : "job_log_begin_status_message",
"MESSAGE" : "Starting Network Manager...",
"_EXE" : "/usr/lib/systemd/systemd",
"__MONOTONIC_TIMESTAMP" : "48768614",
"_TRANSPORT" : "journal",
"SYSLOG_FACILITY" : "3",
"UNIT" : "NetworkManager.service",
"JOB_ID" : "243",
"JOB_TYPE" : "start",
"_GID" : "0",
"CODE_FILE" : "src/core/job.c",
"_MACHINE_ID" : "afe15f1a401041f4988478695a02b2bf",
"_CMDLINE" : "/usr/lib/systemd/systemd --switched-root --system --deserialize 34",
"SYSLOG_IDENTIFIER" : "systemd",
"CODE_LINE" : "574",
"INVOCATION_ID" : "6416439e51ff4543a76bded5984c6cf3",
"_SOURCE_REALTIME_TIMESTAMP" : "1593632887603130"
}
日志配置文件
日志守护程序的行为可以通过更改其配置文件中的设置来修改:/etc/systemd/journald.conf。不建议直接修改此文件;相反,我们应该创建一些单独的配置文件,其中包含我们想要更改的参数,用“.conf”扩展名保存它们,并将它们放在“/etc/systemd/journald.conf.d”目录中。
放置在/etc/systemd/journald.conf.d目录中的文件比/etc/systemd/journald.conf具有更高的优先级:它们按照字典顺序按名称排序,并按照该顺序进行解析,所有文件都位于主文件之后。如果同一选项设置存在于多个文件中,则最后一个要分析的文件将有效。
默认情况下,/etc/systemd/jourlnald.conf文件在[Journal]节中包含一个带注释的选项列表:它们表示编译时使用的默认值(以下内容来自Fedora系统):
[Journal] #Storage=auto #Compress=yes #Seal=yes #SplitMode=uid #SyncIntervalSec=5m #RateLimitIntervalSec=30s #RateLimitBurst=10000 #SystemMaxUse= #SystemKeepFree= #SystemMaxFileSize= #SystemMaxFiles=100 #RuntimeMaxUse= #RuntimeKeepFree= #RuntimeMaxFileSize= #RuntimeMaxFiles=100 #MaxRetentionSec= #MaxFileSec=1month #ForwardToSyslog=no #ForwardToKMsg=no #ForwardToConsole=no #ForwardToWall=yes #TTYPath=/dev/console #MaxLevelStore=debug #MaxLevelSyslog=debug #MaxLevelKMsg=notice #MaxLevelConsole=info #MaxLevelWall=emerg #LineMax=48K #ReadKMsg=yes #Audit=yes
“Storage”选项
我们在文件中遇到的第一个选项是存储。此选项控制日志数据的存储位置。此处编译时使用的默认值为“auto”,但可以在以下选项中进行选择:
- volatile
- persistent
- auto
- none
如果我们使用'volatile'作为此选项的值,则日志数据将仅存储在/run/log/journal(/run是一个tmpfs:其内容存储在内存中)下的内存中,因此在系统重新启动后将无法保存。
如果改为使用“persistent”,则日志数据将存储在磁盘上的“/var/log/journal”下,如果不存在,则创建该日志。但是,如果由于某种原因磁盘不可写,则使用“/run/log/journal”作为回退。
“Storage”选项的“auto”值在这里用作默认值,其工作原理基本上类似于“persistent”,即当使用它时,日志数据存储在“/var/log/journal”下。不同之处在于,如果路径不存在,则不会创建该路径,日志将仅存储在内存中。
最后,如果使用了“none”值,则所有存储都将关闭:当转发到其他日志系统(如syslog)时,所有接收到的数据都将被丢弃。
“Compress”选项
“compress”选项控制是否在存储到磁盘之前压缩超过“512”字节阈值的数据。此选项接受两种类型的值:布尔值(如上所示)(yes),或者设置压缩阈值本身的数字。如果提供了后者,则隐式激活压缩。默认情况下,阈值以字节表示,但可以使用'K'、'M'或者'G'后缀。
“ForwardToSysLog”选项
如前所述,在前Systemd时代,日志由syslog日志系统(rsyslog实际上)管理。该日志系统能够将日志转发到许多目的地,如文本文件、终端,甚至网络上的其他机器。Systemd实现了自己的日志系统,这是本教程的目标:journald。
这两个系统可以共存(这有时是必要的,因为journald忽略了一些功能,如集中式日志记录,或者只是因为作为管理员,我们可能希望日志以文本文件而不是二进制格式存储,因此可以使用标准Unix工具对其进行操作)。
此“ForwardToSysLog”选项采用布尔值:如果设置为“yes”,则消息将转发到“/run/systemd/journal/syslog”套接字,其中可以由“syslog”读取。也可以在引导时通过systemd.journald.forward_to_syslog选项设置此行为。
类似的选项可用于将消息转发到“kmsg”(内核日志缓冲区)、控制台或者“wall”(作为日志消息发送给登录用户)。默认情况下,只有后者设置为“yes”。
