Linux日志机制的核心是rsyslog守护进程,该服务负责监听Linux下的日志信息,并把日志信息追加到对应的日志文件中,一般在/var/log目录下。它还可以把日志信息通过网络协议发送到另一台Linux服务器上,或者将日志存储在MySQL或Oracle等数据库中。目前rsyslog的大版本为v8。
配置文件
一般情况下,rsyslog 配置的文件文件位于/etc/rsyslog.conf 以及 /etc/rsyslog.d/文件夹下,在/etc/rsyslog.conf中通过$IncludeConfig
指令将/etc/rsyslog.d/的所有配置合并到一起。配置主要可以分为以下几类:
全局配置
加载一些通用的模块
module(load="imuxsock") # provides support for local system logging
module(load="imklog") # provides kernel logging support
设置默认的日志格式:
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
一些权限相关,在后面的一些配置中需要特别注意:
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog
规则
每条规则都由选择器和相应的动作组成,选择器说明来源和日志级别,而动作则说明如何处理对应的日志,下面是一些例子:
cron.* /var/log/cron
mail.warn /var/log/mail.warn
把所有来自cron守护进程的消息保存到/var/log/cron文件中。 当指定日志级别时,所有等于或大于该日志等级的信息都要被处理。比如在下面的例子中,mail子系统所有warning及以上信息的日志都保存在/var/log/mail.warn文件中。
mail.=info -/var/log/mail.info
使用=可以指定日志等级,加上 -
表明日志异步写入。
mail.!info /var/log/mail.info
使用!可以排除这类信息。
自定义channel
除了将日志写入本地文件外,rsyslog还支持自定义的规则,下面的指令就定义了一个名称为NAME的channel:
$outchannel NAME, FILE_NAME, MAX_SIZE, ACTION
下面是一个例子注意omfile指明输出到文件。
$outchannel log_rotation, /var/log/test_log.log, 104857600, /home/millions/log_rotation_script
*.* :omfile:$log_rotation
实际用例
如果rsyslog只能做将日志写入本地文件那就有点没意思了,下面我们来看一下rsyslog的一些高级一点的功能。
收集nginx的access log 写入文件中
从nginx的access log中可以分析出很多东西,但是在分布式环境下nginx通常部署在多个不同的服务器下,使用rsyslog可以将这些日志整合起来。
我们在/etc/rsyslog.d/文件夹下新建一个配置文件access_log.conf:
module(load="imfile")
ruleset(name="remote") {
action(type="omfwd"
Protocol="tcp"
Target="127.0.0.1"
Port="8899")
stop
}
input(type="imfile"
File="/var/log/nginx/access.log"
Facility="user"
Severity="info"
Tag="web_access"
PersistStateInterval="1"
Ruleset="remote")
由于要读取文件,我们引入module(load="imfile")
。然后在input中指明输入的文件位置,以及日志的类型和级别。PersistStateInterval
表示持久化的间隔,可以根据需要调整,Ruleset表示使用的规则是什么。在规则中,我们指明了输出类型为转发,目标是127.0.0.1的8899端口,并且使用tcp协议。
接下来,我们再增加一个接受转发日志的配置:
module(load="imtcp")
template(name="msg" type="string" string="%msg:2:$%\n")
ruleset(name="analysis") {
action(type="omfile"
File="/home/millions/log/access.log"
Template="msg")
stop
}
input(type="imtcp"
Port="8899"
Ruleset="analysis")
这里我们的input是tcp,并且监听在8899端口上,输出到指定的文件,并使用自定义的模板msg
。这里要注意权限问题。
然后去访问nginx,就可以看到指定目录下的文件了。
收集nginx日志并重定向到程序
稍微修改以下我们接收日志的配置,就可以把日志重定向给某个程序的标准输入了:
module(load="imtcp")
module(load="omprog")
template(name="msg" type="string" string="%msg:2:$%\n")
ruleset(name="analysis") {
action(type="omprog"
Binary="/usr/bin/php /home/millions/log/test.php"
Template="msg")
stop
}
input(type="imtcp"
Port="8899"
Ruleset="analysis")
为了方便起见,我们这里采用php脚本,也可以换成其他想使用的语言,test.php的内容如下。
$fp = fopen("/home/millions/log/f.log", "w+");
while (($data = fgets(STDIN)) !== false) {
fwrite($fp, "got data:" . $data);
}
这样就可以看到f.log中记录的数据了:
got data:192.168.0.102 - - [08/Jan/2017:11:58:00 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
got data:192.168.0.102 - - [08/Jan/2017:13:20:34 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
如果kill掉test.php,下次同步日志时rsyslog还会启动一个新的test.php,这样可以在运行一定次数后退出进程防止内存泄露。
总结
上面只是对rsyslog的使用做了一个简单的介绍,具体使用还有很大的发挥空间。比如在脚本中不是简单的把日志写入本地文件,而是发往kafka,记录到mysql,mongodb中去。进一步的学习还是需要查看rsyslog的官方文档。