日志流向&&管理

3412 字
17 分钟
日志流向&&管理

日志流向&&管理#

[TOC]


journalctl 基础#

journalctl 是用于查询 systemd-journald 所管理的二进制日志(journal 日志)的命令行工具

Tip
  • .journal 文件,它们是二进制的! 不是纯文本,而是 经过压缩…的二进制格式

  • 无法通过 catless 看到日志内容

  • 创建 /var/log/journal 目录后,需要执行 journalctl --flush 才能立即生效

    立即刷新日志到磁盘(RHEL必须执行)

Terminal window
[root@R11 ~]# ll /run/log/journal/
total 0
drwxr-s---+ 2 root systemd-journal 80 Mar 15 08:25 945083a175da498c9068d4d540f05d72
# 这些日志默认存储在 /run/log/journal/(临时,内存中)
💡 boot ID(如 9450...)
'每次启动都不同,用于区分启动会话'
[root@R11 journal]# tree /run/log/journal/
/run/log/journal/
└── 945083a175d...40f05d72
├── system@f..d-0..0001-00...f0.journal
└── system.journal
# 这些都是二进制日志文件,以.journal结尾!
[root@R11 ~]# ll /var/log/journal
ls: cannot access '/var/log/journal': No such file or directory
# 或 /var/log/journal/(持久化,需启用)
'默认并没有让日志持久化'
[root@R11 ~]# ls /etc/systemd/journald.conf
ls: cannot access '/etc/systemd/journald.conf': No such file or directory
💡(老版本配置位置,新版本可能不存在)
[root@R11 ~]# locate journald.conf
/usr/lib/systemd/journald.conf
# 新版本位置!
[root@R11 ~]# vim /usr/lib/systemd/journald.conf
[Journal]
Storage=persistent
# 可选:限制日志大小
SystemMaxUse=500M
RuntimeMaxUse=100M
---------------------
'Storage参数说明'
volatile:仅存储在内存 `/run/log/journal`
persistent:强制存储在磁盘 `/var/log/journal`
auto:自动,默认使用内存!
none:不存储任何日志
---------------------
[root@R11 ~]# egrep -v '^$|^#' /usr/lib/systemd/journald.conf
.....
[root@R11 ~]# mkdir -p /var/log/journal
==========================
'直接 重启 & --flush'
[root@R11 ~]# ll /var/log/journal
total 0
[root@R11 ~]# systemctl restart systemd-journald
[root@R11 ~]# journalctl --flush
'立即刷新日志到磁盘(RHEL必须执行)'
[root@R11 ~]# ll /var/log/journal
total 0
drwxr-xr-x 2 root root 28 Mar 15 11:25 945083a175da498c9068d4d540f05d72
# 现在就出现在磁盘中了,永久保存!
==========================
'老版记得改权限!'
[root@R11 ~]# ll -d /var/log/journal/
drwxr-xr-x 2 root root 6 Mar 15 08:31 /var/log/journal/
⚠️权限错误 目录应属于 root:systemd-journal,权限 2755
# 可以参考上面的/run/log/journal/目录权限
[root@R11 ~]# chown root:systemd-journal /var/log/journal
[root@R11 ~]# chmod 2755 /var/log/journal
[root@R11 ~]# ll -d /var/log/journal/
drwxr-sr-x 2 root systemd-journal 6 Mar 15 08:31 /var/log/journal/
[root@R11 ~]# systemctl restart systemd-journald
[root@R11 ~]# ll /var/log/journal/
total 0
# 还是没有
'这里我忘记journalctl --flush'
[root@R11 ~]# logger "TEST PERSISTENT LOG"
# 手动创建日志
[root@R11 ~]# journalctl -g "TEST PERSISTENT LOG"
Mar 15 08:40:42 R11 root[2696]: TEST PERSISTENT LOG
========================
-g 选项是 “grep 模式” 的缩写,用于在日志消息内容中进行正则表达式匹配
'按 消息内容 过滤(全文搜索)'
========================
[root@R11 ~]# ll /var/log/journal/
total 0
# 还是没有持久化保存在/var/log/journal/里面
# 说明这会儿还是保存在内存中的
[root@R11 ~]# reboot
[root@R11 ~]# Connection closing...Socket close.
✅我们重启系统再试试!
[root@R11 ~]# journalctl -g "TEST PERSISTENT LOG"
-- No entries --
重启后,我们刚才手动写的日志就丢失
# 说明我们刚才日志是写在内存中的,重启失效!
[root@R11 ~]# ll /var/log/journal
total 0
drwxr-sr-x+ 2 root systemd-journal 28 Mar 15 08:42 945083a175da498c9068d4d540f05d72
# 现在再查看就有了
'配置完持久化日志,重启生效!'
[root@R11 ~]# logger "TEST PERSISTENT LOG"
# 再次手动书写一条日志
[root@R11 ~]# reboot
# 并重启,验证日志是否持久化保存了
[root@R11 journal]# journalctl -g "TEST PERSISTENT LOG"
Mar 15 08:57:08 R11 root[2542]: TEST PERSISTENT LOG
-- Boot 29f2b3d2ad994f91b8f8ab09a96a8fd5 --
# 重启后能够看到之前发的日志!
'被我们持久化保存了'
[root@R11 journal]# tree /var/log/journal/
/var/log/journal/
└── 9450...5d72
├── system@ff...0001-00...f0.journal
└── system.journal

/run/log/journal/ vs /var/log/journal/#

路径类型持久性用途
/run/log/journal/tmpfs(内存)❌ 重启丢失临时存储,用于快速访问
/var/log/journal/磁盘✅ 重启保留持久化日志(需手动创建目录)

即使启用了持久化,/run/log/journal/ 仍可能有内容

  • 因为 journald 会同时缓存 最近的日志 到内存以提高性能

    但主存储在 /var/log/journal/

journalctl 基础命令#

Terminal window
(1)查看所有日志(按时间排序)
'最新的日志在底下,非常不友好!'
[root@R11 ~]# journalctl
Mar 15 08:42:14 localhost kernel: Linux version...el10_1.x86_64
Mar 15 08:42:14 localhost kernel: ...
=========================
'反向查看(最新在前,推荐)'
journalctl -r
[root@R11 ~]# journalctl -r
Mar 15 10:39:27 R11 systemd[1]: Finished...
=========================
'查看最近10条日志'
[root@R11 ~]# journalctl -n 10
Mar 15 10:49:05 R11 systemd[1]: Started...
Mar 15 10:54:10 R11 PackageKit[3340]: daemon quit...
(2)按消息内容过滤(全文搜索)
[root@R11 ~]# journalctl -g "TEST PERSISTENT LOG"
Mar 15 08:40:42 R11 root[2696]: TEST PERSISTENT LOG
# -g 选项是 “grep 模式” 的缩写
# 用于在日志消息内容中进行正则表达式匹配
(3)🔍查看 nginx 服务的日志(指定服务)
# (等价于 `-u nginx`)
[root@R11 ~]# yum -y install nginx
[root@R11 ~]# systemctl enable --now nginx
Created symlink '/etc/systemd/system/multi-user.target.wants/nginx.service' '/usr/lib/systemd/system/nginx.service'.
[root@R11 ~]# journalctl -u nginx
注意:-u 后面跟的是 unit 名称(如 nginx.service)
'这里nginx==nginx.service'
Mar 15 10:06:55 R11 systemd[1]: Starting nginx.service...
.../etc/nginx/nginx.conf test is successful
[root@R11 ~]# journalctl -u log-time.service | tail -3
Mar 15 08:57:29 R11 log_back.sh[1299]: over...successful!!!
=========================
'按进程 ID 查询日志'
[root@R11 ~]# journalctl _PID=1213
Mar 15 08:42:21 R11 polkitd[1213]: Started polkitd version 125
-- Boot 29f2b3d2ad994f91b8f8ab09a96a8fd5 --
Mar 15 08:57:29 R11 systemd-logind[1213]: New seat seat0.
=========================
'按错误级别(err 及以上)的日志'
# 参考下面的日志级别!
# 数值越小,级别越高、越严重
[root@R11 ~]# journalctl -p err
Mar 15 08:42:15 localhost kernel: Warning:....
(4)查看指定时间段的日志
journalctl -u nginx --since "2026-03-14 00:00:00" --until "2026-03-14 19:00:00"
[root@R11 ~]# journalctl -u nginx --since "2026-03-15 00:00:00" --until "2026-03-15 10:19:00"
Mar 15 10:06:55 R11 systemd[1]: Starting nginx.service...
journalctl -u log-time | sed -n '/Mar 15 00:00/,/Mar 15 09:00/p'
(5)实时跟踪最新日志(类似 `tail -f`
[root@R11 ~]# journalctl -f | grep nginx
Mar 15 10:22:38 R11 systemd[1]: Stopping nginx.service...
# 可以先新开一个窗口、再来进行查看!
(6)查看 journal 日志占用的磁盘空间
[root@R11 ~]# journalctl --disk-usage
Archived and active journals take up 14.7M in the file system.
=========================
'手动清理旧日志(保留最近100M)'
[root@R11 ~]# journalctl --vacuum-size=100M
....
(7)查看本次以来启动日志
[root@R11 ~]# journalctl -b
Mar 15 08:57:22 localhost kernel: Linux version 6.12.0-124.8.1.el10_1.x86_64 ...
Mar 15 08:57:22 localhost kernel: Command line: BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.12.0-124.8.1.el10_1.x86_64...
=========================
'上一次启动的日志'
[root@R11 ~]# journalctl -b -1
Mar 15 08:42:14 localhost kernel: Linux version 6.12.0-124.8.1.el10_1.x86_64 ...
Mar 15 08:42:14 localhost kernel: Command line: BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.12.0-124.8.1.el10_1.x86_64 ...
(8)JSON格式输出(便于脚本处理)
[root@R11 ~]# journalctl -o json -u nginx
{"_CMDLINE":"/usr/lib/systemd/systemd --switched-root --system --deserialize=43 rhgb","UNIT":"nginx.service","_MACHINE_......."
{"MESSAGE":"nginx: the configuration file /etc/nginx/nginx.conf syntax is ok","__REALTIME_TIMESTAMP":"1773540415123439".......

日志流向#

image-20260315130504144
image-20260315130504144

  1. 消息通过 /dev/log → 被 systemd-journald 接收 ✅

    ==所有日志首先由 journald 收集==

  2. journald 将其存入 二进制 journal 日志

    位置取决于是否启用 持久化

    • 临时:/run/log/journal/...
    • 持久:/var/log/journal/...
  3. 如果 rsyslog 正在运行,它会从 journald 接收日志

    • 根据 /etc/rsyslog.conf 中的规则、决定是否写入文本文件

rsyslog基础#

  • 日志过滤:支持基于设施(facility)、优先级(priority)、内容等条件进行精细过滤
  • 日志存储:将日志写入本地文件(如 /var/log/messages等)
  • 日志转发:可通过 TCP/UDP 将日志发送到远程日志服务器(集中式日志管理)
  • 格式自定义:支持模板(template)来自定义日志输出格式
Terminal window
# 它是 Linux 系统中用来管理 日志记录 的主配置文件
'它告诉系统:哪些日志要保存到哪里'
==============================
🌟 大白话解释:
你可以把 rsyslog 想成一个“日志快递员”,它负责把系统里各种程序产生的日志(比如登录、错误、邮件等)送到指定的文件里去存起来
这个配置文件就是告诉快递员:“你收到不同类型的包裹(日志),就送到不同的地址(日志文件)”
==============================
[root@R11 ~]# egrep -v '^$|^#' /etc/rsyslog.conf
global(workDirectory="/var/lib/rsyslog")
👉 设置 rsyslog 的工作目录,相当于它的“办公室”
module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat")
👉 启用写日志到文件的功能,
# 并且用传统的格式(比如时间、主机名、信息等)
module(load="imuxsock")
SysSock.Use="off")
👉 关闭通过本地 socket 接收日志的方式
# (现在用 systemd 日志了,所以关掉)
module(load="imjournal"
UsePid="system"
FileCreateMode="0644"
StateFile="imjournal.state")
👉读取 systemd 的日志(也就是现在的系统日志来源),并设置权限和状态保存文件
include(file="/etc/rsyslog.d/*.conf" mode="optional")
👉 包含 /etc/rsyslog.d/ 目录下的其他配置文件(如果有),方便分模块管理
# 包含子配置文件
==============================
📦 最关键的部分:日志分发规则
*.info;mail.none;authpriv.none;cron.none /var/log/messages
# 所有级别为 info 及以上的日志都记到 /var/log/messages,但排除 mail、authpriv、cron 类的日志(因为它们有专门的地方)
authpriv.* /var/log/secure
# 所有认证相关的日志(如 SSH 登录、su 切换用户)
mail.* -/var/log/maillog
# 所有邮件相关的日志
cron.* /var/log/cron
# 定时任务(crontab)的日志
*.emerg :omusrmsg:*
# 如果出现紧急错误(emerg),直接弹出提示给当前用户
uucp,news.crit /var/log/spooler
# 某些旧系统服务的严重错误日志
local7.* /var/log/boot.log
# 特定用途的日志(比如开机过程)

✅ 总结一句话: 这个配置文件就是告诉系统:谁的日志,记到哪个文件里,并且怎么处理

  • 常见日志文件
文件说明
/var/log/messages通用系统日志(多数发行版)
/var/log/secure系统用户登录、登出
/var/log/maillog邮件系统日志
/var/log/cron定时任务日志
/var/log/auth.log认证相关日志(如 SSH 登录)
Tip
  • 主配置文件:/etc/rsyslog.conf

  • 模块化配置目录:/etc/rsyslog.d/

  • 修改完配置文件后,记得 重启 rsyslog 服务:

    ==systemctl restart rsyslog==

Terminal window
[root@R11 ~]# systemctl is-active rsyslog.service
active
# 服务是活跃状态!
# 自定义日志的格式!
[root@R11 ~]# vim /etc/rsyslog.conf
[root@R11 ~]# cat /etc/rsyslog.conf | grep -C 1 local7
# Save boot messages also to boot.log
local7.* /var/log/boot.log
local6.* /var/log/testlog
----------------------------------------------
facility.severity destination
'设施/来源.严重级别 动作'
local是syslog预留的本地自定义设施!供用户或应用程序自己使用
local6是来自 local6 设施的日志
'这个6是设施的编号,不是日志级别!'
# *是通配符,表示所有的日志级别
所以 local6.* 的意思是:
“把 所有来自 local6 设施、任意严重级别 的日志,都写入到指定文件”

日志级别#

数值级别(Level)说明
7debug调试信息(需编译时启用 --with-debug
6info一般信息
5notice通知信息(正常但值得注意)
4warn警告信息(可能有问题)
3error错误信息(请求处理出错)
2crit严重错误
1alert必须立即处理的问题
0emerg系统不可用
Note
  • ==数值越小,级别越高、越严重==
Terminal window
local6.info /var/log/test.log
# 记录 info 级别以及比 info 更严重(即数值 ≤6)的所有日志
如何记录不同的日志级别???
# 可以用;分号进行分隔开!
local6.info;local6.notice;local6.warn
'同一设施的不同日志级别!'
# 精确匹配单一优先级
local6.=info /var/log/test.log

动作类型#

动作类型示例说明
文件/var/log/messages写入指定文件
远程服务器@192.168.1.1UDP发送;@@192.168.1.1 TCP发送发送给远程服务器
丢弃~丢弃匹配的消息
Terminal window
local6.* @@远程服务器IP:端口
==================================
所有来自 local6 设施、任意严重级别的日志,都写入到远程服务器中的xx端口

logger命令#

logger 是一个命令行工具,用于 向系统日志发送消息

  • 所有 logger 消息 首先被 journald 接收

默认行为#

Terminal window
执行:logger "Hello world"
默认行为:
Facility(设施):user
Priority(优先级):notice
所以完整等价于:
logger -p user.notice "Hello world"
Terminal window
[root@R11 ~]# logger "Hello world"
[root@R11 ~]# journalctl -g "Hello world"
Mar 15 13:57:46 R11 root[2814]: Hello world
# 所有日志首先由 journald 收集
[root@R11 ~]# grep -r "Hello world" /var/log/
/var/log/messages:Mar 15 13:57:46 R11 root[2814]: Hello world
# 我们递归过滤一下,发现/var/log/messages也有!
[root@R11 ~]# tail -5 /var/log/messages
........
Mar 15 13:57:46 R11 root[2814]: Hello world
========================
logger -p user.notice "Hello world"
# 和上面那条命令等价!
我们来看一下/etc/rsyslog.conf中的配置
*.info;... /var/log/messages
user.notice 属于 *.info(notice info)
所以也会写入 /var/log/messages

-p 指定#

  • logger -p local6.info "msg" 的行为

  • Facility = local6

  • Priority = info

Terminal window
[root@R11 ~]# grep local6 /etc/rsyslog.conf
local6.* /var/log/testlog
[root@R11 ~]# ll /var/log/testlog
ls: cannot access '/var/log/testlog': No such file or directory
[root@R11 ~]# systemctl restart rsyslog.service
# 重启有点慢,稍微等一会!
[root@R11 ~]# logger -p local6.info "jiuzhao996"
# 手动发消息!
[root@R11 ~]# journalctl -g "jiuzhao996"
Mar 15 14:22:39 R11 root[2964]: jiuzhao996
# journal肯定能捕捉到!
[root@R11 ~]# ll /var/log/testlog
-rw------- 1 root root 43 Mar 15 14:22 /var/log/testlog
[root@R11 ~]# tail /var/log/testlog
Mar 15 14:22:39 R11 root[2964]: jiuzhao996
'这是我们刚写的配置,local6.* 的日志都流向这个文件'
[root@R11 ~]# tail -1 /var/log/messages
Mar 15 14:22:39 R11 root[2964]: jiuzhao996
# messages也有;*.info(notice ≥ info)

==日志流向:==

  1. 同样先被 journald 接收 → 存入 journal(可通过 journalctl 查看)

  2. rsyslog 收到后,检查配置文件(如 /etc/rsyslog.conf/etc/rsyslog.d/*.conf

  3. 如果你有如下规则:

    • local6.* /var/log/testlog

    • 那么这条日志就会额外写入 /var/log/testlog

✅ 所以:这条日志会出现在三个地方

  1. journalctl(所有日志都经过 journald)
  2. /var/log/messages(如果 rsyslog 的主规则匹配 *.info
  3. /var/log/testlog(因为 local6.* 规则)

🎯实验#

Terminal window
'服务端配置!'
[root@R39 ~]# ls /etc/rsyslog.d/
# 这个是子配置文件的目录!
'下面所有的配置文件都被包含在主配置文件里面!'
# 很显然里面什么东西都没有!
[root@R39 ~]# ls -l /etc/resolv.conf
-rw-r--r-- 1 root root 94 Mar 12 12:15 /etc/resolv.conf
# 这个是主配置文件
[root@R39 ~]# vim /etc/rsyslog.d/getremote.conf
# 手动创建一个配置文件,用来接受客户端的消息!
module(load="imtcp")
# 加载 TCP 输入模块(注意是 imtcp)
# 这个模块在整个配置中只需要加载一次
input(type="imtcp" port="10514")
# 监听 TCP 10514 端口
$template RemoteLogs,"/var/log/remote/%fromhost-ip%/%programname%_%$YEAR%-%$MONTH%-%$DAY%.log"
# 定义模板:名字是RemoteLogs
# 按 远程IP + 程序 + 日期 分隔日志文件
*.* ?RemoteLogs
# 把所有接收到的远程日志
#(*.* 表示任何设施.任何级别)都用 RemoteLogs 模板写入文件
# ?RemoteLogs:调用上面定义的模板
& stop
# 停止本地处理,避免重复记录
[root@R39 ~]# systemctl restart rsyslog.service
# 重启服务!
[root@R39 ~]# ss -anptul | grep 10514
tcp LISTEN 0 25 0.0.0.0:10514 0.0.0.0:* users:(("rsyslogd",pid=3916,fd=4))
tcp LISTEN 0 25 [::]:10514 [::]:* users:(("rsyslogd",pid=3916,fd=5))
Terminal window
'回到客户端!'
[root@R11 ~]# vim /etc/rsyslog.conf
.....
# Save boot messages also to boot.log
local7.* /var/log/boot.log
local6.* @@10.0.0.139:10514
# 一有日志就一tcp方式写入到远程主机的10514端口!
[root@R11 ~]# systemctl restart rsyslog.service
[root@R11 ~]# logger -p local6.info "this is a message from A"
# 手动发送日志
切换回服务端验证:
[root@R39 ~]# ll /var/log/remote/
total 0
drwx------ 2 root root 33 Mar 12 15:28 10.0.0.111
drwx------ 2 root root 133 Mar 12 15:27 127.0.0.1
[root@R39 ~]# cd /var/log/remote/10.0.0.111/
[root@R39 10.0.0.111]# ll
total 4
-rw------- 1 root root 57 Mar 12 15:28 root_2026-03-12.log
[root@R39 10.0.0.111]# cat root_2026-03-12.log
Mar 12 15:28:41 R11 root[3570]: this is a message from A
# 成功出来了
[root@R39 10.0.0.111]# tree /var/log/remote/
/var/log/remote/
├── 10.0.0.111
│   └── root_2026-03-12.log
└── 127.0.0.1
├── kernel_2026-03-12.log
├── NetworkManager_2026-03-12.log
├── rsyslogd_2026-03-12.log
└── systemd_2026-03-12.log

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

日志流向&&管理
https://www.kpyun.fun/posts/basics/extension/extension05/
作者
久棹
发布于
2025-09-16
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录