web-dev-qa-db-fra.com

Analyse des fichiers journaux Apache

Je viens de commencer à apprendre Python et je voudrais lire un fichier journal Apache et mettre des parties de chaque ligne dans différentes listes.

ligne du fichier

172.16.0.3 - - [25/Sep/2002: 14: 04: 19 +0200] "GET/HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv: 1.1 ) Gecko/20020827 "

selon site Web Apache le format est

% h% l% u% t\"% r \"%> s% b\"% {Referer} i \"\"% {User-Agent} i \

Je peux ouvrir le fichier et le lire tel quel, mais je ne sais pas comment le lire dans ce format afin de pouvoir mettre chaque partie dans une liste.

32
ogward

Ceci est un travail pour expressions régulières .

Par exemple:

line = '172.16.0.3 - - [25/Sep/2002:14:04:19 +0200] "GET / HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827"'
regex = '([(\d\.)]+) - - \[(.*?)\] "(.*?)" (\d+) - "(.*?)" "(.*?)"'

import re
print re.match(regex, line).groups()

La sortie serait un Tuple avec 6 éléments d'information de la ligne (en particulier, les groupes entre parenthèses dans ce modèle):

('172.16.0.3', '25/Sep/2002:14:04:19 +0200', 'GET / HTTP/1.1', '401', '', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827')
38
David Robinson

Utilisez une expression régulière pour diviser une ligne en "jetons" distincts:

>>> row = """172.16.0.3 - - [25/Sep/2002:14:04:19 +0200] "GET / HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827" """
>>> import re
>>> map(''.join, re.findall(r'\"(.*?)\"|\[(.*?)\]|(\S+)', row))
['172.16.0.3', '-', '-', '25/Sep/2002:14:04:19 +0200', 'GET / HTTP/1.1', '401', '-', '', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827']

Une autre solution consiste à utiliser un outil dédié, par ex. http://pypi.python.org/pypi/pylogsparser/0.4

12
georg

J'ai créé une bibliothèque python qui fait exactement cela: Apache-log-parser .

>>> import Apache_log_parser
 >>> line_parser = Apache_log_parser.make_parser("%h <<%P>> %t %Dus \"%r\" %>s %b  \"%{Referer}i\" \"%{User-Agent}i\" %l %u")
>>> log_line_data = line_parser('127.0.0.1 <<6113>> [16/Aug/2013:15:45:34 +0000] 1966093us "GET / HTTP/1.1" 200 3478  "https://example.com/" "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.18)" - -')
>>> pprint(log_line_data)
{'pid': '6113',
 'remote_Host': '127.0.0.1',
 'remote_logname': '-',
 'remote_user': '',
 'request_first_line': 'GET / HTTP/1.1',
 'request_header_referer': 'https://example.com/',
 'request_header_user_agent': 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.18)',
 'response_bytes_clf': '3478',
 'status': '200',
 'time_received': '[16/Aug/2013:15:45:34 +0000]',
 'time_us': '1966093'}
10
Rory

RegEx semblait extrême et problématique compte tenu de la simplicité du format, j'ai donc écrit ce petit séparateur que d'autres peuvent également trouver utile:

def Apache2_logrow(s):
    ''' Fast split on Apache2 log lines

    http://httpd.Apache.org/docs/trunk/logs.html
    '''
    row = [ ]
    qe = qp = None # quote end character (qe) and quote parts (qp)
    for s in s.replace('\r','').replace('\n','').split(' '):
        if qp:
            qp.append(s)
        Elif '' == s: # blanks
            row.append('')
        Elif '"' == s[0]: # begin " quote "
            qp = [ s ]
            qe = '"'
        Elif '[' == s[0]: # begin [ quote ]
            qp = [ s ]
            qe = ']'
        else:
            row.append(s)

        l = len(s)
        if l and qe == s[-1]: # end quote
            if l == 1 or s[-2] != '\\': # don't end on escaped quotes
                row.append(' '.join(qp)[1:-1].replace('\\'+qe, qe))
                qp = qe = None
    return row
7
Neil C. Obremski

Ajoutez ceci dans httpd.conf pour convertir les journaux Apache en json.

LogFormat "{\"time\":\"%t\", \"remoteIP\" :\"%a\", \"Host\": \"%V\", \"request_id\": \"%L\", \"request\":\"%U\", \"query\" : \"%q\", \"method\":\"%m\", \"status\":\"%>s\", \"userAgent\":\"%{User-agent}i\", \"referer\":\"%{Referer}i\" }" json_log

CustomLog /var/log/Apache_access_log json_log
CustomLog "|/usr/bin/python -u apacheLogHandler.py" json_log

Vous voyez maintenant vos access_logs au format json. Utilisez le code ci-dessous python pour analyser les journaux json qui sont constamment mis à jour.

apacheLogHandler.py

import time
f = open('Apache_access_log.log', 'r')
for line in f: # read all lines already in the file
  print line.strip()

# keep waiting forever for more lines.
while True:
  line = f.readline() # just read more
  if line: # if you got something...
    print 'got data:', line.strip()
  time.sleep(1)
2
Preethi Lakku
import re


Host = r'^(?P<Host>.*?)'
SPACE = r'\s'
IDENTITY = r'\S+'
USER = r'\S+'
TIME = r'(?P<time>\[.*?\])'
REQUEST = r'\"(?P<request>.*?)\"'
STATUS = r'(?P<status>\d{3})'
SIZE = r'(?P<size>\S+)'

REGEX = Host+SPACE+IDENTITY+SPACE+USER+SPACE+TIME+SPACE+REQUEST+SPACE+STATUS+SPACE+SIZE+SPACE

def parser(log_line):
    match = re.search(REGEX,log_line)
    return ( (match.group('Host'),
            match.group('time'), 
                      match.group('request') , 
                      match.group('status') ,
                      match.group('size')
                     )
                   )


logLine = """180.76.15.30 - - [24/Mar/2017:19:37:57 +0000] "GET /shop/page/32/?count=15&orderby=title&add_to_wishlist=4846 HTTP/1.1" 404 10202 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"""
result = parser(logLine)
print(result)
0
Fuji Komalan