1. 项目概述:为什么你需要吃透rsyslog配置?
如果你负责过线上服务器的运维,或者开发过需要处理海量日志的应用,那你大概率跟rsyslog打过交道。它几乎是Linux世界日志收集的“事实标准”,从系统内核消息到Nginx访问日志,再到你自己应用的业务日志,最终都可能汇聚到rsyslog这个管道里。但说实话,很多人对它的配置都停留在“能用就行”的阶段,从网上抄一段*.info /var/log/messages就完事了。一旦遇到日志分类、远程转发、性能瓶颈或者格式解析的问题,面对那一堆$开头的指令和复杂的配置块,往往就抓瞎了。
我自己在管理一个日均TB级日志量的集群时,就曾因为一个配置不当的队列参数,导致日志大量堆积,差点错过一次关键的业务告警。从那以后,我花了大力气把rsyslog,特别是v7和v8这两个主流且兼容性强的版本,从里到外啃了一遍。这篇文章,就是把我这些年踩过的坑、总结出的最佳实践,结合官方文档的精髓,给你掰开揉碎了讲清楚。我们的目标很明确:告别“复制粘贴”,让你真正理解每一行配置背后的逻辑,打造一个既稳定又高效的日志处理中枢。无论是刚接触的运维新手,还是想优化现有架构的老手,这篇详解都能给你直接的帮助。
2. 核心概念与配置结构解析
在动手写配置之前,我们必须先建立几个核心的认知模型。rsyslog的配置不是一堆随意堆砌的命令,它遵循一个清晰的“管道”处理流程:输入(Input) -> 处理(Parse, Filter) -> 输出(Output)。v7/v8版本强化了这个模块化设计,让每个环节都可以通过加载插件(om、im、mm开头)来扩展功能。
2.1 配置文件的核心骨架
一个典型的rsyslog配置文件(通常是/etc/rsyslog.conf或/etc/rsyslog.d/*.conf)遵循以下结构,理解这个结构是读懂一切配置的前提:
# 1. 全局指令 (Global Directives) # 设置rsyslog守护进程本身的参数,如工作目录、队列大小、加载的模块等。 $WorkDirectory /var/spool/rsyslog $ActionQueueSize 100000 module(load="imuxsock") # 加载模块 # 2. 模块加载 (Modules) # 显式加载需要的输入、输出、解析器等模块。这是v7/v8的推荐写法。 module(load="imfile" PollingInterval="10") # 加载文本文件输入模块 module(load="omelasticsearch") # 加载ES输出模块 # 3. 规则集 (Rulesets) # 规则集是规则(选择器+动作)的容器。可以定义多个,实现日志流的分流处理。 ruleset(name="infra_logs") { # 规则在这里定义 } ruleset(name="app_logs") { # 另一个规则集 } # 4. 规则:选择器 + 动作 (Rules: Selector + Action) # 这是最传统的配置形式,也是配置的核心。 # 选择器部分 [设施.优先级] # 动作部分 [处理方式] mail.info /var/log/mail.log # 含义:将mail设施下,优先级为info及以上(含info, notice, warn, err...)的日志,写入指定文件。 # 5. 模板 (Templates) # 定义日志的输出格式。对于文件、数据库、远程转发都至关重要。 template(name="MyFormat" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%\n") # 6. 输入 (Inputs) # 定义日志的来源。传统配置隐含了系统syslog socket作为输入,现代配置需要显式声明。 input(type="imfile" file="/var/log/nginx/access.log" tag="nginx-access" ruleset="app_logs")一个关键转变:在老的语法($ModLoad)中,模块和规则是混在一起的。在新的高级语法(module()和action())中,结构更清晰。我强烈建议,即使在维护旧系统,也尽量向新语法迁移,因为它的可读性和可维护性要好得多。
2.2 设施(Facility)与优先级(Priority/Severity):选择器的灵魂
这是过滤日志最基础、最重要的依据,必须记牢。
设施 (Facility): 代表日志消息的来源或子系统。常用的有:
auth,authpriv: 安全和认证相关消息。cron: 定时任务。daemon: 系统守护进程。kern: 内核消息。mail: 邮件系统。syslog: rsyslog自身产生的消息。user: 用户级程序(默认值)。local0~local7: 留作自定义使用,这是你分配给自己应用的关键编号。比如,约定local0给Nginx,local1给MySQL。
优先级 (Priority): 代表日志的严重等级,从低到高依次是:
debug: 调试信息,最详细。info: 一般性信息。notice: 正常但值得注意的事件。warning或warn: 警告信息。err或error: 错误条件。crit: 严重条件。alert: 需要立即行动。emerg或panic: 系统不可用。
选择器写法:
mail.info: 匹配mail设施,info及以上等级。*.info: 匹配所有设施,info及以上等级。cron.=info: 仅匹配cron设施的info等级(精确匹配)。cron.!info: 匹配cron设施,除info外的所有等级。cron.*: 匹配cron设施的所有等级。cron.none: 不记录cron设施的任何日志。常用于排除某些日志。
实操心得: 给自己公司的应用分配
local0-local7时,一定要形成文档并团队共享。曾经有团队因为两个服务误用了同一个local设施,导致日志混在一起难以区分,排查问题时浪费了大量时间。一个简单的内部Wiki页面就能避免这个问题。
3. 常用核心模块与指令详解
rsyslog的强大,很大程度上来自于其丰富的模块。下面我们深入几个最常用、也最容易出问题的模块。
3.1 输入模块:日志从哪里来?
除了默认的系统日志,我们经常需要收集文本文件、甚至监听TCP/UDP端口。
1. imfile:收集文本文件日志(如Nginx, Tomcat日志)这是最常用的输入模块之一。配置不当会导致日志丢失或重复。
module(load="imfile" PollingInterval="10") # 加载模块,并设置轮询间隔为10秒 input(type="imfile" File="/var/log/nginx/access.log" # 要监控的文件路径 Tag="nginx-access:" # 给日志打上标签,强烈建议末尾加冒号,格式更规范 Severity="info" # 设置默认的日志级别 Facility="local0" # 设置默认的设施,这里我们自定义为local0 PersistStateInterval="100" # 持久化文件状态(记录读取位置)的间隔,行数。防止重启后重复读取或丢失。 ruleset="nginxRules" # 绑定到指定的规则集进行处理 )PollingInterval: 轮询间隔。文件变化不频繁可以设大点(如30),频繁则设小点(如1)。太小会增加CPU负担。PersistStateInterval:这是关键参数!它指定rsyslog在读取多少行后,将当前文件偏移量(即读到哪了)记录到磁盘状态文件(通常在$WorkDirectory下)。如果rsyslog崩溃或重启,它会从这个位置恢复,避免重复或丢失。对于日志量大的文件,建议设置为100-1000。设得太小影响性能,太大则重启后可能重复读取较多行。
2. imtcp / imudp:接收远程syslog用于构建集中式日志服务器。
module(load="imtcp" MaxSessions="500") # 加载TCP输入模块,设置最大连接数 input(type="imtcp" port="514" ruleset="remote") # 在514端口监听TCP连接 module(load="imudp") # 加载UDP输入模块 input(type="imudp" port="514") # 在514端口监听UDP数据包- TCP vs UDP:生产环境强烈推荐TCP。TCP是可靠的,能确保日志不丢失(在网络抖动、接收方繁忙时会有重传和排队)。UDP性能好但不可靠,日志可能静默丢失。对于安全审计等场景,必须用TCP。
MaxSessions: 限制并发连接数,防止恶意连接耗尽资源。
3.2 输出模块:日志到哪里去?
1. omfile:写入本地文件最基础的输出,但也有很多学问。
# 使用模板定义文件写入格式 template(name="FileFormat" type="string" string="/data/logs/%HOSTNAME%/%PROGRAMNAME%.log") # 动作:将消息写入动态命名的文件 action(type="omfile" dynaFile="FileFormat" dirCreateMode="0755" fileCreateMode="0644")- 动态文件名: 使用
dynaFile配合模板,可以按主机名、程序名、日期等自动创建目录和文件,管理起来非常清晰。例如上面的配置会生成如/data/logs/web-server01/nginx.log的路径。 - 文件权限:
dirCreateMode和fileCreateMode可以确保创建的目录和文件拥有安全的权限。
2. omfwd:转发到远程syslog服务器这是实现日志集中化的发送端配置。
action(type="omfwd" Target="log-central.example.com" Port="10514" Protocol="tcp" # 使用tcp Queue.Size="100000" # 内存队列大小 Queue.DiscardMark="97500" # 队列达到此值时开始丢弃 Queue.DiscardSeverity="8" # 丢弃优先级>=8(即info及以下)的日志 Queue.SaveOnShutdown="on" # 关闭时保存队列到磁盘 Queue.WorkerThreads="4" # 工作线程数 action.resumeRetryCount="-1" # 无限重试 )- 队列(Queue): 这是
omfwd(以及许多其他输出)最核心的稳定性保障机制。当网络中断或远程服务器不可达时,日志会先堆积在队列里。Queue.Size: 内存队列的最大消息数。根据内存和日志量设置,通常1万到10万。Queue.DiscardMark/DiscardSeverity:“丢卒保车”策略。当队列满到DiscardMark(如97500)时,开始丢弃严重性低于DiscardSeverity(数值越大越不严重,8对应info)的日志,优先保证error、crit等高优先级日志能被发送。这是一个非常重要的生产环境配置。Queue.SaveOnShutdown: 启用后,关闭时队列内容会保存到磁盘,下次启动时恢复。务必开启。Queue.WorkerThreads: 处理队列的工作线程,提高并发发送能力。action.resumeRetryCount="-1": 连接失败后无限重试,确保最终送达。
踩坑实录: 曾经有一次,日志中心网络升级,短暂中断了2分钟。发送端没有配置队列,导致那段时间所有的
error日志全部丢失,而info日志因为直接丢弃,我们甚至不知道发生过中断。配置了合理的队列和丢弃策略后,即使网络中断半小时,也只会丢失部分低优先级日志,所有高优先级告警都能在恢复后送达。
3. omelasticsearch:写入Elasticsearch对于现代日志分析栈,这是必会项。
module(load="omelasticsearch") template(name="estemplate" type="list" option.json="on") { constant(value="{") constant(value="\"@timestamp\":\"") property(name="timereported" dateFormat="rfc3339") constant(value="\",\"host\":\"") property(name="hostname") constant(value="\",\"severity\":\"") property(name="syslogseverity-text") constant(value="\",\"tag\":\"") property(name="syslogtag") constant(value="\",\"message\":\"") property(name="msg" format="json") constant(value="\"}") } action(type="omelasticsearch" server="es-node01" serverport="9200" template="estemplate" searchIndex="syslog-%$YEAR%.%$MONTH%.%$DAY%" # 按日期分索引 bulkmode="on" # 启用批量提交,极大提升性能 action.resumeretrycount="-1" queue.type="linkedlist" # 使用链表队列,性能更好 queue.size="100000" queue.saveonshutdown="on" )- 模板必须是JSON:
option.json="on"确保输出是合法的JSON。property(name="msg" format="json")会对消息内容进行JSON转义,防止破坏结构。 - 批量模式(bulkmode):务必开启。它将多条日志打包成一个HTTP请求发送,比单条发送性能高出几个数量级。
- 按日期分索引: 像
syslog-2024.04.15这样,便于在ES中进行生命周期管理(ILM),定期删除或归档旧数据。
3.3 模板:定义日志的“样子”
模板决定了日志的最终格式,无论是写文件还是发往网络。
1. 字符串模板 (string)最简单直接,使用占位符(property)。
template(name="SimpleFile" type="string" string="%timegenerated% %HOSTNAME% %syslogtag%%msg%\n" )常用属性(property):
%timegenerated%: 消息到达rsyslog的时间。%timereported%: 消息中自带的时间戳(如果有的话)。%HOSTNAME%: 主机名。%syslogtag%: 标签(通常是程序名+进程ID)。%msg%: 日志消息体。%syslogseverity-text%: 优先级文本(如“info”)。%syslogfacility-text%: 设施文本(如“local0”)。
2. 列表模板 (list)更灵活,可以嵌入常量、属性,并控制JSON格式。
template(name="JsonTemplate" type="list" option.json="on") { constant(value="{") constant(value="\"timestamp\":\"") property(name="timereported" dateFormat="rfc3339") constant(value="\",\"level\":\"") property(name="syslogseverity-text") constant(value="\",\"app\":\"") property(name="programname") constant(value="\",\"pid\":") property(name="procid") constant(value=",\"message\":\"") property(name="msg" format="json") constant(value="\"}") } # 输出结果:{"timestamp":"2024-04-15T10:30:00Z","level":"error","app":"nginx","pid":12345,"message":"connection refused"}format="json": 对属性值进行JSON编码,转义引号、换行符等,这是输出到ES或任何JSON解析器所必需的。
3. 传统格式模板 (legacy)兼容旧的$template指令格式,但新项目不建议使用。
注意事项: 在定义文件路径模板时,属性替换可能会包含斜杠
/(如%programname%可能是nginx/access),这会导致创建意外的子目录。如果这不是你期望的,可以使用replace=操作在模板中过滤掉斜杠,或者确保你的标签(Tag)是规范的。
4. 高级配置与性能调优实战
当你的日志量从MB级增长到GB级甚至TB级时,默认配置很快就会成为瓶颈。以下调优经验来自真实的高负载生产环境。
4.1 规则集与队列:实现日志流编排
规则集允许你将不同的日志流导向不同的处理管道,避免所有日志挤在一条路上。
# 定义不同的规则集 ruleset(name="infra_ruleset") { # 处理基础设施日志,如系统、内核、cron if $syslogfacility-text == 'kern' then { action(type="omfile" file="/var/log/infra/kernel.log") } # 其他基础设施规则... } ruleset(name="app_ruleset") { # 处理应用日志,写入文件并转发到ES action(type="omfile" file="/var/log/app/combined.log") action(type="omelasticsearch" server="es-host" ... ) } ruleset(name="alert_ruleset") { # 专门处理告警日志,发送邮件或调用Webhook if $syslogseverity <= 3 then { # severity 3是error,数值越小越严重 action(type="ommail" server="smtp.example.com" ...) } } # 在输入处绑定规则集 input(type="imtcp" port="514" ruleset="infra_ruleset") input(type="imfile" file="/opt/myapp/*.log" tag="myapp:" ruleset="app_ruleset")主队列与动作队列:
- 主队列 (Main Queue): 位于输入和规则处理之间。默认是
Direct(直接传递),无缓冲。在高负载下,可以设置为LinkedList或FixedArray队列来缓冲。$MainMsgQueueType LinkedList # 使用链表队列作为主队列 $MainMsgQueueSize 100000 # 主队列大小 - 动作队列 (Action Queue): 如前所述,在每个
action()中配置(如Queue.Size)。当动作(如远程转发)执行较慢时,日志会在这里排队。
调优策略:
- IO密集型动作(如写本地文件): 通常不需要大队列,甚至可以用
Direct。 - 网络密集型动作(如转发到远程ES):必须配置足够大的磁盘辅助队列。这是保证可靠性的生命线。
使用磁盘队列(action(type="omfwd" Target="..." Protocol="tcp" queue.type="disk" # 使用磁盘队列,容量远大于内存 queue.filename="fwd_queue" # 队列文件前缀 queue.maxdiskspace="2g" # 队列最大磁盘占用 queue.size="1000000" # 队列可容纳的消息数(理论值,受磁盘空间限制) queue.highwatermark="800000" # 当队列达到此消息数时,开始丢弃低优先级日志 queue.lowwatermark="200000" # 当队列消费到此消息数时,停止丢弃 queue.discardseverity="8" queue.workerthreads="8" # 增加工作线程加速消费 )queue.type="disk")可以承受进程重启甚至服务器重启,数据不会丢失。highwatermark和lowwatermark实现了更平滑的流量控制。
4.2 过滤器:精确控制日志流向
除了基于设施和优先级的选择器,rsyslog支持更强大的过滤表达式。
基于属性的过滤:
if $hostname == 'web-server-01' then { action(type="omfile" file="/path/to/web01.log") } if $msg contains 'error' then { action(type="omfile" file="/path/to/errors.log") } if $syslogtag startswith 'nginx' then { call nginx_ruleset # 调用另一个规则集 }使用
prifilt()(优先级过滤器):prifilt()是传统选择器语法的函数式表达,有时在复杂规则中更清晰。if prifilt('*.info') then { ... } # 匹配所有info及以上日志
4.3 性能关键参数与监控
$MaxMessageSize: 默认是8k。如果日志行非常长(比如包含大的堆栈跟踪),需要调大这个值,否则长日志会被截断。$RepeatedMsgReduction: 默认是on,会抑制连续的重复消息。在调试时,你可能需要把它设为off来看到所有行。$ActionQueueWorkerThreads: 全局默认的动作队列工作线程数。如果有很多并发动作,增加此值可以提升吞吐。$OMFileAsyncWriting: 设置为on启用文件的异步写入,可以显著提升写文件性能,但极端情况下崩溃可能丢失最后几条日志。
监控rsyslog自身: rsyslog会通过syslog设施记录自身的状态和错误。确保你监控了这些日志:
# 在配置中捕获rsyslog自身的错误 syslog.* /var/log/rsyslog/rsyslog.log & stop # 处理完后停止,避免再匹配其他规则定期检查/var/log/rsyslog/rsyslog.log,查看是否有队列满、写入失败、模块加载失败等错误信息。
5. 完整配置案例与排错指南
让我们结合一个常见的场景,搭建一个完整的配置案例:一台应用服务器,需要收集本地系统日志、Nginx访问/错误日志、以及一个自定义Java应用的日志,并将所有日志同时写入本地归档文件,且将错误及以上级别的日志实时转发到中央Elasticsearch集群。
5.1 完整配置示例 (/etc/rsyslog.d/99-myapp.conf)
# 加载必要模块 module(load="imuxsock") # 提供本地系统日志支持 module(load="imjournal") # 从systemd journal读取(可选,但推荐) module(load="imfile" PollingInterval="10") # 监控文件 module(load="omelasticsearch") # 输出到ES module(load="mmjsonparse") # JSON解析模块(如果日志是JSON格式) # 全局设置 $WorkDirectory /var/spool/rsyslog $ActionQueueSize 100000 $MainMsgQueueSize 50000 $MaxMessageSize 64k # 适应可能的长日志 # 定义模板 # 1. 本地文件模板(传统格式) template(name="LocalFileFormat" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n") # 2. Elasticsearch JSON模板 template(name="ESTemplate" type="list" option.json="on") { constant(value="{") constant(value="\"@timestamp\":\"") property(name="timereported" dateFormat="rfc3339") constant(value="\",\"host.ip\":\"") property(name="fromhost-ip") constant(value="\",\"host.name\":\"") property(name="hostname") constant(value="\",\"log.level\":\"") property(name="syslogseverity-text") constant(value="\",\"log.facility\":\"") property(name="syslogfacility-text") constant(value="\",\"process.tag\":\"") property(name="syslogtag") constant(value="\",\"message\":\"") property(name="msg" format="json") constant(value="\",\"fields.env\":\"prod\"") # 添加自定义字段 constant(value="\"}") } # 规则集:处理所有日志,并分流 ruleset(name="all_logs") { # 首先,所有日志都写入一个本地聚合文件(用于长期归档) action(type="omfile" file="/data/logs/archive/all-%$YEAR%%$MONTH%%$DAY%.log" template="LocalFileFormat" createDirs="on" dirCreateMode="0755" fileCreateMode="0644" ) # 然后,根据严重性过滤:将error及以上日志发送到ES if $syslogseverity <= 3 then { # severity 3=err, 2=crit, 1=alert, 0=emerg action(type="omelasticsearch" server="es-cluster.example.com" serverport="9200" template="ESTemplate" searchIndex="app-prod-%$YEAR%.%$MONTH%.%$DAY%" bulkmode="on" queue.type="disk" queue.filename="es_queue" queue.maxdiskspace="1g" queue.size="500000" queue.highwatermark="400000" queue.lowwatermark="100000" queue.discardseverity="6" # 在队列压力大时,丢弃notice及以下日志 queue.workerthreads="4" action.resumeretrycount="-1" ) } # 最后,根据设施或标签,将日志分发到更具体的文件 # 系统/内核日志 if $syslogfacility-text == 'kern' then { action(type="omfile" file="/data/logs/by-facility/kernel.log") } # 通过标签识别Nginx日志 if $syslogtag startswith 'nginx-' then { # 这里可以进一步按访问/错误日志拆分 if $syslogtag == 'nginx-access:' then { action(type="omfile" file="/data/logs/nginx/access.log") } else if $syslogtag == 'nginx-error:' then { action(type="omfile" file="/data/logs/nginx/error.log") } } # 自定义Java应用日志 (使用local1设施) if $syslogfacility-text == 'local1' then { action(type="omfile" file="/data/logs/myapp/application.log") # 如果Java应用输出的是JSON,可以尝试解析 if $msg contains '{' then { # 使用mmjsonparse解析,并为字段添加前缀(.json.) action(type="mmjsonparse") # 解析后,可以通过$!all-json(原始JSON)或$!key访问具体字段 } } } # 定义输入,并绑定到总规则集 # 输入1: 传统系统日志和journal input(type="imuxsock" ruleset="all_logs") input(type="imjournal" ruleset="all_logs") # 输入2: Nginx日志文件 input(type="imfile" File="/var/log/nginx/access.log" Tag="nginx-access:" Severity="info" Facility="local0" PersistStateInterval="100" ruleset="all_logs" ) input(type="imfile" File="/var/log/nginx/error.log" Tag="nginx-error:" Severity="error" # error文件本身级别设为error Facility="local0" PersistStateInterval="50" ruleset="all_logs" ) # 输入3: 自定义Java应用日志文件 (假设应用配置了syslog,输出到local1) # 应用需要配置日志框架(如Logback)通过socket输出到localhost:514 # 这里我们直接通过TCP接收,更可靠 module(load="imtcp") input(type="imtcp" port="51401" ruleset="all_logs") # 在Java应用端,配置Logback的SyslogAppender指向此端口和local1设施。5.2 常见问题排查速查表
遇到问题别慌,按照以下顺序检查和排查:
| 现象 | 可能原因 | 排查命令与步骤 |
|---|---|---|
| 日志完全没有被收集 | 1. rsyslog服务未运行。 2. 配置文件语法错误。 3. 输入模块未正确加载或绑定。 | 1.systemctl status rsyslog2. rsyslogd -N1 -f /etc/rsyslog.d/your.conf(语法检查)3. logger -t TEST "test message"然后检查/var/log/messages或journalctl -u rsyslog看服务是否收到。 |
| imfile模块不读取文件 | 1. 文件路径错误或权限不足。 2. PersistStateInterval设置过大,状态文件损坏。3. 文件被轮转(如logrotate)后,inode变化,imfile丢失跟踪。 | 1. 检查文件是否存在,rsyslog用户(通常是syslog)是否有读权限。2. 查看状态文件 /var/spool/rsyslog/imfile-state:*,尝试删除后重启rsyslog(会从头读取)。3. 确保logrotate配置中使用了 copytruncate或postrotate脚本通知rsyslog(systemctl kill -s HUP rsyslog)。 |
| 日志没有转发到远程服务器 | 1. 网络不通或防火墙阻断。 2. 远程服务器未监听或配置错误。 3. 本地队列已满或动作被挂起。 4. DNS解析问题(如果使用主机名)。 | 1.telnet <remote_host> <port>或nc -zv <remote_host> <port>2. 检查远程服务器的rsyslog配置是否在监听对应端口。 3. 检查rsyslog状态: rsyslogctl status(如果支持) 或查看/var/log/rsyslog/rsyslog.log错误日志。4. 在配置中使用IP地址替代主机名。 |
| Elasticsearch收到空字段或格式错误 | 1. 模板JSON格式不正确。 2. msg字段未用format="json"转义,包含破坏JSON的字符。3. 索引映射(mapping)不匹配。 | 1. 使用logger命令发送一条测试消息,用omfile输出到本地文件,检查生成的JSON格式。2. 确保模板中 property(name="msg" format="json")。3. 在ES中查看索引的映射,确认字段类型(如 timestamp应为date)。 |
| rsyslog进程占用高CPU或内存 | 1. 队列过大,积压严重。 2. imfile的PollingInterval设置过小。3. 规则过于复杂或正则表达式性能差。 4. 输出目标(如ES)响应慢,阻塞了工作线程。 | 1. 检查队列状态(如果版本支持监控指标)。 2. 适当增大 PollingInterval。3. 简化过滤规则,避免在每条消息上执行昂贵的操作。 4. 检查输出目标的健康状况和网络延迟。为慢动作配置更大的磁盘队列和更多工作线程。 |
| 日志出现重复记录 | 1. 同一条日志被多个输入源捕获(如同时被imjournal和imuxsock捕获)。 2. 规则配置重复,导致同一消息触发多个动作且都写入文件。 3. imfile状态文件问题,重启后重复读取。 | 1. 检查输入配置,避免重复监听同一来源。通常只需imjournal或imuxsock之一。2. 审查规则逻辑,使用 & stop在动作后停止处理当前消息,防止它继续匹配后续规则。3. 检查并修复imfile状态文件。 |
5.3 调试与测试技巧
- 干跑测试:
rsyslogd -N1 -f /path/to/config.conf是检查语法错误的第一步,必须确保返回config is valid。 - 前台运行并输出调试信息:
rsyslogd -dn -f /path/to/config.conf。-n表示不进入后台,-d开启调试模式。这会在终端打印详细的处理过程,对排查流程问题极有帮助。 - 使用logger命令发送测试日志:
logger -p local0.info -t MYAPP "This is a test info message"发送一条设施为local0,级别为info的日志。logger -p local0.err -t MYAPP "This is a test error message"发送一条错误日志。 然后去你配置的对应文件或ES中查看是否收到,格式是否正确。
- 检查内部状态: 较新版本的rsyslog支持通过
rsyslogctl或HTTP接口查询指标(如队列深度)。请查阅对应版本的文档。 - 查看rsyslog自身日志: 永远别忘了
/var/log/rsyslog/rsyslog.log或journalctl -u rsyslog -f,这里记录了服务自身的所有错误和警告。
配置文件的管理本身也是一门学问。我建议将不同应用的配置拆分成独立的文件,放在/etc/rsyslog.d/目录下,并以数字前缀排序(如10-nginx.conf,20-myapp.conf)。这样结构清晰,便于维护和更新。每次修改配置后,使用systemctl reload rsyslog让配置生效,而不是重启,以减少服务中断。