ELK 的安装部署已经是第 N 次了! 其实也很简单, 这里记下来, 以免忘记.
- #Elasticsearch 安装部署
- wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.1.tar.gz
- tar -zxvf Elasticsearch-6.0.1.tar.gz
- cd Elasticsearch-6.0.1
- # 配置. 如下 集群名称; 节点名称; 供外网访问的 ip(xxx.xxx.xxx.xxx 或 0.0.0.0); 端口 (注意空格)
vi config/Elasticsearch.YAML
- cluster.name: my-application
- node.name: node-1
- network.host: ip
- http.port: 9200
- # 启动
- useradd es # 需要非 root 用户
- su es
- ./bin/Elasticsearch -d
- # ./Elasticsearch -q 关闭
- exit
- cd ..
- # 访问
- curl ip:9200
- #kibana 安装部署
- wget https://artifacts.elastic.co/downloads/kibana/kibana-6.0.1-linux-x86_64.tar.gz
- tar -zxvf kibana-6.0.1-Linux-x86_64.tar.gz
- cd kibana-6.0.1
vi config/kibana.YAML
- # 配置信息 服务端口; kibana 服务 ip;es 的外网访问 ip;index
- server.port: 5601
- server.host: "0.0.0.0"
- Elasticsearch.url: "http://xxx.xxx.xxx.xxx:9200" # 注意 ip,url 不能使用 localhost,127.0.0.1, 必须使用实际的 ip!!!
- kibana.index: ".kibana"
- # 启动
- nohup ./bin/kibana &
- cd ..
- # 访问
- curl ip:5601
- #Logstash 安装部署
- wget https://artifacts.elastic.co/downloads/logstash/logstash-6.0.1.tar.gz
- tar -zxvf logstash-6.0.1.tar.gz
- cd logstash-6.0.1
- # 配置
- vi logstash-6.0.1/config/logs_to_es.conf
- input {
- file {
- type => "tomcat-catalina"
- path => "/opt/apps/apache-tomcat7/logs/catalina.log"
- codec => multiline {
- pattern => "^\s"
- what => "previous"
- }
- }
- }
- filter {
- #Only matched data are send to output.
- }
- output {
- Elasticsearch {
- action => "index" #The operation on ES
- hosts => "xxx.xxx.xxx.xxx:9200" #Elasticsearch host, can be array.
- index => "tomcat_log" #The index to write data to.
- }
- }
- # 启动
- nohup ./bin/logstash -f config/logs_to_es.conf &
- cd ..
测试:
- # Logstash 管道测试代码
- bin/logstash -e 'input{stdin {}} output{stdout{}}'
- # 参考 https://blog.csdn.net/zhaojiweiwin/article/details/80281525
上面的脚本, 只要把 vi 部分换成 sed -i 或类似免交互的命令, 那么其实是可以一键 快速完成 ELK 的安装部署. 需要注意的是 ip 是不能使用 localhost 或 127.0.0.1 的, 而是需要实际的 ip.
当然, 上面的 logstash 的配置文件是很示例的, 可能不够. 我实际上使用的是下面的配置:
- input {
- file {
- type => "erdp-rc"
- #path => "/app/java/logs/nohup-erdp_${WORD:app}-*.log"
- path => "/app/java/logs/nohup-erdp_*.log"
- #add_field => {"app2"=>"aa"}
- codec => multiline {
- pattern => "^%{TIMESTAMP_ISO8601}"
- negate => true
- what => "previous"
- }
- }
- }
- filter {
- #Only matched data are send to output.
- grok {
- # match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s? %{LOGLEVEL:level} %{INT:pid} --- \[%{URIPATHPARAM:thread}\] %{NOTSPACE:clz}\s+: %{GREEDYDATA:msg}" }
- match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s? %{LOGLEVEL:level} %{INT:pid} --- \[%{NOTSPACE:thread}\] %{NOTSPACE:clz}\s+: %{GREEDYDATA:msg}" }
- }
- grok {
- # match => ["path","%{GREEDYDATA}/nohup-erdp_%{WORD:appName}_%{GREEDYDATA}\.log"]
- match => ["path","%{GREEDYDATA}/nohup-erdp_(?[a-zA-Z0-9.-]+)_%{DATA}\.log"]
- }
- # date {
- # match => [ "timestamp" , "YYYY-MM-dd HH:mm:ss.SSS" ]
- # }
- }
- output {
- Elasticsearch {
- action => "index" #The operation on ES
- hosts => "192.168.11.183:9200" #Elasticsearch host, can be array.
- index => "erdp_log" #The index to write data to.
- }
- }
上面的两个 grok 花了我不少时间. 有些蛋疼. 因为 Logstash 不方便调试, 需要修改 conf, 然后重启, 然后操作, 然后等待日志输出到 elk, 然后 kibana 上面观察. 观察不到呢, 还要怀疑是否是自己的查询条件写错了, 各种修改, 折腾. 这样的一次手动调试下来需要 2-6 分钟. 在线的 grok debugger 又用不了. 真是麻烦.
如上, 可以看到 URIPATHPARAM 用来匹配线程 thread 就出问题了! 开始一直没怀疑. 为什么 URIPATHPARAM 不行, 而 NOTSPACE 就可以呢? 如下
- URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;[email protected]#%_\-]*)+
- #URIPARAM \?(?:[A-Za-z0-9]+(?:=(?:[^&]*))?(?:&(?:[A-Za-z0-9]+(?:=(?:[^&]*))?)?)*)?
- URIPARAM \?[A-Za-z0-9$.+!*'|(){
- },[email protected]#%&/=:;_?\-\[\]]*
- URIPATHPARAM %{
- URIPATH
- }(?:%{
- URIPARAM
- })?
我感觉是匹配到 URIPATHPARAM 后面的就出问题了, 但是 Logstash 没有报错. 所以, 问题一直排查不出来.
士大夫
另外, 需要通过文件名, 找到对应的应用, 添加一个 app_name 的字段, 搞了好久啊.
最开始的时候想通过 input-file-add_field 插件添加进来, 发现 input-file 的 path 无法使用分组, 无法将文件名读取到, 其他通配符也无效..
搜索 "logstash path 添加字段" , 不行. 后面搜索 "logstash get the file name as field" 终于找到了
(其实之前找到了 http://www.voidcn.com/article/p-rueddyth-btd.html, 但是觉得这样效率低, 我就想通过 add_field, 而不想通过 grok 的方式 http://www.voidcn.com/article/p-rueddyth-btd.html )
后面明白, 只能通过 grok 的方式了! 仔细想想, 其实 grok 的方式的效率应该是也是差不多的.
另外注意到 filter 的 grok 是可以多个的, input 的 file 其实也可以多个并行.
但是, 我需要通过 log 文件名再截取一段, appName, 发现 %{Word:appName}, 发现死活不行, 或时好时坏, 后面改成 [a-zA-Z0-9.-]+), 就终于好了! 浪费一两个小时时间啊!
仔细检查, 原来啊, Word 是必须有边界的!--> Word \b\w+\b . 我开始还在怀疑 自定义的 grok 语法是不是搞错了呢! --> (?<field>regex) , 后面又怀疑 GREEDYDATA 是不是应该改为 DATA. 其实都不是的.
附常见的内置的 gork 正则表达式:
- USERNAME [a-zA-Z0-9._-]+
- USER %{
- USERNAME
- }
- INT (?:[+-]?(?:[0-9]+))
- BASE10NUM (?0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
- NUMBER (?:%{
- BASE10NUM
- })
- BASE16NUM (?0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
- BASE16FLOAT \b(?0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b
- POSINT \b(?:[1-9][0-9]*)\b
- NONNEGINT \b(?:[0-9]+)\b
- Word \b\w+\b
- NOTSPACE \S+
- SPACE \s*
- DATA .*?
- GREEDYDATA .*
- QUOTEDSTRING (?>(?\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|"|(?>(?>\\.|[^\]+)+)|`))
- UUID [A-Fa-f0-9]{
- 8
- }-(?:[A-Fa-f0-9]{
- 4
- }-){
- 3
- }[A-Fa-f0-9]{
- 12
- }
- Mac (?:%{
- CISCOMAC
- }|%{
- WINDOWSMAC
- }|%{
- COMMONMAC
- })
- IPV4 (?
- 1,2
- })[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{
- 1,2
- })[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{
- 1,2
- })[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{
- 1,2
- }))(?![0-9])
- IP (?:%{
- IPV6
- }|%{
- IPV4
- })
- HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{
- 0,62
- })(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{
- 0,62
- }))*(\.?|\b)
- HOST %{
- HOSTNAME
- }
- IPORHOST (?:%{
- HOSTNAME
- }|%{
- IP
- })
- HOSTPORT (?:%{
- IPORHOST=~/\./
- }:%{
- POSINT
- })
- # Years?
- YEAR (?>\d\d){
- 1,2
- }
- HOUR (?:2[0123]|[01]?[0-9])
- MINUTE (?:[0-5][0-9])
- # '60′ is a leap second in most time standards and thus is valid.
- SECOND (?:(?:[0-5][0-9]|60)(?:[:.,][0-9]+)?)
- TIME (?!<[0-9])%{
- HOUR
- }:%{
- MINUTE
- }(?::%{
- SECOND
- })(?![0-9])
- # datestamp is YYYY/MM/DD-HH:MM:SS.UUUU (or something like it)
- DATE_US %{
- MONTHNUM
- }[/-]%{
- MONTHDAY
- }[/-]%{
- YEAR
- }
- DATE_EU %{
- MONTHDAY
- }[./-]%{
- MONTHNUM
- }[./-]%{
- YEAR
- }
- ISO8601_TIMEZONE (?:Z|[+-]%{
- HOUR
- }(?::?%{
- MINUTE
- }))
- ISO8601_SECOND (?:%{
- SECOND
- }|60)
- TIMESTAMP_ISO8601 %{
- YEAR
- }-%{
- MONTHNUM
- }-%{
- MONTHDAY
- }[T ]%{
- HOUR
- }:?%{
- MINUTE
- }(?::?%{
- SECOND
- })?%{
- ISO8601_TIMEZONE
- }?
- DATE %{
- DATE_US
- }|%{
- DATE_EU
- }
- DATESTAMP %{
- DATE
- }[- ]%{
- TIME
- }
- TZ (?:[PMCE][SD]T|UTC)
- DATESTAMP_RFC822 %{
- DAY
- } %{
- MONTH
- } %{
- MONTHDAY
- } %{
- YEAR
- } %{
- TIME
- } %{
- TZ
- }
- DATESTAMP_OTHER %{
- DAY
- } %{
- MONTH
- } %{
- MONTHDAY
- } %{
- TIME
- } %{
- TZ
- } %{
- YEAR
- }
- # Log Levels
- LOGLEVEL ([A-a]lert|ALERT|[T|t]race|TRACE|[D|d]ebug|DEBUG|[N|n]otice|NOTICE|[I|i]nfo|INFO|[W|w]arn?(?:ing)?|WARN?(?:ING)?|[E|e]rr?(?:or)?|ERR?(?:OR)?|[C|c]rit?(?:ical)?|CRIT?(?:ICAL)?|[F|f]atal|FATAL|[S|s]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)
- https://www.cnblogs.com/dyh004/p/9700110.html
来源: http://www.bubuko.com/infodetail-3071344.html