Toon posts:

[Bash] Script om log file te analyseren

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben een shell script aan het maken om de log file van mijn Postfix MTA te analyseren. Zodat ik o.a. een overicht kan maken van de gerejecte mails en van de spammails.

#!/usr/local/bin/bash
echo "| Datum | | Type | From | IP adres" > "Jun/18"
echo "\--------------------|--------|------|--------------------------------------/ " >> "Jun/18"

awk '{ if ($2 == 18 && $7 == "reject:" )
print "|", $2, $1, "at", $3, "|", substr($7,0,6), "|", $8, "|", $10, "|"}' /var/log/maillog >> "Jun/18"

Dit werkt op zich goed. Het probleem is dat de veldlengte van het FROM adres ($10) niet altijd dezelfde lengte heeft. Hierdoor komen de velden in de kolom ernaast (IP adres) niet netjes onder elkaar te staan, maar direct achter het FROM adres.

Hoe kan ik de kolom From een vaste lengte geven?

  • TRON
  • Registratie: September 2001
  • Laatst online: 17-02 12:21
Controleren hoe 'groot' FROM is en daarop je spaties aanpassen?

Leren door te strijden? Dat doe je op CTFSpel.nl. Vraag een gratis proefpakket aan t.w.v. EUR 50 (excl. BTW)


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 17-12-2025

curry684

left part of the evil twins

Professionele website nodig?


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 18-02 10:22

NetForce1

(inspiratie == 0) -> true

Met printf, een lengte van 15 wordt dan bijv. printf "%15s", $10. Wellicht moet je hier ff een aparte variabele voor aanmaken, kan eea nu ff niet testen.

.edit: die var moet je dan wel vullen met sprintf ipv printf (sprintf geeft geen output op het scherm)

[ Voor 29% gewijzigd door NetForce1 op 18-06-2004 17:03 ]

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • BTB
  • Registratie: Augustus 2000
  • Laatst online: 05-01 09:09

BTB

 

Ik zou dit gewoon niet in een shell-script doen maar gewoon in Perl. Veel makkelijker.

Bram Bouwens


  • arikkert
  • Registratie: Juli 2002
  • Laatst online: 17-02 12:23
bbouwens schreef op 18 juni 2004 @ 17:06:
Ik zou dit gewoon niet in een shell-script doen maar gewoon in Perl. Veel makkelijker.
kant en klaar pakket is te vinden op
http://jimsun.linxnet.com/postfix_contrib.html
alhoewel de topicstarter natuurlijk met een vraag over bash kwam.

Verwijderd

Als je het mij vraagt is dit geen bash maar AWK :) En awk is veel gemakkelijker voor simpele file-parsing dan perl, perl is overkill voor dit soort whitespace-delimited logs.

Verwijderd

Topicstarter
kant en klaar pakket is te vinden op
http://jimsun.linxnet.com/postfix_contrib.html
alhoewel de topicstarter natuurlijk met een vraag over bash kwam.
Er zijn inderdaad wel kant-en-klare pakketen voor, maar ik vind het leuk om zelf te maken :)

Zowel Perl als Bash ken ik niet zo goed. Dus waarmee ik het maak is niet echt van belang, omdat het in beide gevallen uitzoek werk wordt :)

Ik heb een Perl tutorial gevonden en ben daarmee begonnen. De moeilijkheid valt eigenlijk wel mee. Ben nu aan het proberen om met Perl de benodigde gegevens uit de Postfix log te halen, om het daarna in een MySQL database te plaatsen.

Verwijderd

Topicstarter
Verwijderd schreef op 18 juni 2004 @ 21:54:
Als je het mij vraagt is dit geen bash maar AWK :) En awk is veel gemakkelijker voor simpele file-parsing dan perl, perl is overkill voor dit soort whitespace-delimited logs.
Kan AWK niet worden aangeroepen vanuit een Perl script?

  • Aapzak
  • Registratie: November 2000
  • Laatst online: 08-01 15:23

Aapzak

Your genuine OS hopper

Perl is gebasseerd op AWK. Toen de bedenker van Perl dingen moest doen die in AWK en SED niet meer konden is hij Perl gaan ontwikkelen.

Ik denk persoonlijk niet dat jij met dit script al tegen de beperkingen van AWK aanloopt en waarschijnlijk is het gebruik van Perl dan niet nodig.

Aan de andere kant, Perl is leuk en mooi. Je kan er echt heel veel in, maar je kan ook vrij gemakkelijk iets simpels maken, de leercurve is niet zo stijl.

Ik heb zelf log-analysers geschreven onder Perl (mijn eerste kennismaking met Perl en zeker geen topwerk dus), en dat vond ik echt leuk om te doen, wel een aanrader dus.

is de field separator herkenbaar? is het een tab-karakter of spaties of een ander karakter dat in de tekst niet voorkomt? Dat kan je je lijn daar op splitsen en alle delen in een array of losse variabelen opvangen (tenminste, in Perl gaat dat zo, AWK ken ik niet)

PSN ID: Aapzak


Verwijderd

Topicstarter
is de field separator herkenbaar? is het een tab-karakter of spaties of een ander karakter dat in de tekst niet voorkomt? Dat kan je je lijn daar op splitsen en alle delen in een array of losse variabelen opvangen (tenminste, in Perl gaat dat zo, AWK ken ik niet)
Een regel uit de log kan er zo uit zien
code:
1
2
3
4
Jun 19 11:26:02 epauli postfix/smtpd[45242]: NOQUEUE: reject: 
RCPT from uudestaan.iki.fi[212.16.100.1]: 450 <wqlqhitrw@epauli.dyndns.org>: 
Recipient address rejected: User unknown in local recipient table; from=<> 
to=<wqlqhitrw@epauli.dyndns.org> proto=ESMTP helo=<uudestaan.iki.fi>


