Linux之rsyslog(5)过滤条件
文章摘要:本文详细介绍了rsyslog的四种过滤条件类型:传统选择器(基于优先级和设备)、基于属性的过滤器(支持多种比较操作)、基于表达式的过滤器(支持复杂运算)以及BSD风格块(v7+版本不再支持)。重点讲解了选择器的设备-优先级语法和扩展功能,以及基于属性过滤器的contains、isequal等操作符的使用方法。文章还提供了配置示例,如通过msg属性过滤特定消息内容,并强调正则表达式和转义字
Linux之rsyslog(5)过滤条件
Author:Once Day Date:2025年11月11日
全系列文章请查看专栏: Linux Shell基础_Once_day的博客-CSDN博客。
漫漫长路,有人对你微笑过嘛…
参考文档:
文章目录
1. rsyslog 过滤条件(Filter Conditions)
Rsyslog 提供四种不同类型的 “过滤条件”:
- 基于优先级和设备的 “传统” 选择器。
- 基于属性的过滤器。
- 基于表达式的过滤器。
- BSD 风格块(不向上兼容)。
1.1 选择器(Selectors)
选择器是过滤系统日志消息的传统方式。Rsyslog 保留了其原始语法,因为该语法广为人知、高效实用,且需兼容标准系统日志守护进程(stock syslogd)的配置文件。若仅需根据优先级和设备进行过滤,应使用选择器行。它们在 Rsyslog 中并非次要功能,而是完成该任务的最简语法。在 Rsyslog v7 之前的版本中,使用选择器行相比高级格式有显著性能优势,如今两种格式的性能已无差异。
选择器字段本身由两部分组成:设备和优先级,以句点(“.”)分隔。两部分均不区分大小写,也可指定为十进制数字,但不建议这样做,特此提醒。设备和优先级的详细说明见 syslog (3)。下文提及的名称与 /usr/include/syslog.h 中类似的 LOG_ 常量对应。
设备为以下关键字之一:auth、authpriv、cron、daemon、kern、lpr、mail、mark、news、security(与 auth 相同)、syslog、user、uucp 以及 local0 至 local7。关键字 security 不应再使用,mark 仅用于内部用途,因此不应在应用程序中使用。不过,你仍可在此指定并重定向这些消息。设备指定生成消息的子系统,例如所有邮件程序若使用系统日志记录,都会通过 mail 设备(LOG_MAIL)进行日志输出。
优先级为以下关键字之一,按严重程度升序排列:debug、info、notice、warning、warn(与 warning 相同)、err、error(与 err 相同)、crit、alert、emerg、panic(与 emerg 相同)。关键字 error、warn 和 panic 已过时,不应再使用。优先级定义消息的严重程度。
原始 BSD 系统日志守护进程(BSD syslogd)的行为是,按指定操作记录所有指定优先级及更高级别的消息。Rsyslogd 行为与之一致,但增加了部分扩展功能。
除上述名称外,rsyslogd (8) 还支持以下扩展语法:星号(“*”)表示所有设备或所有优先级,具体取决于其位置(句点之前或之后)。关键字 none 表示指定设备无任何优先级。可使用逗号(“,”)运算符在一条语句中指定多个设备,且这些设备使用相同的优先级模式。设备数量无限制,但需注意此类语句仅提取设备部分,优先级部分会被忽略。
可使用分号(“;”)分隔符为单个操作指定多个选择器。需注意,选择器字段中的每个选择器都可覆盖之前的选择器。利用这一特性,可从模式中排除部分优先级。
Rsyslogd 对原始 BSD 语法进行了扩展,使选择器的使用更直观。可在每个优先级前加等号(“=”),表示仅匹配该优先级,不包含更高级别。也可(两种方式均可)在优先级前加感叹号(“!”),表示忽略所有该优先级(仅该优先级或该优先级及更高级别)。若同时使用两种扩展语法,感叹号必须位于等号之前,按直觉使用即可。
需注意,相比传统 BSD 系统日志的行为,Rsyslog 存在部分限制。这些限制源自 sysklogd,至少可追溯至 20 世纪 90 年代,因此一直存在于 Rsyslog 中。
例如,在 BSD syslogd 中,可编写如下选择器:
*.debug;local6.err
其意图是记录所有设备的 debug 及更高级别消息,但 local6 设备仅记录 err 及更高级别消息。
但实际上,local6.err 会允许 err 及更高级别消息,但不会排除 local6 设备的低级别消息。
作为替代方案,可显式排除所有不需要匹配的严重级别。对于上述情况,以下选择器与 BSD 系统日志的选择器等效:
*.debug;local6.!=info;local6.!=notice;local6.!=warn
1.2 基于属性的过滤器
基于属性的过滤器是 rsyslogd 独有的功能。它允许根据任何属性进行过滤,例如主机名(HOSTNAME)、系统日志标签(syslogtag)和消息内容(msg)。所有当前支持的属性列表可在 rsyslog 属性文档中查询。通过该过滤器,可使用指定的比较操作,检查每个属性是否符合指定值。
基于属性的过滤器必须在第 1 列以冒号(:)开头,以此告知 rsyslogd 这是新型过滤器。冒号后需依次跟上属性名、逗号、要执行的比较操作名称、另一个逗号,最后是要比较的值(该值必须加引号)。逗号之间可包含空格和制表符。属性名和比较操作区分大小写,因此 “msg” 是有效属性名,而 “MSG” 无效。简而言之,语法如下:
:property, [!]compare-operation, "value"
目前支持以下比较操作:
-
contains(包含):检查 “比较值” 中的字符串是否包含在属性中。需完全匹配,不支持通配符。
-
isequal(完全相等):比较提供的 “比较值” 字符串与属性内容。两者必须完全一致才算匹配。与 contains 的区别在于,contains 会在属性值中任意位置搜索比较值,而 isequal 要求所有字符完全相同。因此,isequal 最适用于 syslogtag 或 FROMHOST 等已知确切内容的字段。
-
startswith(以…… 开头):检查比较值是否恰好出现在属性值的开头。例如,使用
:msg, startswith, "val"时,若 msg 内容为 “values are in this message” 则匹配,但若 msg 内容为 “There are values in this message” 则不匹配(后者可用 contains 匹配)。需注意,startswith 比正则表达式快得多,即便正则表达式已实现,从性能角度考虑,使用 startswith 仍极具意义。 -
endswith(以…… 结尾):检查比较值是否恰好出现在属性值的末尾。例如,
:programname, endswith, "_foo"会匹配程序名为 “xxx_foo” 的情况。 -
regex(基本正则表达式匹配):将属性与提供的 POSIX 基本正则表达式(BRE)进行匹配。
-
ereregex(扩展正则表达式匹配):将属性与提供的 POSIX 扩展正则表达式(ERE)进行匹配。
可在比较操作前直接加感叹号(!),表示对该操作的结果取反。例如,若 msg 内容为 “This is an informative message”,则 :msg, contains, "error" 不匹配,而 :msg, !contains, "error" 匹配。
否定操作适用于需执行通用处理但排除特定事件的场景,可结合丢弃操作(discard action)使用。示例如下:
*.* /var/log/allmsgs-including-informational.log
:msg, contains, "informational" ~
*.* /var/log/allmsgs-but-informational.log
注意第 2 行的波浪号~不可遗漏!该示例中,所有消息先写入 allmsgs-including-informational.log 文件;随后,包含 “informational” 字符串的所有消息被丢弃,即 “丢弃行”(示例中第 2 行)之后的配置不再适用于这些消息;最后,剩余所有消息会写入 allmsgs-but-informational.log 文件。
比较值是带引号的字符串,支持以下转义序列:
\":表示引号字符(例如"String with \"Quotes\"")\\:表示反斜杠字符(例如"C:\\tmp")
转义序列均以反斜杠开头,未来可能会添加更多转义序列。反斜杠字符本身必须转义。除上述列出的序列外,其他任何序列均无效,可能导致不可预测的结果。
“msg”(消息内容)可能是基于属性的过滤器最常用的场景,它对应日志的实际消息文本。若需根据消息内容过滤(例如包含特定代码),可通过以下方式轻松实现:
:msg, contains, "ID-4711"
该过滤器会匹配包含字符串 “ID-4711” 的消息。需注意,比较区分大小写,因此消息中包含 “id-4711” 时不会匹配。
:msg, regex, "fatal .* error"
该过滤器使用 POSIX 正则表达式,会匹配包含 “fatal” 和 “error” 且两者之间有任意字符的字符串(例如 “fatal net error” 和 “fatal lib error”,但不匹配 “fatal error”—— 正则表达式要求两者之间有至少一个字符)。
正确配置基于属性的过滤器有时可能存在难度。为帮助你以最小开销完成配置,rsyslogd 在评估所有基于属性的过滤器时,会输出调试信息。如需启用该功能,可在前台运行 rsyslogd 并指定-d选项。
基于属性的过滤器目前不支持布尔运算(例如 “消息包含‘ID17’或包含‘ID18’”),仅支持上述提及的 “非(!)” 操作。需注意,虽然可通过基于属性的过滤器查询设备(facility)和优先级(severity),但此类场景更建议使用传统选择器(见前文)。
1.3 基于表达式的过滤器
基于表达式的过滤器支持根据任意复杂表达式过滤,可包含布尔运算、算术运算和字符串运算。这类过滤器将逐步发展为完整的配置脚本语言。但需注意,在此过程中其语法可能会有轻微变化,因此若现在使用,需做好后续修改配置文件的准备。不过开发团队会尽快实现脚本功能,所以语法变动的影响周期可能不会太长。
基于表达式的过滤器以新行第 1 列的关键字 “if” 标识,格式如下:
if 表达式 then 选择器行的操作部分
“if” 和 “then” 是必须存在的固定关键字。“表达式” 可以是(可能非常复杂的)运算表达式,详细规则见表达式文档。“选择器行的操作部分” 即常规操作(例如使用 “/var/log/logfile” 表示写入该文件)。
1.4 BSD 风格块
注意:由于技术原因,rsyslog v7 及以上版本不再支持 BSD 风格块,因此强烈建议不要使用。
rsyslogd 支持在 rsyslog.conf 中使用 BSD 风格块。每个行块通过程序名或主机名指定与前一个块分隔。一个块仅记录与最近指定的程序名和主机名对应的消息。例如,一个块选择ppp作为程序名,紧随其后的块选择主机名dialhost,则第二个块仅记录来自 dialhost 主机上 ppp 程序的消息。
指定规则:
- 程序名指定:以
!prog开头的行,后续块将关联到该特定程序的 syslog 调用。为foo指定程序名时,也会匹配内核日志中以foo:为前缀的消息;使用-foo形式则表示后续块应用于除 foo 外的所有程序的消息。 - 主机名指定:以
+hostname形式的行,后续块将应用于来自该指定主机的消息;使用-hostname形式则表示后续块应用于除该主机外的所有主机的消息。若主机名指定为@,则使用本地主机名(暂未实现)。 - 重置指定:将程序名或主机名指定为
*,可重置之前的程序名或主机名指定。
需注意,rsyslogd 不支持 BSD syslogd 中的#!prog”“#+hostname和#-hostname语法。默认情况下,未设置任何主机名或程序名。
1.5 示例
*.* /var/log/file1 # 传统方式
if $msg contains 'error' then /var/log/errlog # 基于表达式的方式
目前,若需检查设备(facility)和优先级(severity),需指定数值型值,具体数值可参考 RFC 5424。若不希望使用数值,也可使用文本属性,只需确保使用正确的属性名。随着表达式支持的增强,这一限制将有所改变。
例如,若需过滤设备为 local0、消息以DEVNAME开头、且包含error1或error0的消息,可使用以下过滤器:
if $syslogfacility-text == 'local0' and $msg startswith 'DEVNAME' and ($msg contains 'error1' or $msg contains 'error0') then /var/log/somelog
需注意,上述表达式必须写在同一行!若需存储设备为 local0、消息以DEVNAME开头,但不包含error1或error0的所有消息,只需添加not:
if $syslogfacility-text == 'local0' and $msg startswith 'DEVNAME' and not ($msg contains 'error1' or $msg contains 'error0') then /var/log/somelog
若需不区分大小写的比较,可使用contains_i替代contains,使用startswith_i替代startswith。需注意,基于表达式的过滤器目前不支持正则表达式,该功能将在表达式引擎添加函数支持后实现(原因是正则表达式将作为独立的可加载模块,需满足更多前置条件才能开发)。
更多推荐

所有评论(0)