Syslog(系统日志)是一种在 IP 网络中传输操作系统和应用程序的日志信息的标准网络协议,常被应用于安全管理系统、日志审计系统等场景。
Syslog 协议的关键概念有以下 3 个:
通过 Facility、Priority 和 Action 的组合使用可以描述清楚 “存储什么日志、存储在哪里” 的问题。
下列是 Linux Kernel 中实现的 Syslog Facilities(syslog.h),Applicant 通过调用这些服务类型来记录它们的软件日志信息。
下列是 Linux Kernel 中实现的 7 个 Syslog Severities。
1)记录到普通文件或设备文件
*.* /var/log/file.log # 绝对路径
*.* /dev/pts/0 # 设备文件
2)”|”,表示将日志送给其他命令处理
3)”@HOST”,表示将日志发送到特定的主机
*.emerg @192.168.10.1
4)”用户”,表示将日志发送到特定的用户
5)”*”,表示将日志发送所有登录到系统上的用户
示例:摘取 $msg 变量内容,判断如果 keyboard 关键字就进行远程传送,没有此关键字的就不传送;
if $msg contains "keyboard" then
action(type="omfwd" Target="172.18.20.60"\
Port="8594"\
Protocol="udp"\
queue.type="LinkedList"\
queue.spoolDirectory="/var/spool/rsyslog"\
queue.filename="test2"\
queue.size="100000"\
queue.maxdiskspace="2g"\
queue.highwatermark="60000"\
queue.lowwatermark="2000"\
queue.discardmark="80000"\
queue.timeoutenqueue="3000"\
queue.maxfilesize="200m"\
queue.dequeuebatchsize="1000"\
)
rsyslog(rocket-fast system for log)是 CentOS6 以后引入的一个日志服务,是 Syslog 协议的软件实现。rsyslog 能够接受从各种各样的来源,将其输入,输出的结果到不同的目的地。此外还具有以下特性:
Rsyslog 架构如上图所示,消息流是:输入模块 => 预处理模块 => 主队列 => 过滤模块 => 执行队列 => 输出模块。
Systemd 启动方式:
/lib/systemd/system/rsyslog.service
CLI 启动方式:
rsyslogd -f /root/rsyslog_worker_dir/rsyslog.conf -i /root/rsyslog_worker_dir/rsyslog.pid
rsyslogd -f /root/rsyslog_worker_dir/rsyslog.conf -i /root/rsyslog_worker_dir/rsyslog.pid -dn >debuglog
# 检测配置文件是否正确
rsyslogd -N1 -f file
rsyslog.conf 配置文件由 3 个部分组成:
#################
#### MODULES ####
#################
module(load="imuxsock") # provides support for local system logging
#module(load="immark") # provides --MARK-- message capability
# provides UDP syslog reception
module(load="imudp")
input(type="imudp" port="514")
# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514")
# provides kernel logging support and enable non-kernel klog messages
module(load="imklog" permitnonkernelfacility="on")
###########################
#### GLOBAL DIRECTIVES ####
###########################
#
# Use traditional timestamp format.
# To enable high precision timestamps, comment out the following line.
#
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
# Filter duplicated messages
$RepeatedMsgReduction on
#
# Set the default permissions for all log files.
#
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog
#
# Where to place spool and state files
#
$WorkDirectory /var/spool/rsyslog
#
# Include all config files in /etc/rsyslog.d/
#
$IncludeConfig /etc/rsyslog.d/*.conf
#################
#### RULES ####
#################
# 服务名称[.=!]信息等级 信息记录的文件名或设备或主机
# . 表示大于等于 xxx 级别的信息;
# .= 表示等于 xxx 级别的信息;
# .! 表示在 xxx 之外的等级的信息;
mail.info /var/log/maillog_info # mail 服务产生的大于等于 info 级别的日志信息,都记录到后面指定的位置中。
# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.* /dev/console
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none /var/log/messages
# The authpriv file has restricted access.
authpriv.* /var/log/secure
# Log all the mail messages in one place.
mail.* -/var/log/maillog
# Log cron stuff
cron.* /var/log/cron
# Everybody gets emergency messages
*.emerg :omusrmsg:*
# Save news errors of level crit and higher in a special file.
uucp,news.crit /var/log/spooler
# Save boot messages also to boot.log
local7.* /var/log/boot.log
Rsyslog 预定义了一些内置的属性,我们可以在配置文件中定义日志输出格式、或定义动态文件名的时候使用到这些属性。以 $ 开头的是从本地系统获得的变量、不带 $ 就是从消息中获得变量。例如:
属性替代的语法格式:
%propname:fromChar:toChar:options:fieldname%
属性替换的功能很强大,你可以使用起始字符获取自己所需的字段,也可以使用正则表达式,也可以使用分隔符。例如:为了兼容一个 RFC 协议,rsyslog 规定如果用户输入的 msg 不是以空格开头,rsyslog 会自动补充一个空格,因此如果你希望输出的时候去掉这个空格,就可以使用:
%msg:2:$% # 选取 msg 变量中,起始位置为 2,终止位置为结尾。
我们经常需要根据空格来分析字符串,F 表示使用字符分割,32 是空格的 ASCII 码,例如:
%msg:F,32:3% # 按照空格分隔,取第三个子串。
模板渲染结合属性替代功能,常用于定义日志的输出格式,或者定义 omfile 模块的动态路径、动态文件等。例如:
$template t_msg, "%msg\n%"
$template f_debug, "/data0/logs/%$year%-%$month%-%$day%/debug.log"
通过过滤规则(Ruleset)可以针对不同的 Syslog 来源应用不同的过滤规则。需要在配置文件中预先定义才可以使用。例如针对不同的端口使用不同的过滤规则:
$Ruleset tcp1999
$RulesetCreateMainQueue on
Local3.* @@10.0.0.44:1999
$Ruleset tcp2000
$RulesetCreateMainQueue on
Local4.* @@10.0.0.44:2000
在配置文件中导入了 Filter 模块之后就可以应用过滤规则了。例如:
Local3.* -/data0/logs/local3.log;t_msg # 在这个输出中使用 t_msg 的模板。
Local4.* -?f_local3_test;t_msg # 问号表示要使用模板定义的动态路径。
Rsyslog 的队列具有主队列和工作队列这 2 种类型。从输入模块接收的消息会进入主队列,主队列中的消息,经过过滤模块,会进入到相应的工作队列。
队列j具有 4 种工作模式:
前两种是磁盘队列,更可靠,但是性能也较差;而后两种是内存队列。FixedArray 会预分配队列长度,而 LinkedList 是动态分配,如果你的系统日志流量比较平稳,可以使用预分配队列,如果日志属于突发型,可以使用动态队列。
此外,内存队列还可以通过指定一个 queuename 来添加 DA 模式,DA 模式主要是为了防止意外情况(进程关闭、Server 宕机)下,内存队列可以不丢失。
通过查看 rsyslog 的系统命令,可以看见 rsyslog 对队列提供了大量的可配参数,可以根据需要来进行优化。
$ vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
$ModLoad imtcp
$InputTCPServerRun 514
$template myFormat,"%timestamp% %fromhost-ip% %msg%\n"
$ActionFileDefaultTemplate myFormat
# 服务端 IP 地址,一个 @ 表示 TCP 传输,两个 @ 表示 UDP 传输
*.info;mail.none;authpriv.none;cron.none @@192.168.157.61:514
$ systemctl start rsyslog
$ vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
$ModLoad imtcp
$InputTCPServerRun 514
*.info;mail.none;authpriv.none;cron.none /data/log/messages
# 允许 157.0 网段内的主机以 TCP 协议来传输
$AllowedSender tcp, 192.168.157.0/24
# 定义模板,接受日志文件路径,这里区分了不同主机的日志
$template Remote,"/data/log/%fromhost-ip%/%fromhost-ip%_%$YEAR%-%$MONTH%-%$DAY%.log"
# 过滤服务器本机的日志。
:fromhost-ip, !isequal, "127.0.0.1" ?Remote
$ systemctl start rsyslog
$ mkdir -pv /data/log
$ touch messages
$ systemctl restart rsyslog
$ tree /data/log/
/data/log/
├── 192.168.157.60
│ └── 192.168.157.60_2019-05-10.log
└── messages
client $ logger "I'm very happy"
server $ tail -f /data/log/192.168.157.60/192.168.157.60_2019-05-10.log
$ yum install mariadb-server rsyslog-mysql -y
$ systemctl start mariadb.service
$ rpm -ql rsyslog-mysql
/usr/lib64/rsyslog/ommysql.so # 客户端通信模块
/usr/share/doc/rsyslog-8.24.0/mysql-createDB.sql # 创建 rsyslog 日志表结构的 SQL 语句
$ mysql < /usr/share/doc/rsyslog-8.24.0/mysql-createDB.sql
mysql> show databases;
mysql> use Syslog;
mysql> show tables;
+------------------------+
| Tables_in_Syslog |
+------------------------+
| SystemEvents |
| SystemEventsProperties |
+------------------------+
mysql> grant all on Syslog.* to 'rsysloguser'@'127.0.0.1' identified by 'rsyslogpass';
mysql> flush privileges;
修改服务器配置文件:
$ vim /etc/rsyslog.conf
......
$ModLoad ommysql # 打开连接 MySQL 的模块
*.* :ommysql:127.0.0.1,Syslog,rsysloguser,rsyslogpass
$ systemctl restart rsyslog.service
client $ logger 'THIS IS A TEST'
mysql> use Syslog;
mysql> select * from SystemEvents\G;
*************************** 17. row ***************************
ID: 17
CustomerID: NULL
ReceivedAt: 2019-05-10 23:15:07
DeviceReportedTime: 2019-05-10 23:15:06
Facility: 1
Priority: 5
FromHost: send
Message: THIS IS A TEST
NTSeverity: NULL
Importance: NULL
EventSource: NULL
EventUser: NULL
EventCategory: NULL
EventID: NULL
EventBinaryData: NULL
MaxAvailable: NULL
CurrUsage: NULL
MinUsage: NULL
MaxUsage: NULL
InfoUnitID: 1
SysLogTag: root:
EventLogType: NULL
GenericFileName: NULL
SystemID: NULL
在 /etc/rsyslog.d/ 目录下新建一个 apache_log.conf 配置文件:
# 加载 imfile 模块
$ModLoad imfile
$InputFilePollInterval 10
## Apache 访问日志文件路径
$InputFileName /var/log/apache2/access.log
# tag 标签,可以作为过滤或分类用
$InputFileTag apache-access
# 状态文件,只需要指定文件名,程序会在工作目录 $WorkDirectory 下创建指定文件
$InputFileStateFile stat-apache-access
# 日志类型,user 代表应用日志
$InputFileFacility user
# 日志级别
$InputFileSeverity info
# 写入状态文件时间间隔
$InputFilePersistStateInterval 25000
## 以上属性可等效写为:
## input(type="imfile" File="/path" Tag="tag1" StateFile="filename" Severity="info" Facility="user" PersistStateInterval="25000")
## Apache 错误日志文件路径
$InputFileName /var/log/apache2/error.log
$InputFileTag apache-error
$InputFileStateFile stat-apache-error
$InputFileSeverity error
$InputFilePersistStateInterval 25000
## 日志格式模板:msg 代表默认产生的消息
$template apache_temp,"%msg%\n"
## 按照 tag 分类指定 rsyslog 日志服务器地址,
if $syslogtag == 'apache-access' then @your_server:port;apache_temp
if $syslogtag == 'apache-access' then ~
if $syslogtag == 'apache-error' then @your_server:port;apache_temp
if $syslogtag == 'apache-error' then ~
# The imjournal module bellow is now used as a message source instead of imuxsock.
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imjournal # provides access to the systemd journal
# 启用 udp 模块,默认端口为 514
module(load="imudp")
input(type="imudp" port="514")
# 启用 tcp 模块
module(load="imtcp")
input(type="imtcp" port="514")
# 将收到的日志模板化,比如在前面添加 IP 进行区分
$template access_log, "%FROMHOST-IP% %msg%\n"
$template error_log, "%msg%\n"
$template eophp_log, "%msg%\n"
# 指定保存到服务器的路径
# access-log
$template access_log_path, "/data/apache/logs/%$NOW%/access-log/web1-access_log"
# error-log
$template error_log_path, "/data/apache/logs/%$NOW%/error-log/web1-error_log"
# eophp log
$template eophp_log_path, "/data/eophp_logs/%$NOW%/%FROMHOST-IP%.log"
# if 进行条件匹配比如多台客户端的 IP 在同一个网络,可以用 startwith 匹配 IP 的前缀
# $syslogtag 为日志的 tag 标签
if $fromhost-ip startswith '119.123.' and $syslogtag == 'apache-access' then ?access_log_path;access_log
& ~
# web1-error-log
if $fromhost-ip startswith '119.123.' and $syslogtag == 'apache-error' then ?error_log_path;error_log
& ~
# eophp
if $fromhost-ip startswith '119.123.' and $syslogtag == 'eplog' then ?eophp_log_path;eophp_log
&~
# omit...