RSYSLOG is the rocket-fast system for log processing.

本地Rsyslog版本: 7.4.4

配置

基本语法

Rsyslog 现在支持三种配置语法格式:

sysklogd 是老的简单格式,一些新的语法特性不支持。legacy rsyslog 是以dollar符($)开头的语法,在v6及以上的版本还在支持,一些插件和特性可能只在此语法下支持。RainnerScript是最新的语法。

老的语法格式(sysklogd & legacy rsyslog)是以行为单位。新的语法格式(RainnerScript)可以分割多行。

注释有两种语法:

执行顺序: 指令在rsyslog.conf文件中是从上到下的顺序执行的。

模块(Modules)

Rsyslog 使用 $ModLoad 指令加载模块。常用的模块类型是 Input Modules 和 Output Modules。

输入模块(Input Modules) 用于从多个来源收集(读取)消息,比如tcp/udp, 文本等。

模块作用
imfileinput module for text files
imrelpRELP input module
imudpudp syslog message input
imtcpinput plugin for tcp syslog
imptcpinput plugin for plain tcp syslog (no TLS but faster)
immarksupport for mark messages
imklogkernel logging
imuxsockunix sockets, including the system log socket
impstatsprovides periodic statistics of rsyslog internal counters

输出模块(Output Modules)处理消息。通过它,可以格式化消息以及传递消息到不通的目标(target)。

模块作用
omfilefile output module
omfwd????????
ompipenamed pipe output module
omrelpRELP output module
ommysqloutput module for MySQL
omprogpermits sending messages to a program for custom processing
omuxsockoutput module Unix domain sockets

还有其它类型的模块, 可以参考官方模块文档

简单的消息工作流:

Module Workflow

消息从 Input Modules 接收,然后传递给 Parser Modules,最终传递给 Output Module。

Templates

模板是 rsyslog 一个重要的属性,它可以控制日志的格式,支持类似template()语句的基于string或plugin的模板

legacy 格式使用 $template 的语法,不过这个在以后要移除,所以最好使用新格式 template():

$template name, param[, options]

name 是模板的名称,param 指定模板内容,options 用来设置模板选项。TODO

基于string的模板:

$template strtpl,"PRI: %pri%, MSG: %msg%\n"

基于plugin的模板:

$template plugintpl,=myplugin

举个例子:

$template MyTemplateName,"Text %property% some more text\n",<options>

模板指令定义一个模板 MyTemplateName,模板的格式是引号阔起来的,其中百分号%标记的是property,可以获取rsyslog的消息内容,更多参考 property replacer

Filter Conditions

Rsyslog 提供三种格式的过滤条件语法:

选择器(Selectors):

选择器是过滤syslog消息的传统方法。它使用rsyslog的原始语法,效率高,适合针对优先级(priority)和设施(facility)的过滤。

选择器由两部分组成, 一个facility和一个priority, 中间用句号(.)分隔。priority和facility都忽略大小写,并且可以用十进制数字代替,不过不建议这么做。可以通过 man 3 syslog更详细的了解这两部分。

Facility 用来指定哪个程序发送的日志消息,可以让配置通过不同的消息来源做不通的处理。

priority 列表:
debug
info
notice
warning
warn (same as warning)
err
error (same as err)
crit, alert
emerg
panic (same as emerg)

error, warn, panic已经过时,不应该再使用。

星号符(*)可以表示所有facility或所有priority。
关键词none表示为指定级别的。

一个priority可以指定多个facilities, 使用逗号(,)分隔。(priority不能这么做)

在一个action下配置多个selectors,使用分号(;)分隔。

priority前面加等于号(=)表示仅选择当前级别的。

priority前面加感叹号(!)表示排除该级别的。 TODO 测试 测试失败,不能用?

如果要同时使用感叹号和等于号,感叹号应该在等于号之前。

举例:

TODO

Property-Based Filters:

可以过滤任何属性,例如 HOSTNAME、msg等。支持的属性见The Property Replacer

property-based filter必须使用冒号(:)开头。

语法:

:property, [!]compare-operation, "value"

value 是用来比较的值,必须用引号括起来。

注意 property和compare-operation是大小写敏感的。

compare-operation 有:

contains : property 包含指定 value
isequal : property 和指定 value 相等
startswith : 以 value 起始的property
regex
ereregex

Rsyslog Queue

队列是 rsyslog 的核心。下图(来源) 展示了rsyslog处理消息的流程:

message flow

队列分为 Main QueueAction Queue,Main Queue 只有一个,Action Queue 有多个,每一个 Action 前面都有一个 Action Queue。Main Queue 的配置一般以MainMsg开头,Action Queue的配置以Action开头,两者的配置基本相同。

队列的模式有Direct, Disk, In-Memory, Disk-Assisted Memory四种,最后一种后面都简称DA,这种队列模式是Disk 和 In-Memory的结合体。其中 In-Memory 又包括 FixedArrayLinkedList两种模式。

Direct Queues

实际上是一个 non-queuing queue。它直接把消息从 producer 传递给 customer。

