前言
之前談了 Elasticsearch 和 Kibana 的安裝,作為開源實(shí)時(shí)日志分析平臺(tái) ELK 的一部分,當(dāng)然少不了 Logstash 。其實(shí) Logstash 的作用就是一個(gè)數(shù)據(jù)收集器,將各種格式各種渠道的數(shù)據(jù)通過它收集解析之后格式化輸出到 Elasticsearch ,最后再由
Kibana 提供的比較友好的 Web 界面進(jìn)行匯總、分析、搜索。
ELK 內(nèi)部實(shí)際就是個(gè)管道結(jié)構(gòu),數(shù)據(jù)從 Logstash 到 Elasticsearch 再到 Kibana 做可視化展示。這三個(gè)組件各自也可以單獨(dú)使用,比如 Logstash 不僅可以將數(shù)據(jù)輸出到
Elasticsearch ,也可以到數(shù)據(jù)庫、緩存等。下面看看 Logstash 的安裝和基本的使用。
安裝
到官網(wǎng)根據(jù)不同操作系統(tǒng)下載最新版本的Logstash壓縮包,之后本地解壓縮。
運(yùn)行
解壓縮之后就可以運(yùn)行了,在 Logstash 的根目錄下執(zhí)行命令:
bin/logstash -e "input { stdin {}} output { stdout {}}"
控制臺(tái)輸出“Successfully started Logstash API endpoint”表示 Logstash 啟動(dòng)成功
命令里的-e表示后面跟著的是一個(gè)配置信息字符串,字符串的功能就是讓 Logstash
接受控制臺(tái)里的輸入,并輸出到控制臺(tái),比如在控制臺(tái)輸入 hello world :
如果用最簡化的方式執(zhí)行:
bin/logstash -e ""
會(huì)看到 Logstash 采用了默認(rèn)的配置,從控制臺(tái)輸入,并以 json 格式輸出到控制臺(tái):
配置文件
實(shí)際運(yùn)維中配置信息通常會(huì)放配置文件中來管理,這種情況下 Logstash 提供了 -f 參數(shù)來指定配置信息所在的配置文件。在 Logstash 的根目錄下執(zhí)行命令:
bin/logstash -f config/demo.conf
Logstash 會(huì)加載 config 目錄中 demo.conf 文件,文件中的內(nèi)容作為配置信息,看下
demo.conf 文件的內(nèi)容:
input { stdin {}}
output { stdout {}}
執(zhí)行命令之后會(huì)發(fā)現(xiàn)其行為和上面的 -e 配置字符串是一樣的,輸入什么字符控制臺(tái)顯示什么字符。
工作原理
Logstash 內(nèi)部也是管道的方式進(jìn)行數(shù)據(jù)的搜集、處理、輸出。在 Logstash 中,包括了三個(gè)階段:
輸入 input --> 處理 filter(不是必須的) --> 輸出 output
每個(gè)階段都由很多的插件配合工作,比如 file、elasticsearch、redis 等等。
每個(gè)階段也可以指定多種方式,比如輸出既可以輸出到 Elasticsearch 中,也可以指定到 stdout 在控制臺(tái)打印。
正是由于這種插件方式,使得 Logstash 變得易于擴(kuò)展和定制,下面分別看看這三個(gè)階段的一些插件的使用。
input-file 插件
看下 input 的一個(gè)插件例子。上面講的是從控制臺(tái)輸入,如果要從文件讀取輸入,則可以用 file 插件:
input { file { path => "/tmp/abc.log" }}
上面是這個(gè)插件的最小化配置, path 后面跟隨的是文件的全路徑名,如果要匹配一個(gè)目錄下的所有文件,可以用通配符*:
input { file { path => "/tmp/data/*" } }
要匹配多個(gè)不同目錄下的文件,則用中括號(hào)括起來,并逗號(hào)分隔不同文件路徑:
input { file { path => ["/tmp/data/*","/log/abc/hello.log"] }}
注意文件的路徑名需要時(shí)絕對路徑。
output-elasticsearch 插件
如果要將數(shù)據(jù)輸出到,則可以用 Elasticsearch 插件:
output {
elasticsearch {
action => "index"
hosts => "localhost:9200"
index => "log-example"
}
}
上面配置的含義是,將數(shù)據(jù)輸出到 Elasticsearch 服務(wù)器,hosts 是提供服務(wù)的地址和端口號(hào),action 是指索引到一個(gè)文檔,index 是指要被寫進(jìn)的索引名,當(dāng)然還有其他參數(shù)配置,具體參見該插件的官方文檔說明
filter-grok 插件
不論是 input 的 stdin 還是 file 插件,都是從不同來源讀取數(shù)據(jù),但它們讀取的都是一行一行的文本數(shù)據(jù),輸出的時(shí)候會(huì)發(fā)現(xiàn)它們都是作為一行放到輸出的 message 屬性中:
很多情況下需要對這些文本做格式化的解析再輸出,比如日志文件中數(shù)據(jù)格式是這樣的:
[2017-04-03 23:30:11.020][INFO][logstash] Pipeline main started
上面的文本格式是:[時(shí)間][日志級(jí)別][模塊名]日志信息描述
輸出 json 時(shí)也希望將時(shí)間放到自定義的 TimeStamp 屬性中,將日志級(jí)別信息放到
LogLevel 屬性中,將模塊名放到 ModuleName 屬性中,將日志信息描述放到
LogDesc 屬性中。
如果是這種需求就用到了 grok 插件,該插件是 Logstash 將普通文本解析成結(jié)構(gòu)化數(shù)據(jù)的最好的方式。(這可不是我非要安利,是官網(wǎng)上說的:Grok is currently the best way in logstash to parse crappy unstructured log data into something structured and queryable.)
- grok 表達(dá)式
grok 表達(dá)式語法是這樣的:
%{SYNTAX:SEMANTIC}
SYNTAX 是要匹配的文本的模式名。SEMANTIC 是匹配出的內(nèi)容的標(biāo)識(shí)符,該標(biāo)識(shí)符即輸出到 output 中的屬性名。看一個(gè)簡單的 grok 表達(dá)式例子:
%{IP:source_ip}
它表示使用名為 IP 的正則表達(dá)式提取內(nèi)容,并將匹配出的內(nèi)容命名為 source_ip 。所以如果輸入是 IP 地址的格式:11.22.33.123,則會(huì)將該內(nèi)容放到 source_ip 中。
-
grok 中預(yù)定義的模式
上面的 IP 是 grok 里預(yù)定義的模式,其正則表達(dá)式的定義實(shí)際是:
IP 模式定義
grok 已經(jīng)預(yù)定義了很多模式,比如匹配一串?dāng)?shù)字可以用 NUMBER、匹配 MAC 地址用 MAC、匹配時(shí)間用 TIMESTAMP_ISO8601、匹配 LOG 日志級(jí)別用 LOGLEVEL
等等。詳細(xì)定義參見github 中的說明 grok 中的自定義模式
如果上面列的這些模式不能滿足需求,grok 也允許自定義模式。
先看下自定義模式的語法:
pattern_name regexp
pattern_name 就是自定義的模式名,regexp 就是模式的正則表達(dá)式定義,之間用一個(gè)空格分隔開。比如自定義一個(gè)隊(duì)列 ID 模式,它的格式是10或11個(gè)數(shù)字、大寫字母組成的字符串,其定義語法如下:
QUEUE_ID [0-9A-F]{10,11}
熟悉正則表達(dá)是的應(yīng)該知道[0-9A-F]表示數(shù)字、大寫字母組成的字符,后面的{10,11}表示有10或11個(gè)這樣的字符。
接著在 Logstash 根目錄下建一個(gè) patterns 目錄,該目錄下新建一個(gè)文件叫
myPattern 。文件內(nèi)容就是:
QUEUE_ID [0-9A-F]{10,11}
最后在 filter 配置中加上 patterns 目錄,并引用上面定義的這個(gè) QUEUE_ID :
filter {
grok {
patterns_dir => ["./patterns"]
match => { "message" => "%{TIMESTAMP_ISO8601:TimeStamp} %{QUEUE_ID:queue_id}: %{GREEDYDATA:syslog_message}" }
}
}
patterns_dir 用于指定自定義模式的文件所在的目錄,match 的內(nèi)容就是 grok 表達(dá)式,TIMESTAMP_ISO8601 和 GREEDYDATA 預(yù)定義的模式,QUEUE_ID 是自定義的模式。它將匹配以下格式的內(nèi)容:
2017-04-03 23:30:11.020 12345abcde hello world
匹配后的結(jié)果是:
{"@timestamp": "2017-04-12T11:57:40.186Z", "queue_id": "12345abcde", "@version": "1", "syslog_message": "hello world", "message": "2017-04-03 23:30:11.020 12345abcde hello world", "TimeStamp": "2017-04-03 23:30:11.020"}
- 日志文件的 filter 配置
所以上面的日志文件中數(shù)據(jù)的 filter 區(qū)段配置:
filter {
grok {
match => {
"message" => "\[%{TIMESTAMP_ISO8601:TimeStamp}\]\[%{LOGLEVEL:LogLevel}\]\[%{WORD:ModuleName}\] %{GREEDYDATA:LogDesc}"
}
}
}
由于中括號(hào)是特殊字符,所以正則表達(dá)式中它的前面要加上反斜杠\。
加載文件配置后運(yùn)行結(jié)果如下: