我正在尝试编写一个脚本来从 nginx 日志文件中收集过去 24 小时的日志。我的脚本正在从日志文件中收集所有日志,而我只需要过去 24 小时的错误。
脚本来收集过去 24 小时的 nginxaccess.log
和error.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
如何使用
- 将脚本复制到一个空文件中,另存为
get_log.py
使用源文件、输出文件和时间作为参数运行它:
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 提供了示例,并且只能得出该脚本完成其工作以外的结论。