在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”。