这种模式适合简单的把日志写入本地, 效率非常高。

所以 Action Queue 的默认模式就是 Direct Queues。

Disk Queues

这种对了使用硬盘当做缓存,因为没有使用内存,所以缓存速度最慢,但是可靠性最高,一般用于数据非常重要的情景下。

缓存文件存在指定的目录下,文件名是 队列名.7位数字,从 0000001开始,当一个文件达到限制的最大大小,会继续新建文件,文件名加一。

In-Memory Queues

这种队列是最常使用的队列,它分为 FixedArrayLinkedList 两种。它们使用内存作为缓存,所以效率非常高,但是相对的它们的可靠性没有Disk Queue好。

FixedArray 是预分配固定大小的队列,也是Main Queue的默认模式。它针对的是队列日志相对较小的情况,拥有很好的性能。

LinkedList 是动态分配大小的队列,适合队列日志很大的情况。

官方建议这两者间优先选择 LinkedList。

Disk-Assisted Queues

它集成了In-Memory 和 Disk 这两种队列的优点。

如果一个In-Memory Queue定义了队列名(通过 $<object>QueueFileName),它自动就变成 Disk-Assisted(DA)模式。

DA队列实际是两个队列,一个普通的memory队列 (called the "primary queue")和一个disk队列(called the "DA queue")。当达到一定条件后,DA队列就会被激活。

关于队列的配置

因为 MainMsgQueue 和 ActionQueue 的配置基本一样(除了有些默认值可能不同), 所以这里以MainMsgQueue 为例:

对于DA队列,最有特点就是队列阈值的设置了。主要包括这几个配置:

DA 对于阈值处理的逻辑比较有意思,并不是单纯的内存满了就开始使用硬盘。首先,有 low watermarkhigh watermark 这两个概念。

如果队列大小达到 high watermark,队列开始写数据到disk
如果队列大小降到 low watermark,停止写入disk(直到再次达到 high watermark); 或者 disk queue 队列为空(即da队列里的数据处理完),这两种情况都会进入in-memory 模式

关于终止队列的一些处理配置:

当配置的队列大小或硬盘空间满了以后,rsyslogd 会限制数据submitter。配置 $MainMsgQueueTimeoutEnqueue 后,当超过这个时间后新来的日志会被丢弃;设置0为直接丢弃。

$MainMsgQueueTimeoutShutdown$MainMsgQueueTimeoutActionCompletion$MainMsgQueueSaveOnShutdown 是在队列终止后可以做的一系列措施。

关于队列的worker thread:

每个队列(direct queue除外)都有一个工作线程池(worker thread pool).
初始时,是没有worker thread的,当有消息来是,会自动启动一个.
$MainMsgQueueWorkerThreadMinumumMessages 配置一个worker thread处理的消息大小,
$MainMsgQueueWorkerThreads 配置work thread的上限值。

比如设置一个worker thread的最小处理消息大小是100个,当小于100个是,只有一个worker,当超过100个,小于200个时,会有两个worker...

以上配置要注意单位, 默认值,Main Queue 和 Action Queue 可能有些配置的默认值不一样。

另外所有指明针对disk的配置,都是包括 disk queue 和 DA queue.

更多配置参考这里

在一般情况下,大部分的配置都可以直接使用默认的配置,这里给出一份Action使用DA队列的配置:

# 这两个是全局的 
$ActionResumeRetryCount                  3
$ActionResumeInterval                    10
# 以下是每个ActionQueue自己的配置
$ActionQueueType                         LinkedList
$ActionQueueFileName                     da_queue
$ActionQueueMaxFileSize                  100M         # 设置单个disk文件的大小
$ActionQueueMaxDiskSpace                 10G          # 设置最大占用空间
$ActionQueueDisacdSeverity               3            # 设置忽略的等级
$ActionQueueLowWaterMark                 5000         # 默认是2000
$ActionQueueHighWatermark                15000        # 默认是8000
$ActionQueueDiscardMark                  30000        # 默认是9750
$ActionQueueSize                         80000        # 文档没写,测试发现默认是1000
$ActionQueueSaveOnShutdown               on

*.* @log-center.xxx.com:514

Main Queue 的默认模式是 FixedArray,Action Queue 的默认模式是 Direct

关于Rsyslog Queue的官方文档:

impstats 模块

队列的相关统计信息可以使用输出模块 impstats 来查看。参考配置:

$ModLoad impstats
$PStatInterval 5
$PStatSeverity 7

syslog.=debug  /var/log/rsyslog-stats
&~

样例表示每5s(默认是300s)生成一个统计信息,日志等级是7及以上(默认是6),日志写入/var/log/rsyslog-stats后丢弃。

这里我配置为DA类型,通过 impstats 模块观察:

