从 nginx 日志文件收集过去 24 小时内的错误

从 nginx 日志文件收集过去 24 小时内的错误

我正在尝试编写一个脚本来从 nginx 日志文件中收集过去 24 小时的日志。我的脚本正在从日志文件中收集所有日志,而我只需要过去 24 小时的错误。

脚本来收集过去 24 小时的 nginxaccess.logerror.log

awk -vDate=`date -d'now-24 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print Date, $0}' /var/log/nginx/access.log > /data/production_logs/nginxaccess.log
awk -vDate=`date -d'now-24 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print Date, $0}' /var/log/nginx/error.log > /data/production_logs/nginxerror.log

第二个脚本:

egrep 'Error|error|Exception|failed|Unhandled|err|Err' /data/production_logs/myapp.log > /data/production_logs/myapp_error.log

脚本示例如下:

egrep 'Error|error|Exception|failed|Unhandled|err|Err' /var/log/nginx/error.log > /var/log/nginx/last24hourlogs.log

仅从过去 24 小时的日志中 grep 上述错误异常并将其保存为last24hourlogs.log

所需日志格式:

2016/11/27 13:55:00 [error] 6822#0: *14569 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 223.182.171.4, server: myappserver
2016/12/03 12:51:26 [error] 6820#0: *19094 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 157.48.95.8, server:

tail -f /home/example.com/.forever/bdapp.log

2016/12/19 12:30:51 [error] 2147#0: *5647 open() "/usr/share/nginx/html/example.com/myapp_email-templates/social-01.png" failed (2: No such file or directory), client: 66.249.84.191, server: example.com, request: "GET /myapp_email-templates/social-01.png HTTP/1.1", host: "example.com"
2016/12/19 12:30:51 [error] 2147#0: *5646 open() "/usr/share/nginx/html/example.com/myapp_email-templates/social-02.png" failed (2: No such file or directory), client: 66.249.84.128, server: example.com, request: "GET /myapp_email-templates/social-02.png HTTP/1.1", host: "example.com"

答案1

读取过去 x 小时内的日志文件,查找特定行

重要笔记

  • 下面的答案是基于 OP 提供的示例编写的,假设输出示例是日志文件中行出现的精确副本。这对于正确解析日期至关重要;如果位置或者 格式时间戳不同,将会失败!
  • 由于缺少排序信息,无法优化脚本的性能;需要使用我们当前掌握的信息检查所有行。
  • 还不清楚日志文件是否以 UTC 或当地时间报告,报告应在什么时间生成。“过去 24 小时”可能需要根据当地时差进行校正。

剧本

#!/usr/bin/env python3
import time
import calendar
import sys

#--- set conditions below 
matches = ['Error', 'error', 'Exception', 'failed', 'Unhandled', 'err', 'Err']
# ---

pattern = "%Y/%m/%d%H:%M:%S"

source = sys.argv[1]
report = sys.argv[2]
last_hrs = sys.argv[3]

# shift =  time.timezone
shift = 0
now = time.time()

def convert_toepoch(pattern, stamp):
    """
    function to convert readable format (any) into epocherror
    """
    return int(time.mktime(time.strptime(stamp, pattern)))

with open(source) as infile:
    with open(report, "wt") as outfile:
        for l in infile:
            try:
                # parse out the time stamp, convert to epoch
                stamp = "".join(l.split()[:2])
                tstamp = convert_toepoch(pattern, stamp)
                # set the conditions the line has to meet
                if now - tstamp - shift <= int(last_hrs)*3600:
                    if any([s in l for s in matches]):
                        outfile.write(l)
            except (IndexError, ValueError):
                pass

如何使用

  1. 将脚本复制到一个空文件中,另存为get_log.py
  2. 使用源文件、输出文件和时间作为参数运行它:

    python3 /path/to/get_log.py <logfile> <ouput_file> 24
    

如上所述,时间 ( 24) 可能需要根据当地时区进行修复。请告知我。

它能做什么

  • 该脚本查找带有时间戳的行,显示定义时间段内的时间(从现在开始 x 小时),并与纪元时间进行比较。如果匹配,它会查找文件中是否存在任何条件字符串。
  • 如果是,则该行将写入报告中

编辑

OP 提到它不起作用。然而,对 OP 应要求发布的两个示例进行的测试表明,该脚本完美地完成了工作:

它为什么有效?

  • Op 的示例-时间戳:

    2016/11/27 13:55:00
    

    转换为以下格式:

    "%Y/%m/%d%H:%M:%S"
    

    按以下方式:

    stamp = "".join(l.split()[:2])
    

    并随后转换为时代:

    tstamp = convert_toepoch(pattern, stamp)
    
  • 以下行:

    if now - tstamp - shift <= int(last_hrs)*3600:
    

    last_hrs选择线条,从现在开始盖章。

  • 以下行:

    if any([s in l for s in matches]):
    

    随后查找是否存在以下字符串:

    ['Error', 'error', 'Exception', 'failed', 'Unhandled', 'err', 'Err']
    

    发生在线路中。

如上所述,我彻底测试了它精确的OP 提供了示例,并且只能得出该脚本完成其工作以外的结论。

相关内容