目標是要把線上環境的debug日志及集中化收集起來,一方面是方便開發調試;一方面是避免直接到線上環境查看,存在安全隱患。
常用可選方案:
- rsyslog發送端 + rsyslog接收端: 直接存在接收端的本地硬盤
- rsyslog發送端 + logstash接收端 + <后續第三方處理>: 接受到log更新行后,通過logstash簡單處理后,可以繼續往第三方處理,如放到ElasticSearch,或者放到消息隊列Kfaka等
- rsyslog發送端 + Splunk: Splunk是商業軟件,也是業內用的比較多的方式,價格不菲
基本原理和處理流程都是類似的: 監控本地log文件內容的變化,然后把變化的文件內容發送到遠端收集服務上。
例如常說的ELKstack(ElasticSearch+Logstash+Kibana)的第一步都是配置rsyslog發送端。
不管哪種方案都得監控本地文件的變化,rsyslog屬於必選。我們需求比較簡單,暫時選用了落地到本地盤,默認存儲15天debug日志。
本文主要介紹rsyslog發送端、接收端的配置,以及遇到的一些坑。
rsyslog 簡介
rsyslog 在Linux上自帶,兼容syslog語法,在syslog基礎上增加了更多協議的支持,配合額外module插件可以完成很多場景的使用。借用下官網的圖片:
注: Windows 平台需要 nxlog (nxlog 是用C 語言寫的一個跨平台日志收集處理軟件)。
安裝
在CentOS 6.8 Final 上自帶的版本為 5.8.10。如需最新版本,可參考官網。
1
2
3
4
5
6
7
8
9
10
11
|
$ rsyslogd -version
rsyslogd 5.8.10, compiled with:
FEATURE_REGEXP: Yes
FEATURE_LARGEFILE: No
GSSAPI Kerberos 5 support: Yes
FEATURE_DEBUG (debug build, slow code): No
32bit Atomic operations supported: Yes
64bit Atomic operations supported: Yes
Runtime Instrumentation (slow code): No
See http://www.rsyslog.com
for more information.
|
V5版本開發於2010年,屬於比較舊的版本,最新版本是V8,支持了更多的字符串處理函數和更多module,當然性能也更好。
缺點是:新舊配置語法不兼容,而采用內置版本的另一個偷懶的好處是雲端的鏡像也不需要再額外升級,能支持更多老機器。
后面介紹以V5版本為例,如有不同的,會單獨指出。
工作流
message先進入主隊列再過濾到分支隊列, 最后在各個processor線程中輸出內容, 輸出方式可以是kafka/rsyslog/file/ES..
配置文件介紹
執行文件: /sbin/rsyslogd
主配置文件: /etc/rsyslog.conf
自定義配置文件: /etc/rsyslog.d/*.conf
修改配置文件后,重啟服務: sudo /etc/init.d/rsyslog restart
一份配置文件主要包括以下幾個部分:
- MODULES
- RULES
- 全局指令,模板,模塊參數等
自帶的配置文件如下,參考后面的注釋:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# rsyslog v5 configuration file
# For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html
# If you experience problems, see http://www.rsyslog.com/doc/troubleshoot.html
#### MODULES #### # 模塊放在開頭加載
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command) # 可以用來調試,稍后有例子
$ModLoad imklog # provides kernel logging support (previously done by rklogd)
#$ModLoad immark # provides --MARK-- message capability
# Provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514
# Provides TCP syslog reception # TCP server,接收端需要加載這個模塊,發送端不需要
#$ModLoad imtcp
#$InputTCPServerRun 514
#### GLOBAL DIRECTIVES ####
# Use default timestamp format
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat # 消息格式
# File syncing capability is disabled by default. This feature is usually not required,
# not useful and an extreme performance hit
#$ActionFileEnableSync on
#### RULES #### # 用來指定哪種類型的,哪種級別的log,發送給誰處理
# 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 *
# 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 # local開頭的是自定義的日志類型
# ### begin forwarding rule ###
# The statement between the begin ... end define a SINGLE forwarding
# rule. They belong together, do NOT split them. If you create multiple
# forwarding rules, duplicate the whole block!
# Remote Logging (we use TCP for reliable delivery)
#
# An on-disk queue is created for this action. If the remote host is
# down, messages are spooled to disk and sent when it is up again.
#$WorkDirectory /var/lib/rsyslog # where to place spool files
#$ActionQueueFileName fwdRule1 # unique name prefix for spool files
#$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible)
#$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
#$ActionQueueType LinkedList # run asynchronously
#$ActionResumeRetryCount -1 # infinite retries if host is down
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
#*.* @@remote-host:514
# ### end of the forwarding rule ###
# Finally include all config files in /etc/rsyslog.d. This allows overrides
# of the default configuration above.
$IncludeConfig /etc/rsyslog.d/*.conf # 這里會自動加載自定義的*.conf配置文件,可以覆蓋默認參數
|
模塊 imfile
為了完成我們的任務,除了上面默認的模塊,還需要加載 imfile
,,來指定監控哪些文件,參考文檔。
1
|
$ModLoad imfile # Load the imfile input module
|
該模塊把標准的文本文件轉換成syslog的message格式, 所謂標准文本是指:保護可打印的字符,每行以 LF
作為分隔符號。 支持文件正在在logrotate的時候,仍能正確處理。
它會把監控文件的讀取到哪一個位置(類似游標cursor),存儲在state文件里(由 $WorkDirectory
指定)。
該模塊支持如下指令,一組如下設置,可以稱為一個 listener:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
$InputFileName /path/to/file # 待監控的文件路徑
$InputFileTag tag # 文件唯一標識tag,最好保持唯一,用於接收端區分原始log文件,可以包含特殊字符,如":"、","等
$InputFileStateFile /path/to/state/file
# 【重要】需要保證發送端唯一,記錄讀取到哪兒,狀態文件保存在$WorkDirectory,默認為 /var/lib/rsyslog
# 如果某個要監控的文件名變化了,一定要重新設置該值
$InputFileFacility facility # log類型,默認local0, local開頭的表示自定義類型
$InputFileSeverity severity # log級別:info,warning,默認notice
$InputRunFileMonitor # 啟動監控當前的文件,如果忘記這行,則啥事也不會發生
$InputFilePollInterval seconds # 全局設置,默認輪詢是10s
$InputFilePersistStateInterval lines # 每多少行更新state文件狀態
$InputFileReadMode mode # 官網竟然沒這個解釋,不過也沒用到。。。
$InputFileMaxLinesAtOnce number
# 默認10240,如果在發送端,需要同時監控多個文件,會處理完當前文件特定行后,切換到下一個文件,避免一個文件一直占用處理,導致收集別的文件不及時。
$InputFileBindRuleset ruleset # 屬於較高級的設置,可以把這個listener綁定到特點的規則(http://www.rsyslog.com/doc/v5-stable/concepts/multi_ruleset.html)
|
接收端配置,注意tag里的逗號 ','
,稍后在接收端,會它來分隔:
1
2
3
4
5
6
7
8
9
|
# For product, total 19 files.
$InputFileName /Data/logs/product/cache-Statistic.log
$InputFileTag product,cache-Statistic
$InputFileSeverity info
$InputFileStateFile state_product_cache-Statistic
$InputFilePersistStateInterval 25000
$InputFileFacility local5
$InputRunFileMonitor
|
Rule 設置
一條rule的語法格式如: <Facility>.<Severity> <Target>
例如:
1
2
3
4
5
6
7
8
|
# Log cron stuff
cron.* /var/log/cron
# 記錄info到本地messages文件,.none 結尾表示排除掉這些文件類型。
*.info;mail.none;authpriv.none;cron.none /var/log/messages
# 所有為local5的任意級別日志發送到遠端514
local5.* @@192.168.56.10:514
|
Facility
日志設備(可以理解為日志類型):
1
2
3
4
5
6
7
8
9
10
11
|
auth
#pam產生的日志,認證日志
authpriv
#ssh,ftp等登錄信息的驗證信息,認證授權認證
cron
#時間任務相關
kern
#內核
lpr
#打印
mail
#郵件
mark(syslog)
#rsyslog服務內部的信息,時間標識
news
#新聞組
user
#用戶程序產生的相關信息
uucp
#unix to unix copy, unix主機之間相關的通訊
local 1~7 #自定義的日志設備
|
Severity
1
2
3
4
5
6
7
8
|
debug
#有調式信息的,日志信息最多
info
#一般信息的日志,最常用
notice
#最具有重要性的普通條件的信息
warning, warn
#警告級別
err, error
#錯誤級別,阻止某個功能或者模塊不能正常工作的信息
crit
#嚴重級別,阻止整個系統或者整個軟件不能正常工作的信息
alert
#需要立刻修改的信息
emerg, panic
#內核崩潰等嚴重信息
|
Target
- 文件: /var/log/messages
- 用戶: root,*(表示所有用戶), 會發到/var/spool/mail/收件箱里
- 日志服務器: @192.168.56.10 或者 @@192.168.56.10
- 管道: | COMMAND
一個 @
表示 UDP
, 兩個 @@
表示 TCP
協議。
常用指令
模板$template
模板 $template
, 最主要的一個指令,在 接收端 可用來定義消息格式、文件名。主要是在接收端使用。
可參考 官方文檔Templates
語法:
1
2
|
$template <name>,<內容>,<可選項>
$template MyTemplateName,"\7Text %property% some more text\n",<options>
|
默認的消息格式 RSYSLOG_TraditionalFileFormat
1
2
|
<接收內容的時間> <發送者的hostname> <
$InputFileTag> <原始消息%msg%>
Dec 18 20:39:27 jumper-172-31-56-18 karltestdemoTag blala... dummy msg
|
如果只需要顯示原始消息,可設置
1
|
$template CleanMsgFormat,"%msg%\n"
|
內置屬性 Properties
模板里支持一些 內置的變量:
1
2
3
4
5
6
7
8
|
%msg%
%syslogfacility%
%HOSTNAME%
%syslogpriority%
%timereported:::date-mysql%
%timegenerated:::date-mysql%
%iut%
'%syslogtag%'
|
屬性處理 Property Replacer
Property Replacer 用來處理變量,支持一些簡單的字符串處理,如大小寫,substring等,類似jinja2的filter概念。
版本越新支持的處理函數越強大。
語法: %property:fromChar:toChar:options%
1
2
3
4
|
# For product
$template productFileFormat,"/Data/logs/product/%fromhost-ip%/%syslogtag:F,44:2%-%$YEAR%%$MONTH%%$DAY%.log"
if $syslogtag startswith 'product' then ?productFileFormat;CleanMsgFormat
& ~
|
上面的例子,在接收端會保存為 /Data/logs/product/198.168.56.123/karltest_demo-20161218.log
解釋下這個指令%syslogtag:F,44:2%
F,
- 代表自定義一個分隔符44
- 是逗號 ,
的 ASCII 碼值,如需要別的分隔符,需要查對應 ASCII 值2
- 取分隔后的第二個字段
所以就是: 假設發送端自定義的tag為 $InputFileTag product,karltest_demo
,
如果tag以product開始,則取出逗號分隔的第二個字段作為保存的文件名,這也是為啥上面tag里要設置一個逗號的緣故。
另外,還支持一定的 regex 語法,可以進行更高級的控制。官方提供了一個在線的 regex 語法測試。
友情提醒:真的很難用。。。
停止指令
上面的接收端,在一條規則后,加上了如下的指令(也叫停止指令),代表如果log被當前的rule已經處理過了,則完成本次執行,跳過后續rule的處理。 類似 C++里 switch/case,如果忘記加break的穿透副作用。
1
|
& ~
|
如果沒有這個指令,則一條新來的消息可以被多個rule處理。 這里我們並不需要,只要命中就保存到接收端同名的文件里。
發送端配置
- 加載 imfile 模塊
- 指定要監控的 log 文件路徑,設置合適的tag
- 指定遠端的接收端的地址
完整配置: /etc/rsyslog.conf 和 /etc/rsyslog.d/product.conf
接收端配置
- 加載 imtcp 模塊
- 設置 message 格式
- 設置 文件存儲路徑,文件名格式
完整配置: /etc/rsyslog.conf
遇到的坑
UDP or TCP ?
一般來說選擇TCP都是OK的,除非忍受部分丟失,在意影響性能,可以改用UDP。
但是注意:如果你的消息每行大小超過了4k,只能用TCP。這是因為UDP棧大小限制的。
引用官方有關 MaxMessageSize 的描述:
Note: testing showed that 4k seems to be the typical maximum for UDP based syslog. This is an IP stack restriction. Not always … but very often. If you go beyond that value, be sure to test that rsyslogd actually does what you think it should do ;) It is highly suggested to use a TCP based transport instead of UDP (plain TCP syslog, RELP). This resolves the UDP stack size restrictions.
如何測試: vim vs echo ?
配置好接收端、發送端rsyslog后,需要驗證下是否能正確傳送新的log行。
- echo追加:
echo "dummy message" >> /Data/logs/product/karltest.log
- vim編輯:
vim /Data/logs/product/karltest.log
用vim編輯后,保存會刷新整個文件,導致rsyslog在比較state file的時候,認為全部是新增的行,會在接收端出現重復的log行。
所以正確測試方法是用 echo 追加的方式。
Tips:
發送端:可以配合 watch 來測試:watch -n 1 " echo $(date) dummy message >> /Data/logs/product/karltest.log "
接收端:tailf /Data/logs/karltest/karltest.log
接收端:log行太長,被截斷了
默認大小是2k,大概可以保存1000個中文字符,參考官方說明 $MaxMessageSize, 最小也是2k。
在加載imtcp/imudp之前設置, 此配置包括發送和接收,所以rsyslog客戶端、服務端都要設置:
1
2
3
4
5
|
$MaxMessageSize 32k
# Provides TCP syslog reception
#$ModLoad imtcp
#$InputTCPServerRun 514
|
發送端:/var/log/messages 文件變大
log除了發送到了接收端,還在本地 /var/log/messages
里重復出現了,導致messages上G
罪魁禍首是默認的配置文件如下這行:
1
2
3
4
5
|
# 修改前
*.info;mail.none;authpriv.none;cron.none /var/
log/messages
# Fix后
*.info;mail.none;authpriv.none;cron.none;
local5.none;local6.none /var/log/messages
|
因為前面有通配符 *.info
導致我們自定義的 local5.info
也會寫到本地messages文件。
為了保險,請把接收端、發送端的配置文件都修改掉,忽略掉local5。
接收端:消息被多個rule處理
在命中某條rule后,直接break停止
1
2
3
4
5
6
7
|
if $syslogtag startswith 'product' then ?productFileFormat;CleanMsgFormat
& ~
# 新版本v6之后,變為:
# rsyslogd: warning: ~ action is deprecated, consider using the 'stop' statement instead [try http://www.rsyslog.com/e/2307 ]
if $syslogtag startswith 'product' then ?productFileFormat;CleanMsgFormat
stop
|
接收端: 保存的文件路徑不對
要注意自定義tag的前綴匹配,如果兩個tag有共同的前綴,需要把長的放在前面,調整好順序。
Fix 前:
1
2
3
4
5
6
7
8
9
|
# For erp_wms
$template erp_wms_FileFormat,"/Data/logs/erp/wms/%fromhost-ip%/%syslogtag:F,44:2%-%$YEAR%%$MONTH%%$DAY%.log"
if $syslogtag startswith 'erp_wms' then ?erp_wms_FileFormat;CleanMsgFormat
& ~
# For erp_wms3
$template erp_wms3_FileFormat,"/Data/logs/erp/wms3/%fromhost-ip%/%syslogtag:F,44:2%-%$YEAR%%$MONTH%%$DAY%.log"
if $syslogtag startswith 'erp_wms3' then ?erp_wms3_FileFormat;CleanMsgFormat
& ~
|
Fix 后:
1
2
3
4
5
6
7
8
9
10
|
# 這里注意下面的tag的順序, 一定要讓長的tag(erp_wms3)保持在上面,因為他們有共同的前綴(erp_wms)
# For erp_wms3
$template erp_wms3_FileFormat,"/Data/logs/erp/wms3/%fromhost-ip%/%syslogtag:F,44:2%-%$YEAR%%$MONTH%%$DAY%.log"
if $syslogtag startswith 'erp_wms3' then ?erp_wms3_FileFormat;CleanMsgFormat
& ~
# For erp_wms
$template erp_wms_FileFormat,"/Data/logs/erp/wms/%fromhost-ip%/%syslogtag:F,44:2%-%$YEAR%%$MONTH%%$DAY%.log"
if $syslogtag startswith 'erp_wms' then ?erp_wms_FileFormat;CleanMsgFormat
& ~
|
接收端: rsyslog 文件名太長后被截斷
比如發送端原始文件名tag: product,cache_status_im_request.log
但是到了接收端就截斷了: cache_status_im_re-20161218.log
因為本來名字就長,加上了時間后更長了,
個人理解,Linux中關於文件名(255),文件路徑(4096)的限制如下,而在接收端,都沒有超過這個長度。
$ cat /usr/include/linux/limits.h
#ifndef _LINUX_LIMITS_H
#define _LINUX_LIMITS_H
#define NR_OPEN 1024
#define NGROUPS_MAX 65536 /* supplemental group IDs are available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
#define LINK_MAX 127 /* # links a file may have */
#define MAX_CANON 255 /* size of the canonical input queue */
#define MAX_INPUT 255 /* size of the type-ahead buffer */
#define NAME_MAX 255 /* # chars in a file name */
#define PATH_MAX 4096 /* # chars in a path name including nul */
#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
#define RTSIG_MAX 32
#endif
進過一番艱難的測試復現,猜測是 $InputFileTag
這個 %syslogtag%
的原因。
官方解釋Sending messages with tags larger than 32 characters。
發送端默認的模板為:
1
2
3
|
# 忽略舊的5.8.6的語法
template (name=
"ForwardFormat" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME%
%syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%")
|
可以看到 %syslogtag:1:32%
,被截斷到32字符,這個也與我測試的結果一致。
所以如果需要處理更長的tag,需要修改 發送端的template模板,去掉 :1:32
限制。
然后綁定這個模板到對應的target上。
注意:接收端可能也要相應處理,才能handle更長的tag名(未測試)。
免責聲明:由於折騰這個rsyslog太累,最后一條暫時沒有Fix,如有需要,請自行測試后再用。
UPDATED @ 2017-01-24
這個問題越來越嚴重,所以必須花時間解決掉。
如下的兩個%syslogtag%,由於前32個字符都相同,導致最后日志寫到同一個文件 databas.log
(按照逗號切割后)了。
1
2
3
4
5
6
|
$InputFileName /Data/logs/mqorder/order-mq-aws/database-stat.log
$InputFileTag erp_mqorder-order-mq-aws,database-stat # 長度39
...
$InputFileName /Data/logs/mqorder/order-mq-aws/database-timeout.log
$InputFileTag erp_mqorder-order-mq-aws,database-timeout # 長度42
...
|
解決方法 :
在發送端的主配置文件 /etc/rsyslog.conf
里修改發送規則:
1
2
3
4
5
6
7
8
9
10
11
|
# ### begin forwarding rule ###
$template LongTagForwardFormat,"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%"
$WorkDirectory /var/lib/rsyslog # where to place spool files
$ActionQueueFileName karlzhou_fwdRule # unique name prefix for spool files
$ActionQueueMaxDiskSpace 5g # 5gb space limit (use as much as possible)
$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
$ActionQueueType LinkedList # run asynchronously
$ActionResumeRetryCount -1 # infinite retries if host is down
local5.* @@rsyslog.karlzhou.org:514;LongTagForwardFormat
# ### end of the forwarding rule ###
|
其中起作用的就是 LongTagForwardFormat
這個模板。
解決過程 :
TL;DR
參考了上面的鏈接: 官方解釋Sending messages with tags larger than 32 characters 和 tag getting truncated。
官方解釋里是 5.8.6 的舊的語法,而CentOS6.x Final上自帶的是 5.8.10, 語法不一樣。
從官網下載5.8.10的源碼: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.10.tar.gz
全文搜索關鍵字 %syslogtag
, 最終在如下幾個文件找到蛛絲馬跡:
- rsyslog-5.8.10/tools/smfwd.c
- rsyslog-5.8.10/tools/smtradfile.c
- rsyslog-5.8.10/tools/smtradfwd.c
- rsyslog-5.8.10/tools/syslogd.c
全文搜索關鍵字 ForwardFormat
:
- rsyslog-5.8.10/tools/syslogd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/* hardcoded standard templates (used
for defaults) */
static uchar template_DebugFormat[] =
"\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% rawmsg: '%rawmsg%'\n\n\"";
static uchar template_SyslogProtocol23Format[] =
"\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
static uchar template_TraditionalFileFormat[] =
"=RSYSLOG_TraditionalFileFormat";
static uchar template_FileFormat[] =
"=RSYSLOG_FileFormat";
static uchar template_ForwardFormat[] =
"=RSYSLOG_ForwardFormat";
static uchar template_TraditionalForwardFormat[] =
"=RSYSLOG_TraditionalForwardFormat";
static uchar template_WallFmt[] =
"\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
static uchar template_StdUsrMsgFmt[] =
"\" %syslogtag%%msg%\n\r\"";
static uchar template_StdDBFmt[] =
"\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
static uchar template_StdPgSQLFmt[] =
"\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
static uchar template_spoofadr[] =
"\"%fromhost-ip%\"";
/* end templates */
|
正如官網鏈接所說,源碼里 hardcoded 里多個默認模板格式,
其中我們需要關注的就是 RSYSLOG_ForwardFormat
, 對應的文件即:rsyslog-5.8.10/tools/smfwd.c
。
1
2
3
4
5
6
7
8
9
10
11
|
/* smfwd.c
* This is a strgen module for the traditional (network) forwarding format.
*
* Format generated:
* "<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%"
*
* NOTE: read comments in module-template.h to understand how this file
* works!
*
* File begun on 2010-06-01 by RGerhards
*
|
這里,就能找到我們需要的正確的默認格式了, 可以看到 %syslogtag% 截取了前面32個字符,把ForwardFormat規則替換成完整的 %syslogtag% 即可,注意:最大的長度是512。
接下來……
通過一番設置,我們已經能成功收集若干台線上機器的日志了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# tree -I "*gz|*log" /Data/logs/
/Data/logs/
├── gateway
│ ├── 172.31.70.18
│ │ └── archived
│ ├── 172.31.70.19
│ │ └── archived
│ ├── 172.31.70.195
│ │ └── archived
│ ├── 172.31.70.197
│ │ └── archived
│ ├── 172.31.70.198
│ │ └── archived
│ └── 172.31.70.20
│ └── archived
├── product
│ ├── 172.31.70.118
│ │ └── archived
│ ├── 172.31.70.119
│ │ └── archived
│ ├── 172.31.70.23
│ │ └── archived
│ └── 172.31.70.24
│ └── archived
...
# du -sh /Data/logs
271G /Data/logs
|
那么問題來了:
上百台機器的上幾百G的日志,怎么才能避免接收端硬盤爆掉?
得用另一個Linux自帶的腳本 /usr/sbin/logrotate
, 來配合 rsyslog。