一、rsyslog 是什么?它解决了什么问题?
1. 核心作用
rsyslog( rocket-fast system for log processing)是一个高性能的日志处理守护进程。它的职责是:
按照规则采集系统中产生的日志,并根据配置把日志写到指定的位置(文件、远程服务器、数据库等)
通俗地说,操作系统内核、各种服务(ssh、http、邮件、定时任务)都在不停地输出日志。rsyslog 像一个"日志快递分拣中心"——它接收所有日志,然后根据你制定的规则,把不同种类的日志投递到不同的目标。
2. 为什么需要远程日志?
| 场景 | 问题 | 远程日志解决 |
|---|---|---|
| 服务器宕机 | 日志存在本地,机器挂了日志也读不了 | 日志实时发到远程,服务器挂了也能查 |
| 入侵溯源 | 攻击者登录后会清理本地日志 | 远程日志无法被攻击者篡改 |
| 多机审计 | 几十台机器一台台查太慢 | 一台日志服务器集中查看所有日志 |
| 合规要求 | 等保/sox 要求日志集中归档 | 统一存储、统一备份 |
二、linux 系统日志分类详解
在 linux 中,日志并不是杂乱无章地堆在一起。rsyslog 默认按照 程序功能 把日志写入不同的文件。
| 日志文件 | 存放内容 | 典型场景 |
|---|---|---|
| /var/log/messages | 通用系统消息和服务启动/报错信息 | 应用程序崩溃、网络服务异常 |
| /var/log/secure | 认证相关的安全日志 | ssh 登录成功/失败、sudo 操作 |
| /var/log/maillog | 邮件服务器日志 | sendmail/postfix 收发记录 |
| /var/log/cron | 定时任务执行日志 | crontab 执行结果、报错 |
| /var/log/boot.log | 系统启动过程的日志 | 内核加载、服务自启状态 |
记忆技巧:文件名就暗示了用途——secure 管安全、maillog 管邮件、cron 管定时任务,一眼就能看出是干什么的。
三、rsyslog 日志采集规则:类型 × 级别
rsyslog 的规则核心只有两件事:什么类型 + 什么级别。
1. 日志类型(facility)—— 谁产生的日志
| 类型 | 含义 | 说明 |
|---|---|---|
| auth | 用户认证 | 用户登录/登出验证 |
| authpriv | 服务认证 | ssh、sudo 等服务的认证信息 |
| cron | 定时任务 | crond 相关的日志 |
| kern | 内核日志 | 内核输出的信息(优先级高) |
| 邮件系统 | 邮件服务产生的日志 | |
| news | 新闻组/更新信息 | 一般较少用到 |
| user | 用户级别日志 | 普通用户程序产生的日志 |
2. 日志级别(severity)—— 日志有多严重
级别从低到高排列:
| 级别 | 含义 | 严重程度 |
|---|---|---|
| debug | 调试信息 | 🟢 最低 |
| info | 普通信息 | 🟢 |
| notice | 重要信息 | 🟡 |
| warning | 警告 | 🟡 |
| err | 错误 | 🟠 |
| crit | 严重错误 | 🔴 |
| alert | 必须立即处理 | 🔴 紧急 |
| emerg | 系统濒临崩溃 | 🔴 最高 |
| none | 不采集 | — |
原理一句话:级别是向下包含的。如果你指定了 err,那么 err + crit + alert + emerg 都会被记录下来。级别越低包含的范围越大。
3. 规则语法:类型.级别
*.* → 所有类型的所有级别(最全的日志) authpriv.err → authpriv 类型的 err 及以上级别 *.*;auth.none → 所有类型所有级别,但排除 auth 类型 kern.debug → 内核的 debug 及以上级别
语法结构:
<类型>.<级别> 动作
逗号 ; 分隔多条规则,. 前面是类型、后面是级别。none 特殊级别表示"不采集这个类型"。
四、本地日志规则配置
4.1 采集所有日志到一个自定义文件
操作命令
vim /etc/rsyslog.conf
在文件末尾追加一行:
*.* action(type="omfile" file="/var/log/qwe")
然后重启服务:
systemctl restart rsyslog
逐行解释
| 配置/命令 | 解释 |
|---|---|
| *.* | 第一个 * = 所有日志类型,第二个 * = 所有日志级别。含义:不管什么类型的日志、不管多严重的级别,全部采集 |
| action(type="omfile" file="/var/log/qwe") | action 是 rsyslog 的动作声明;type="omfile" 表示输出模块是写文件(output module file);file="/var/log/qwe" 指定输出的目标文件路径。注意:没有写绝对路径的开头 /,实际应写 /var/log/qwe,这里原笔记略有省略但 rsyslog 默认相对路径基于 / |
| systemctl restart rsyslog | 重启 rsyslog 服务使配置生效。每次修改 rsyslog.conf 必须重启 |
测试验证
cat /var/log/qwe
你会看到系统中所有类型的日志都被写入了这个文件——包括内核、服务、认证等。这说明规则生效了。

4.2 排除某个类型的日志
场景
我们希望采集"除了服务认证(authpriv)之外的所有日志"。因为 secure 文件已经记录了认证信息,重复采集浪费空间。
配置
*.*;authpriv.none action(type="omfile" file="/var/log/qwe")
原理
这条规则拆开理解:
*.*— 所有类型所有级别authpriv.none— 但类型为 authpriv 的日志不采集(none是排除指令)- 分号
;表示"同时满足"——先包含全部,再排除指定类型
效果:除了 ssh 登录、sudo 等认证日志之外,其他所有日志都写入 /var/log/qwe。
测试方法
# 在另一台机器上尝试 ssh 登录 ssh -l root 192.168.17.138 # 查看 qwe 文件,应该没有 ssh 相关的日志 cat /var/log/qwe
同时可以对比 /var/log/secure 的内容——认证日志只出现在了 secure 中,说明我们的排除规则生效了。

注意:排除规则必须写在包含规则前面,以 ; 连接。rsyslog 按顺序匹配规则,先遇到谁就执行谁。
4.3 清空日志文件
> /var/log/qwe
这个命令用 > 重定向符清空文件内容,相当于 : > /var/log/qwe 或 truncate -s 0 /var/log/qwe。测试前清空文件,方便对比观察新的日志是否被正确写入。
五、自定义日志格式
5.1 为什么需要自定义格式?
默认的日志格式包含的信息比较有限。在生产环境中,我们往往需要知道:
- 日志是什么时候产生的(不是写入时间,而是事件发生时间)
- 是哪台机器产生的(多机集中管理时尤为重要)
- 是哪个程序输出的
- 具体内容是什么
5.2 自定义模板
配置
vim /etc/rsyslog.conf
加入以下内容:
$template lee, "%timegenerated% %fromhost-ip% %syslogtag%: %msg%\n" *.*;authpriv.none action(type="omfile" template="lee" file="/var/log/lee")

模板参数详解
| 参数 | 含义 | 示例值 |
|---|---|---|
| %timegenerated% | 日志生成的时间戳 | jul 30 10:52:44 |
| %fromhost-ip% | 产生日志的主机 ip 地址 | 192.168.17.131 |
| %syslogtag% | 产生日志的程序名称 | sshd, crond, root |
| %msg% | 实际的日志内容 | session opened for user root |
| \n | 换行符,每条日志占一行 | — |
整条配置的含义:
- 第一行
$template lee, ...— 定义一个名为lee的日志格式模板 - 第二行
*.*;authpriv.none action(... template="lee" ...)— 在写入动作中引用这个模板 - 最终写入文件的日志格式就是:
时间 ip 程序名: 内容
重启服务
systemctl restart rsyslog.service
5.3 测试自定义格式
# 清空之前的日志 > /var/log/qwe # 使用 logger 命令手动生成一条日志 logger test # 查看自定义格式的日志文件 cat /var/log/lee
logger 是 linux 内置的向 syslog 发送日志的命令行工具。运行 logger test 会生成一条内容为 test 的日志,经由 rsyslog 处理后写入 /var/log/lee。

输出示例:
jul 30 23:39:22 192.168.17.131 root: test
对比:如果不用自定义模板,默认格式可能缺少 ip 和时间信息。在远程日志场景中,%fromhost-ip% 是最关键的字段——它让你知道日志来自哪台机器。
六、远程日志同步
这是本文的核心——搭建一台 日志服务器,让网络中所有 linux 机器把日志实时发送过来。
6.1 架构原理
┌──────────────────────┐ udp 514 ┌──────────────────────┐ │ 发送方(client) │ ──────────────────────> │ 接收方(server) │ │ 192.168.17.131 │ │ 192.168.17.138 │ │ │ syslog 协议 │ │ │ rsyslog 收集本机日志 │ (基于 udp) │ 按来源 ip + 程序名 │ │ 然后转发到远程 │ │ 自动分类存储 │ └──────────────────────┘ └──────────────────────┘
通信原理:
- rsyslog 支持通过 udp 514 端口 传输日志(也支持 tcp)
- udp 传输速度快、开销小,但不保证送达——日志丢失一两行是可以容忍的(因为日志是持续产生的)
- 接收方通过
imudp模块(input module udp)监听 udp 514 端口 - 发送方使用
@符号指定远程目标(一个@是 udp,两个@@是 tcp)
6.2 接收方配置(日志服务器)
接收方就是我们的 日志服务器,负责接收所有其他机器发来的日志。
步骤 1:编辑配置文件
vim /etc/rsyslog.conf
在文件末尾或合适位置加入以下内容:
# 定义日志存储路径模板:按来源 ip 和程序名分目录存放 $template remotebyip, "/var/log/remote/%fromhost-ip%/%programname%.log" # 定义日志格式模板:时间 + 来源ip + 程序名 + 内容 $template remoteformat, "%timegenerated% %fromhost-ip% %syslogtag%: %msg%\n" # 非本机产生的日志,按 remotebyip 模板、remoteformat 格式写入 :source, !isequal, "localhost" -?remotebyip;remoteformat # 非本机日志处理完后,不再继续往下匹配(丢弃) :source, !isequal, "localhost" ~ # 加载 udp 输入模块(只需加载一次) module(load="imudp") # 在 514 端口启动 udp 监听 input(type="imudp" port="514")

每行解释
| 配置 | 解释 |
|---|---|
| $template remotebyip, "/var/log/remote/%fromhost-ip%/%programname%.log" | 定义了一个名为 remotebyip 的路径模板。日志会按 来源ip/程序名.log 的结构存放。例如来自 192.168.17.131 的 ssh 日志存在 /var/log/remote/192.168.17.131/sshd.log |
| $template remoteformat, "%timegenerated% %fromhost-ip% %syslogtag%: %msg%\n" | 定义日志内容格式模板,包含时间、来源 ip、程序标签、消息内容 |
| :source, !isequal, "localhost" -?remotebyip;remoteformat | 条件判断:如果日志来源(source)不等于(!isequal)本机(localhost),则按照 remotebyip 路径和 remoteformat 格式写入。-? 中的 - 表示异步写入(先写缓冲区再落盘,提高性能),? 后面跟模板名 |
| :source, !isequal, "localhost" ~ | 上一条把非本机日志写入了文件,这一条用 ~(波浪号表示 丢弃)告诉 rsyslog:非本机日志处理完了,不要再往下匹配了。防止日志被重复处理 |
| module(load="imudp") | 加载 imudp 输入模块(input module for udp)。这是 rsyslog 的插件化架构——模块按需加载,不用不加载 |
| input(type="imudp" port="514") | 在 udp 514 端口上启动监听。514 是 syslog 的标准端口,低于 1024 的端口需要 root 权限 |
核心原理:$template 定义"怎么写",:source, !isequal 定义"哪些写",module(load="imudp") 定义"怎么收"。三条各司其职。
步骤 2:重启服务并验证端口
systemctl restart rsyslog # 查看 udp 514 端口是否在监听 netstat -antlupe | grep rsyslog
udp 0 0 0.0.0.0:514 0.0.0.0:* 0 148148 37733/rsyslogd udp6 0 0 :::514 :::* 0 148149 37733/rsyslogd
| 输出字段 | 含义 |
|---|---|
| udp | 协议是 udp |
| 0.0.0.0:514 | 监听所有网卡的 514 端口 |
| 0.0.0.0:* | 接受来自任何 ip 的连接 |
| 37733/rsyslogd | 进程 pid 和进程名,说明确实是 rsyslog 在监听 |
| udp6 :::514 | ipv6 版本的同端口监听 |
6.3 发送方配置(被收集的机器)
操作命令
vim /etc/rsyslog.conf
在文件末尾添加一行:
*.* @192.168.17.138
重启服务:
systemctl restart rsyslog
逐行解释
| 配置 | 解释 |
|---|---|
| *.* | 所有类型、所有级别的日志。发送方一般把全部日志都发出去,接收方来筛选和归类 |
| @192.168.17.138 | 一个 @ 表示使用 udp 协议发送到目标 ip 的 514 端口(默认端口,可省略)。如果是 @@192.168.17.138 则使用 tcp 协议 |
@ vs @@:
@= udp(速度快,无连接,可能丢包)→ 适合局域网内部日志收集@@= tcp(可靠性高,开销大)→ 适合跨公网、重要日志传输
6.4 测试远程日志同步
步骤 1:发送方生成测试日志
# 在发送方(192.168.17.131)执行 logger test
logger test 会生成一条内容为 test 的日志,logger 命令的默认程序标签是当前用户名(这里是 root)。
步骤 2:接收方查看远程日志
# 在接收方(192.168.17.138)执行 cat /var/log/remote/192.168.17.131/root.log

结果分析
| 字段 | 值 | 说明 |
|---|---|---|
| 时间 | jul 30 10:52:44 | 日志在发送方产生的时间(%timegenerated%) |
| 来源 ip | 192.168.17.131 | 发送方的 ip 地址(%fromhost-ip%) |
| 程序名 | root | 产生日志的程序(这里是 logger 命令,标签为当前用户名) |
| 内容 | test | 实际的日志消息 |
至此,远程日志同步搭建成功! 发送方的任何日志都会实时传输到接收方,并按 来源ip/程序名.log 的目录结构自动归档。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论