遇到 nginx 错误请求时如何使用 fluentd regexp
how to use fluentd regexp when meet the nginx bad request
我用fluentd
代替logstash
,我用in-tail
插件来尾nginx access
日志,访问日志的格式是这样的:
log_format main '$remote_addr - $remote_user [$time_local] $request '
'"$status" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $request_time';
fluentd
conf 就像
format /^(?<host>\S+)\s-\s(?<user>\S+)\s\[(?<time>[^\]]*)\]\s(?<method>\S+)\s(?<url>\S+)\s(?<http_version>\S+)\s"(?<status>[^\"]+)"\s(?<bytes>\d+)\s"(?<rfc>[^\"]+)"\s"(?<agent>[^\"]+)"\s"(?<x_forward>[^\"]+)"\s(?<time_spent>\S+).*$/
请求正确时可以正常工作,但请求错误时会出错,如下所示:
172.31.33.157 - - [08/May/2017:16:30:20 +0800] - "400" 0 "-" "-" "-" 0.000
错误的请求错过了method
和rfc
字段,所以fluentd
运行是错误的。如何修改 format
以便我不关心请求是错误的还是正确的?
任何答案将不胜感激
运行进入另一个场景,agent
或rfc
字段为none,出现运行错误。就像
172.31.44.196 - - [08/May/2017:18:47:31 +0800] GET /click?mb_pl=ios&version=1.1 HTTP/1.1 "302" 5 "-" "" "100.38.38.149, 54.224.136.60" 0.004
或
172.31.44.196 - - [08/May/2017:18:47:31 +0800] GET /click?mb_pl=ios&version=1.1 HTTP/1.1 "302" 5 "" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304" "100.38.38.149, 54.224.136.60" 0.004
如何解决这种情况?
您可以将可选的模式部分包装在 可选的非捕获组、(?:...)?
:
中
^(?<host>\S+)\s-\s(?<user>\S+)\s\[(?<time>[^\]]*)\](?:\s(?<method>\S+))?(?:\s(?<url>\S+))?\s(?<http_version>\S+)\s"(?<status>[^\"]+)"\s(?<bytes>\d+)(?:\s"(?<rfc>[^\"]+)")?\s"(?<agent>[^\"]+)"\s"(?<x_forward>[^\"]+)"\s(?<time_spent>\S+).*$
在这里,我包装了以下部分:
(?:\s(?<method>\S+))?
(?:\s(?<url>\S+))?
(?:\s"(?<rfc>[^\"]+)")?
这意味着,整个子模式序列将是可选的,一个空格和命名的捕获组模式。
注意:当您有更多可选字段时,您可能会发现自己处于模式组开始匹配输入中属于其他组的不需要部分的情况。在这种情况下,请确保 限制通用模式 并使用可选模式:将 +
替换为 *
以匹配 0 次或多次出现,而不是 1 次或多次出现,如上所示使用可选组,并确保只匹配预期的 characters/patterns。
查看下面的增强模式:
^(?<host>\S+)\s-\s(?<user>\S+)\s\[(?<time>[^\]]*)\](?:\s(?<method>\w+))?(?:\s(?<url>\/\S+))?\s(?<http_version>\S+)\s"(?<status>\d+)"\s(?<bytes>\d+)(?:\s"(?<rfc>[^\"]*)")?(?:\s"(?<agent>[^\"]*)")?\s"(?<x_forward>[^\"]*)"\s(?<time_spent>[\d.]+).*$
参见regex demo。
这里有一些兴趣点:
(?<method>\w+))?
- 在这里,我们只匹配单词字符 (\S
> \w
,您甚至可以考虑使用 [A-Z]
)
(?:\s(?<url>\/\S+))?
- 添加了 /
因为您的 URL 以 /
开头
(?<status>\d+)
- \S
更改为 \d
(因为状态代码仅由数字组成)
(?<rfc>[^\"]*)")?
- +
更改为 *
(值可以为空)
(?:\s"(?<agent>[^\"]*)")?
- 这里与 rfc
相同
\s"(?<x_forward>[^\"]*)"
- 同上
(?<time_spent>[\d.]+
- time_spent 值仅包含数字和点。
我用fluentd
代替logstash
,我用in-tail
插件来尾nginx access
日志,访问日志的格式是这样的:
log_format main '$remote_addr - $remote_user [$time_local] $request '
'"$status" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $request_time';
fluentd
conf 就像
format /^(?<host>\S+)\s-\s(?<user>\S+)\s\[(?<time>[^\]]*)\]\s(?<method>\S+)\s(?<url>\S+)\s(?<http_version>\S+)\s"(?<status>[^\"]+)"\s(?<bytes>\d+)\s"(?<rfc>[^\"]+)"\s"(?<agent>[^\"]+)"\s"(?<x_forward>[^\"]+)"\s(?<time_spent>\S+).*$/
请求正确时可以正常工作,但请求错误时会出错,如下所示:
172.31.33.157 - - [08/May/2017:16:30:20 +0800] - "400" 0 "-" "-" "-" 0.000
错误的请求错过了method
和rfc
字段,所以fluentd
运行是错误的。如何修改 format
以便我不关心请求是错误的还是正确的?
任何答案将不胜感激
运行进入另一个场景,agent
或rfc
字段为none,出现运行错误。就像
172.31.44.196 - - [08/May/2017:18:47:31 +0800] GET /click?mb_pl=ios&version=1.1 HTTP/1.1 "302" 5 "-" "" "100.38.38.149, 54.224.136.60" 0.004
或
172.31.44.196 - - [08/May/2017:18:47:31 +0800] GET /click?mb_pl=ios&version=1.1 HTTP/1.1 "302" 5 "" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304" "100.38.38.149, 54.224.136.60" 0.004
如何解决这种情况?
您可以将可选的模式部分包装在 可选的非捕获组、(?:...)?
:
^(?<host>\S+)\s-\s(?<user>\S+)\s\[(?<time>[^\]]*)\](?:\s(?<method>\S+))?(?:\s(?<url>\S+))?\s(?<http_version>\S+)\s"(?<status>[^\"]+)"\s(?<bytes>\d+)(?:\s"(?<rfc>[^\"]+)")?\s"(?<agent>[^\"]+)"\s"(?<x_forward>[^\"]+)"\s(?<time_spent>\S+).*$
在这里,我包装了以下部分:
(?:\s(?<method>\S+))?
(?:\s(?<url>\S+))?
(?:\s"(?<rfc>[^\"]+)")?
这意味着,整个子模式序列将是可选的,一个空格和命名的捕获组模式。
注意:当您有更多可选字段时,您可能会发现自己处于模式组开始匹配输入中属于其他组的不需要部分的情况。在这种情况下,请确保 限制通用模式 并使用可选模式:将 +
替换为 *
以匹配 0 次或多次出现,而不是 1 次或多次出现,如上所示使用可选组,并确保只匹配预期的 characters/patterns。
查看下面的增强模式:
^(?<host>\S+)\s-\s(?<user>\S+)\s\[(?<time>[^\]]*)\](?:\s(?<method>\w+))?(?:\s(?<url>\/\S+))?\s(?<http_version>\S+)\s"(?<status>\d+)"\s(?<bytes>\d+)(?:\s"(?<rfc>[^\"]*)")?(?:\s"(?<agent>[^\"]*)")?\s"(?<x_forward>[^\"]*)"\s(?<time_spent>[\d.]+).*$
参见regex demo。
这里有一些兴趣点:
(?<method>\w+))?
- 在这里,我们只匹配单词字符 (\S
>\w
,您甚至可以考虑使用[A-Z]
)(?:\s(?<url>\/\S+))?
- 添加了/
因为您的 URL 以/
开头
(?<status>\d+)
-\S
更改为\d
(因为状态代码仅由数字组成)(?<rfc>[^\"]*)")?
-+
更改为*
(值可以为空)(?:\s"(?<agent>[^\"]*)")?
- 这里与rfc
相同
\s"(?<x_forward>[^\"]*)"
- 同上(?<time_spent>[\d.]+
- time_spent 值仅包含数字和点。