2012-03-11 25 views
2

我需要分析一个系统日志。我被告知我应该拆分一个列表,然后遍历它来查找一个IP地址。这是日志的一小部分。有重复的条目,因此我只能注意到包含单词“从根失效密码”的行。Python - 分割一个列表,然后循环查找一个IP地址

Jan 10 09:32:07 j4-be03 sshd[3876]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.241.173.35 user=root 
Jan 10 09:32:09 j4-be03 sshd[3876]: Failed password for root from 218.241.173.35 port 47084 ssh2 
Jan 10 09:32:17 j4-be03 sshd[3879]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.241.173.35 user=root 
Jan 10 09:32:19 j4-be03 sshd[3879]: Failed password for root from 218.241.173.35 port 47901 ssh2 
Jan 10 09:32:26 j4-be03 sshd[3881]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.241.173.35 user=root 
Jan 10 09:32:29 j4-be03 sshd[3881]: Failed password for root from 218.241.173.35 port 48652 ssh2 

这是我的代码到目前为止,还有一些伪代码。

f=open('auth','r') 
count=0 
for line in f: 
    if "failed password for root from" in line: 
count +=1 
if count>=13: 
    take the ip address, remove duplicates and print the address 

如果有从一个IP地址13次或更多的尝试这个地址必须被添加到一个文件中。我知道如何写一个新文件,但是如果可能的话,一个小例子会很方便。我所熟悉的.append

+0

你可以使用正则表达式? – 2012-03-11 00:19:17

+0

不,我没有正则表达式的经验对不起 – bigl 2012-03-11 00:25:49

回答

3

可能更容易使用re

re_ips = r'Failed password for (?:root|invalid user\s?.*) from ((?:\d{1,3}\.){3}\d{1,3}) ' 

这将让你从相关线路的所有IP地址。这里有一个如何使用这个正则表达式打印复发13次以上的文件bad_ips.log的IP地址的例子:

from collections import defaultdict 
import re 

ip_freq = defaultdict(int) 
with open("auth", "r") as fh: 
    for match in re.finditer(r'Failed password for (?:root|invalid user\s?.*) from ((?:\d{1,3}\.){3}\d{1,3}) ', fh.read()): 
     ip_freq[match.group(1)] += 1 

with open("bad_ips.log", "w") as fh: 
    for ip, n in ip_freq.iteritems(): 
     if n>=13: 
      print >>fh, ip 

编辑:根据您的新的要求更新的正则表达式。

edit2:再次更新正则表达式以正确匹配日志文件中的invalid user xxxx

EDIT3:收拾例如

+0

我将如何显示结果? – bigl 2012-03-11 00:24:12

+0

刚刚添加了一个例子 – joe 2012-03-11 00:30:38

+0

这个工作很完美,非常感谢。在我平静地离开你之前,只是一个小小的插件。我还有几个ips需要检查,但是他们以“无效用户失败密码”开头。将它添加到代码中的意义何在? – bigl 2012-03-11 01:25:31

0

你可以做这样的事情:

import re 
f = open('auth', 'r') 
ip_list = re.findall(r'Failed password for root from (.*?)\s', f.read()) 
clean_list = [ip for ip in set(ip_list) if ip_list.count(ip) > 13] 

有你clean_list其中只包含了在auth重复超过13倍的IP。

+0

这很好,但是当我打印clean_list时它只显示一个IP地址。应该有其他几个地址。有任何想法吗? – bigl 2012-03-11 00:31:14

+0

看看你在'ip_list'和'set(ip_list)'中得到了什么。可能有一些我忽略了。我只是用你提供的样本日志行来测试它。另外,你确定你有多个IP重复13次以上? – 2012-03-11 00:44:13

+0

在ip_list我得到根和无效重复很多次。在设置(ip_list)我越来越设置(['根','无效'])是啊有四个或五个ips应该出现 – bigl 2012-03-11 00:50:20

0

看起来你可以从那里得到IP地址,只需通过split()返回的列表的第-4个元素。要计算某些地址的出现次数,您可以将它们添加到列表中,并使用它的方法或创建某种计数字典(也有类似的方便的类设计,但您可以使用常规字典)。

ip_count = {} 
for line in open("auth"): 
    if "Failed password for root from" in line: 
     ip = line.split()[-4] 
     if ip in ip_count: 
      ip_count[ip] += 1 
     else: 
      ip_count[ip] = 1 

然后你分析字典,也许写经常遇到的IP地址到一个文件:

out = open("frequent.ips", 'w') 
for ip in ip_count: 
    if ip_count[ip] > 13: 
     out.write("%s: %d attempts.\n" % (ip, ip_count[ip])) 
+0

除了结束之外,一切进展顺利))。我收到一个语法错误:在扫描字符串文字时出现EOL。括号对我来说似乎很好。两个关闭? – bigl 2012-03-11 00:38:55

+0

'ip_count'和输出文件中有什么? – 2012-03-11 00:53:41

+0

ip_count包含{'213.251.192.26':13,'218.241.173.35':15,'89 .249.209.92':13}输出文件中没有任何内容。我想这是因为我无法在底部完成写入功能 – bigl 2012-03-11 00:59:47

1

这应该做的伎俩:

import re 
with open('auth', 'r') as f: 
    ip_list = re.findall(r'Failed password for root from (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', f.read())) 
    thirteen_plus = [i for i in set(ip_list) if ip_list.count(i) >= 13] 
相关问题