De velden zijn dus gescheiden met een spatie, maar spaties komen ook op andere plaatsen voor, zoals bij : "Recipient address rejected".

  • Aapzak
  • Registratie: November 2000
  • Laatst online: 08-01 15:23

Aapzak

Your genuine OS hopper

Verwijderd schreef op 19 juni 2004 @ 11:58:
[...]


Een regel uit de log kan er zo uit zien
code:
1
2
3
4
Jun 19 11:26:02 epauli postfix/smtpd[45242]: NOQUEUE: reject: 
RCPT from uudestaan.iki.fi[212.16.100.1]: 450 <wqlqhitrw@epauli.dyndns.org>: 
Recipient address rejected: User unknown in local recipient table; from=<> 
to=<wqlqhitrw@epauli.dyndns.org> proto=ESMTP helo=<uudestaan.iki.fi>


De velden zijn dus gescheiden met een spatie, maar spaties komen ook op andere plaatsen voor, zoals bij : "Recipient address rejected".
Hoe zit dat met die dubbele punten gevolgd door spaties, als ik die in deze regel gebruik als separator krijg ik deze losse onderdelen:
code:
1
2
3
4
5
6
7
8
Jun 19 11:26:02 epauli postfix/smtpd[45242]
NOQUEUE
reject
RCPT from uudestaan.iki.fi[212.16.100.1]
450 <wqlqhitrw@epauli.dyndns.org>
Recipient address rejected
User unknown in local recipient table; from=<>
to=<wqlqhitrw@epauli.dyndns.org> proto=ESMTP helo=<uudestaan.iki.fi>


Dus dat lijkt me de separator.

[ Voor 5% gewijzigd door Aapzak op 19-06-2004 12:58 . Reden: mijn resultaten in code vorm gezet ]

PSN ID: Aapzak


Verwijderd

Topicstarter
Aapzak schreef op 19 juni 2004 @ 12:57:
[...]
Hoe zit dat met die dubbele punten gevolgd door spaties, als ik die in deze regel gebruik als separator krijg ik deze losse onderdelen:
Dus dat lijkt me de separator.
Daar zat ik later ook naar te kijken, het is inderdaad de dubbele punt met daarachter een spatie. Ik ga uitzoeken hoe arrays en split werken.

Verwijderd

Topicstarter
Verwijderd schreef op 19 juni 2004 @ 16:32:
[...]
Daar zat ik later ook naar te kijken, het is inderdaad de dubbele punt met daarachter een spatie. Ik ga uitzoeken hoe arrays en split werken.
Ik ben inmiddels een aardig eind verder.
Met een Perl script lees ik de Postfix logfile, bewerk deze gegevens en voeg ze daarna toe aan een tabel in een MySQL database.

Via een cronjob wil ik ieder uur het Perl script uitvoeren om de statistieken te updaten.
Daarbij wordt dan de log file gelezen waarvan al gegevens in de database staan. Als bij het uitvoeren van de INSERT query niet wordt gecontrolleerd of er al een record met dezelfde gegevens aanwezig is, komen er dingen dubbel in de database te staan. Dit is vrij simpel op te lossen door voor de INSERT query een SELECT query uit te voeren die er zo uit kan zien:

SELECT `id`FROM `reject` WHERE month='Jul' AND day='1' AND hour='10', etc...
Als er een resultaat wordt gevonden bestaat het record al, anders toevoegen.

Hierbij heb ik een probleem met het tellen van het aantal opgehaalde records. PHP heeft de functie mysql_num_rows (of mysql_numrows). Ik was op zoek naar een soortgelijke functie in Perl. Daarbij kwam ik op {NUM_OF_FIELDS}
code:
1
2
3
4
my $sth = $dbh->prepare("QUERY");
$sth->execute();
my $nr_of_fields = $sth->{NUM_OF_FIELDS};
print $nr_of_fields;

Ik dacht dat dit de aantal records zou teruggeven, maar het laat het aantal velden zien dat achter SELECT is geplaatst.
Dus bij SELECT id,type,error wordt er 3 gegeven en bij SELECT id, type 2.

Ik heb NUM_OF_FIELDS al gewijzigd in NUM_OF_ROWS, MYSQL_NUM_ROWS of ROWS, maar dan geeft Perl deze melding: unrecognised attribute at analyse2.pl line 62.

Met Google kom ik niet verder dan NUM_OF_FIELDS. Weet iemand welke Perl functie het aantal records dat door een SELECT query wordt opgehaald laat zien?

  • arikkert
  • Registratie: Juli 2002
  • Laatst online: 17-02 12:23
uit perldoc DBI

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
            "rows"

             $rv = $sth->rows;

           Returns the number of rows affected by the last row affecting com-
           mand, or -1 if the number of rows is not known or not available.

           Generally, you can only rely on a row count after a non-"SELECT"
           "execute" (for some specific operations like "UPDATE" and
           "DELETE"), or after fetching all the rows of a "SELECT" statement.

           For "SELECT" statements, it is generally not possible to know how
           many rows will be returned except by fetching them all.  Some driv-
           ers will return the number of rows the application has fetched so
           far, but others may return -1 until all rows have been fetched.  So
           use of the "rows" method or "$DBI::rows" with "SELECT" statements
           is not recommended.

           One alternative method to get a row count for a "SELECT" is to exe-
           cute a "SELECT COUNT(*) FROM ..." SQL statement with the same "..."
           as your query and then fetch the row count from that.


but remember, its not the result that counts ... its walking the path that leads to it :Y)
Pagina: 1