2014-03-14T17:51:16.744660+08:00 localhost rsyslogd-pstats: imuxsock: submitted=3086634 ratelimit.discarded=0 ratelimit.numratelimiters=0
2014-03-14T17:51:16.744712+08:00 localhost rsyslogd-pstats: action 1 queue[DA]: size=138176 enqueued=138176 full=0 maxqsize=138176
2014-03-14T17:51:16.744720+08:00 localhost rsyslogd-pstats: action 1 queue: size=13808 enqueued=151976 full=0 maxqsize=20009
2014-03-14T17:51:16.744727+08:00 localhost rsyslogd-pstats: main Q[DA]: size=0 enqueued=0 full=0 maxqsize=0
2014-03-14T17:51:16.744732+08:00 localhost rsyslogd-pstats: main Q: size=4 enqueued=3087045 full=0 maxqsize=261

可以看到,action queue使用了da队列,因为默认的 $WorkDirectory /var/spool/rsyslog,在 /var/spool/rsyslog 下可以看到存储的日志:

root@localhost:/var/spool/rsyslog# ll
total 160384
drwxr-xr-x 2 syslog adm        36864 Mar 14 17:50 ./
drwxr-xr-x 7 root   root        4096 Oct 29 13:27 ../
-rw------- 1 syslog syslog 100000283 Mar 14 17:50 fwdacq.00000001
-rw------- 1 syslog syslog  50443050 Mar 14 17:52 fwdacq.00000002

root@localhost:/var/spool/rsyslog# du -sh *
96M     fwdacq.00000001
49M     fwdacq.00000002

存储文件默认是用队列名.7位数字以递增方式命名的,因为定义了存储文件的最大值是100M,所以可以看到第一个是96M,再存储就存不了了,进而新建第二个文件存储。

2014-03-14T17:27:07.485964+08:00 localhost rsyslogd-pstats: imuxsock: submitted=32005 ratelimit.discarded=0 ratelimit.numratelimiters=0
2014-03-14T17:27:08.090574+08:00 localhost rsyslogd-pstats: action 1 queue[DA]: size=0 enqueued=0 full=0 maxqsize=0
2014-03-14T17:27:08.090590+08:00 localhost rsyslogd-pstats: action 1 queue: size=1000 enqueued=1065 full=65 maxqsize=1000
2014-03-14T17:27:08.090598+08:00 localhost rsyslogd-pstats: main Q[DA]: size=0 enqueued=0 full=0 maxqsize=0
2014-03-14T17:27:08.090604+08:00 localhost rsyslogd-pstats: main Q: size=9940 enqueued=32042 full=18 maxqsize=10000

在没有配置 $MainMsgQueueSize$ActionQueueSize 时,可以看到队列最大值分别是10000和1000。

对于Action Queue, 可以看到默认是'Action 1'、'Action 2'...命名的,可以通过 $ActionName <name>来对Action Queue命名. 在文档中还没找到这个配置,不过在mail list中看到了回答.

更多的可以参考:

Rainer Script

P.S. 再次吐槽, rsyslog 的文档不愧是我见过最差的文档, 读起来线路不清晰就算了, rst解析很多地方也有问题。

从v8.7.0升级到v8.13.0,有些legacy的配置项已经彻底移除了, 替换为Rainer Script的配置, 所以研究了下Rainer Script。

检查配置: (rsyslogd -N1 或者 rsyslogd -dn)

$ rsyslogd -N1
rsyslogd: version 8.13.0, config validation run (level 1), master config /etc/rsyslog.conf
rsyslogd: invalid or yet-unknown config file command 'SystemLogRateLimitInterval' - have you forgotten to load a module? [v8.13.0 try http://www.rsyslog.com/e/3003 ]
rsyslogd: invalid or yet-unknown config file command 'SystemLogRateLimitBurst' - have you forgotten to load a module? [v8.13.0 try http://www.rsyslog.com/e/3003 ]
rsyslogd: invalid or yet-unknown config file command 'IMUXSockRateLimitInterval' - have you forgotten to load a module? [v8.13.0 try http://www.rsyslog.com/e/3003 ]
rsyslogd: invalid or yet-unknown config file command 'IMUXSockRateLimitBurst' - have you forgotten to load a module? [v8.13.0 try http://www.rsyslog.com/e/3003 ]

V8的配置文档」, 主要需要看几个配置:

迁移基本就是搜索每一项lagacy配置, 查找对应的rainer配置,另外通过上面可以看出,新配置的命令还是比较有规律的.

比如Action<xxx>的配置变为Action.<xxx>, ActionQueue<xxx>变为Queue.<xxx>(不区分大小写).

另外, 在Action的链接里提到两点:

  • Be warned that legacy action format is hard to get right. It is recommended to use RainerScript-Style action format whenever possible!
  • Please also note that legacy action parameters do not affect RainerScript action objects.

比如:

$actionResumeRetryCount 10
action(type="omfwd" target="server1.example.net")
@@server2.example.net

第一行的配置对第二行的action无效,只对第三行有效。

坑不少~~

其它参考:

实践

遇到一个kernel的报错, 一直在刷日志, 现在要把包含这条报错信息的内核日志丢弃:

:msg, contains, "message want to be dropped" ~

或者更详细的:

if $syslogfacility-text == 'kern' and ($msg contains 'message want to be dropped') then ~

参考: Discarding unwanted messages

更多资料

官方资料