【问题标题】:Parse multiple log files for strings解析多个日志文件的字符串
【发布时间】:2017-07-06 05:49:58
【问题描述】:

我正在尝试从日志目录中解析多个日志文件,以在列表中搜索任意数量的字符串以及服务器名称。我觉得我已经尝试了一百万种不同的选项,并且只使用一个日志文件就可以正常工作。但是当我尝试浏览目录中的所有日志文件时,我似乎无处可去。

if args.f:
    logs = args.f
else:
    try:
        logs = glob("/var/opt/cray/log/p0-current/*")
    except IndexError:
        print "Something is wrong. p0-current is not available."
        sys.exit(1)

valid_errors = ["error", "nmi", "CATERR"]

logList = []
for log in logs:
    logList.append(log)



#theLog = open("logList")
#logFile = log.readlines()
#logFile.close()
#printList = []

#for line in logFile:
#    if (valid_errors in line):
#        printList.append(line)
#
#for item in printList:
#    print item


#    with open("log", "r") as tmp_log:

#       open_log = tmp_log.readlines()
#           for line in open_log:
#               for down_nodes in open_log:
#                   if valid_errors in open_log:
#                       print valid_errors

down_nodes 是一个预先填充的列表,位于脚本的上方,其中包含标记为关闭的服务器列表。

注释掉了一些我一直在努力的各种尝试。

logList = []
for log in logs:
    logList.append(log)

我认为这可能是将每个单独的日志文件放在一个列表中的方法,然后遍历这个列表并使用 open() 后跟 readlines() 但我在这里缺少某种逻辑..也许我我的想法不正确。

我真的可以在这里做一些指针。

谢谢。

【问题讨论】:

  • glob 返回的日志已经是一个列表。

标签: python linux python-2.7 logging glob


【解决方案1】:

所以你的最后一个 for 循环是多余的,因为 logs 已经是一个字符串列表。有了这些信息,我们可以遍历 logs 并为每个 log 做一些事情。

for log in logs:
    with open(log) as f:
        for line in f.readlines():
            if any(error in line for error in valid_errors):
                #do stuff

if any(error in line for error in valid_errors): 行检查line 以查看valid_errors 中的任何错误是否在行中。语法是一个生成器,它为valid_errors 中的每个error 生成error

要回答您涉及down_nodes 的问题,我认为您不应将其包含在同一个any() 中。你应该尝试类似

if any(error in line for error in valid_errors) and \
    any(node in line for node in down_nodes):

【讨论】:

  • 啊太棒了。我想多了。它似乎工作得很好:) - 我不知道最后一行,任何(有效错误中的错误在线错误): - 错误是这里的变量吗?像 i 或 line 等?我以前没见过这个。 any() 是一件有用的事情。但是,如果您只有一两行解释,我很想了解更多信息? (我试图投票,但它不会让我)
  • @jonnybinthemix 我在答案中添加了一点
  • 谢谢,感谢您抽出宝贵时间为我做这件事 :) - 这很好,很简单,我喜欢。
  • 如果我想调整它来满足两个需求,我还会使用 any() 还是 all()?我猜 all() 将匹配必须匹配 valid_errors 中的所有内容?但是,如果我有另一个名为 down_nodes 的列表,并且我想匹配 down_nodes 中的任何字符串和 valid_errors 中的任何字符串......是否很容易适应上面的内容?
  • 不幸的是,我现在无法对此进行测试,但我想知道这条线是否能满足我的要求:if any(error in line for error in valid_errors and down_nodes): - 你有什么想法?我将能够在几个小时内对其进行测试。
【解决方案2】:

首先你需要找到所有的日志:

import os
import fnmatch

def find_files(pattern, top_level_dir):
    for path, dirlist, filelist in os.walk(top_level_dir):
        for name in fnmatch.filter(filelist, pattern)
            yield os.path.join(path, name)

例如,查找当前目录中的所有*.txt 文件:

txtfiles = find_files('*.txt', '.')

然后从名字中获取文件对象:

def open_files(filenames):
    for name in filenames:
        yield open(name, 'r', encoding='utf-8')

文件中的最后一行:

def lines_from_files(files):
    for f in files:
        for line in f:
            yield line

由于您想查找一些错误,因此检查可能如下所示:

import re

def find_errors(lines):
    pattern = re.compile('(error|nmi|CATERR)')
    for line in lines:
        if pattern.search(line):
            print(line)  

您现在可以处理从给定目录生成的行流:

txt_file_names = find_files('*.txt', '.')
txt_files = open_files(txt_file_names)
txt_lines = lines_from_files(txt_files)
find_errors(txt_lines)

将日志作为数据流处理的想法源于 David Beazley 的谈话。

【讨论】:

  • 啊,这很有趣,谢谢。我在另一个我正在工作的脚本中使用了 re.compile、re.match 等,我想知道它在这里是否有用。但我虽然想显示整个日志行,而不是给定日志行的一部分,所以我认为只转储这些行会更容易。基本上我要做的是让脚本找到已关闭的服务器,然后自动检查一些事情以查看它们是否由于常见原因而关闭......然后在屏幕上显示明显的那些。
猜你喜欢
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 2021-11-27
相关资源
最近更新 更多