2012-03-11 64 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] 
相關問題