Roger: logfile parsen

moin!

ich würde gern ein logfile mittels php auswerten, welches mein router an einen syslog-server gesendet hat.
die einträge sehen wie folgt aus:

Jan 27 11:19:10 192.168.1.1 Vigor: Local User: 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web

damit ich das log auswerten kann, muss ich zunächst alle werte in ein array bekommen. leider gibt es kein trennzeichen zwischen den einzelnen spalten ("Vigor: Local User:" schießt da ein wenig quer).

nun ist die frage die, ob ich einfach alles stur per explode(" ", $str) in einen array bringe und dann im nachheinein die felder noch zusammenstricke (zb. datum), oder ob es (zumindest für den server) einfacher / resourcenschonender ist, wenn ich mit regexp arbeite? wobei bei letzterem mir nat. klar das wissen fehlt. aber ich bin nat. aufgeschlossen für alles :)

gruß.
roger.

--
meine freundin sagt, ich wäre neugierig.
so steht's zumindest in ihrem tagebuch.
  1. Hallo,

    leider gibt es kein trennzeichen zwischen den einzelnen spalten

    Und woran erkennt dann der Mensch, wo eine Spalte[1] anfängt und aufhört?

    [1] Definiere doch bitte mal den Begriff 'Spalte'.

    LG
    Chris

    1. moin!

      [1] Definiere doch bitte mal den Begriff 'Spalte'.

      ein mehrdimensionaler array besteht doch aus zeilen und spalten. nich? pro spalte steht eben der dazugehörige wert.

      in meinem fall müsste der kopf der spalten so heißen:
      timestamp | router-ip | router-message | interne ip:port | externe ip:port | portbeschreibung

      gruß.
      roger.

      --
      meine freundin sagt, ich wäre neugierig.
      so steht's zumindest in ihrem tagebuch.
      1. Hallo,

        [1] Definiere doch bitte mal den Begriff 'Spalte'.

        ein mehrdimensionaler array besteht doch aus zeilen und spalten. nich? pro spalte steht eben der dazugehörige wert.

        in meinem fall müsste der kopf der spalten so heißen:
        timestamp | router-ip | router-message | interne ip:port | externe ip:port | portbeschreibung

        Vergiss doch bitte mal einen Moment lang deine IT-Kenntnisse und formuliere einfach, woran _DU_ persönlich eine Spalte erkennst in dem Logbuch, dargestellt mit den üblichen Programmen (Texteditor) oder sogar ausgedruckt auf Papier...

        Woher kommt das Log? Ist das ein übliches Apache-Log?

        LG
        Chris

        1. moin!

          Vergiss doch bitte mal einen Moment lang deine IT-Kenntnisse und formuliere einfach, woran _DU_ persönlich eine Spalte erkennst in dem Logbuch, dargestellt mit den üblichen Programmen (Texteditor) oder sogar ausgedruckt auf Papier...

          na anhand der inhalte, die ich versucht habe in meinem letzten posting (spaltenüberschrift) zu beschreiben.

          Woher kommt das Log? Ist das ein übliches Apache-Log?

          nein:

          ich würde gern ein logfile mittels php auswerten, welches mein router an einen syslog-server gesendet hat.

          gruß.
          roger.

          --
          meine freundin sagt, ich wäre neugierig.
          so steht's zumindest in ihrem tagebuch.
      2. Hallo Roger,

        timestamp | router-ip | router-message | interne ip:port | externe ip:port | portbeschreibung

        - %{timestamp} hat eine immergleichbleibende Länge
         - %{router-ip} trennt sich von %{router-message} durch ein einzelnes Leerzeichen
         - %{interne ip:port} trennt sich durch ein Leerzeichen von %{router-message} ab
         - %{interne ip:port} trennt sich von %{externe ip:port} durch String ' -> ' ab
         - %{externe ip:port} trennt sich von %{portbeschreibung} durch ein Leerzeichen ab

        nach dieser aufgezeigten Logik kommst Du mit (bspw.) substr() und explode() an alle Teile heran

        Gruß aus Berlin!
        eddi

        --
        Wer Rechtschreibfehler findet, darf sie behalten.
        1. moin!

          nach dieser aufgezeigten Logik kommst Du mit (bspw.) substr() und explode() an alle Teile heran

          ja, danke!
          allerdings gibt's da noch ein klitzekleines problemchen:
          router-message ändert sich. moment! ha, es fängt zumindest immer mit "vigor:" an. ok, und auf das kann man ja auch prüfen.

          nun ja, der grundstein ist gelegt ;)

          gruß.
          roger.

          --
          meine freundin sagt, ich wäre neugierig.
          so steht's zumindest in ihrem tagebuch.
          1. Re:

            nach dieser aufgezeigten Logik kommst Du mit (bspw.) substr() und explode() an alle Teile heran

            ja, danke!
            allerdings gibt's da noch ein klitzekleines problemchen:
            router-message ändert sich. moment! ha, es fängt zumindest immer mit "vigor:" an. ok, und auf das kann man ja auch prüfen.

            denksde :þ
            Nach skizziertem Schema würede %{router-message} per Ausschluß ermittelt werden.

            Gruß aus Berlin!
            eddi

            --
            Wer Rechtschreibfehler findet, darf sie behalten.
            1. moin!

              denksde :þ
              Nach skizziertem Schema würede %{router-message} per Ausschluß ermittelt werden.

              shit. klang so einfach...

              • %{router-ip} trennt sich von %{router-message} durch ein einzelnes Leerzeichen
              • %{interne ip:port} trennt sich durch ein Leerzeichen von %{router-message} ab

              um router-message auszuschließen, müsste man hier wohl mittels regexp die positionen der beiden ips (router, intern) ausfindig machen. korrekt?

              gruß.
              roger.

              --
              meine freundin sagt, ich wäre neugierig.
              so steht's zumindest in ihrem tagebuch.
              1. Hallo Roger,

                timestamp | router-ip | router-message | interne ip:port | externe ip:port | portbeschreibung

                • %{timestamp} hat eine immergleichbleibende Länge
                • %{router-ip} trennt sich von %{router-message} durch ein einzelnes Leerzeichen
                • %{interne ip:port} trennt sich durch ein Leerzeichen von %{router-message} ab
                • %{interne ip:port} trennt sich von %{externe ip:port} durch String ' -> ' ab
                • %{externe ip:port} trennt sich von %{portbeschreibung} durch ein Leerzeichen ab
                  
                $a=file('log.datei');  
                $c=count($a);  
                  
                for($i=0;$i<$c;$i++){  
                   $b[$i]['time']=substr($a[$i],0,15);  
                  
                   $v=substr($a[$i],16);  
                   list($b[$i]['r-ip'],$v)=explode(' ',$v,2);  
                   $v=explode(' -> ',$v);  
                   $b[$i]['msg']=substr($v[0],0,strrpos($v[0],' ')+1);  
                   $b[$i]['i-ip']=substr($v[0],strrpos($v[0],' '));  
                   list($b[$i]['e-ip'],$b[$i]['po-b'])=explode(' ',$v[1]);  
                }  
                
                

                so, wie ich es geschrieben hatte...
                Selber denken hätte Dich jetzt weiter gebracht!

                Gruß aus Berlin!
                eddi

                --
                Wer Rechtschreibfehler findet, darf sie behalten.
                1. moin!

                  danke. hatte ich doch aber schon. sry.
                  ich hatte es nur ein wenig anders gemacht. und zwar habe ich beim datei-einlesen gleich auf bestimmte werte überprüft um den speicher nicht zu belasten. deswegen hab ich mit fgetcsv() gearbeitet. oder ist das falsch?

                  gruß.
                  roger.

                  --
                  meine freundin sagt, ich wäre neugierig.
                  so steht's zumindest in ihrem tagebuch.
  2. Hi,

    die einträge sehen wie folgt aus:

    Jan 27 11:19:10 192.168.1.1 Vigor: Local User: 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web

    wirklich? Apache-Logs z.B. lassen sich eindeutig anhand der Leerzeichen trennen, wenn man nur die in "" bzw. [] eingeschlssenen Strings zusammen läßt.

    freundliche Grüße
    Ingo

    1. Hallo,

      wirklich? Apache-Logs z.B. lassen sich eindeutig anhand der Leerzeichen trennen, wenn man nur die in "" bzw. [] eingeschlssenen Strings zusammen läßt.

      Nicht so ganz...

      Denn die Aufruf-Methoden (GET, POST, HEAD, ...) hätten z.B. auch eine eigene Spalte verdient. Und Der Text im Client/Accept-Header ist auch recht variabel.

      Allerdings kann man sich das Format "vernünftig" einstellen, wenn man auf die Konfiguration des Servers Zugriff hat. Echtes CSV wäre eine Lösung, wenn auch nicht die Beste, da das dann nicht mehr mit jedem Editor lesbar wäre.

      Lieber wäre mir für das ungepackte Log-Format ein festes Satzformat. Dann könnte man in den Logs auch extrem schnell navigieren. Leider kenne ich beim Apache keine Konfiguration, die feste Spaltenbreiten ermöglicht. Wäre beim Accept-Header auch schon wieder enorme Platzverschwendung *g*

      LG
      Chris

      1. Hi,

        wirklich? Apache-Logs z.B. lassen sich eindeutig anhand der Leerzeichen trennen, wenn man nur die in "" bzw. [] eingeschlssenen Strings zusammen läßt.

        Nicht so ganz...

        Denn die Aufruf-Methoden (GET, POST, HEAD, ...) hätten z.B. auch eine eigene Spalte verdient.

        können sie doch bekommen: suche nach dem ersten in "" gesetzten String und extrahiere hieraus die Zeichen bis zum ersten Space.

        Und Der Text im Client/Accept-Header ist auch recht variabel.

        Du meinst z.B. HTTP/1.1? Der steht in meinen Standard-Logfiles im besagten String nach dem zweiten Leerzeichen; leicht herauszufiltern.

        freundliche Grüße
        Ingo

        1. Hallo,

          Denn die Aufruf-Methoden (GET, POST, HEAD, ...) hätten z.B. auch eine eigene Spalte verdient.

          können sie doch bekommen: suche nach dem ersten in "" gesetzten String und extrahiere hieraus die Zeichen bis zum ersten Space.

          Und Der Text im Client/Accept-Header ist auch recht variabel.
          Du meinst z.B. HTTP/1.1? Der steht in meinen Standard-Logfiles im besagten String nach dem zweiten Leerzeichen; leicht herauszufiltern.

          Mit Client ist mutmaßlich der Header "User-Agent" gemeint und did Header Accept(-*) sind in der Tat sehr diffiziel zu parsen. Aber daran wird deutlich, wenn man eben die Funktionalität von mod_log_config ausschöpft, statt defaults (worauf Deine Anmerkungen ja anwendbar sein mögen) zu verwenden, das hier, wie bereit von Dir angemerkt wurde, überaus sinnvoll ist mit "sonderzeichen" à la []"'# zu arbeiten.

          Nur im eigentlichen geht es nicht um einen log stream Apaches!

          Gruß aus Berlin!
          eddi

          --
          Wer Rechtschreibfehler findet, darf sie behalten.
    2. moin!

      Jan 27 11:19:10 192.168.1.1 Vigor: Local User: 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web
      wirklich? Apache-Logs z.B. lassen sich eindeutig anhand der Leerzeichen trennen

      wie auch immer. aber o.g. ist kein apache log, sondern wie in meinem allerersten satz beschrieben ein log meines routers, welches an eine linux-maschine mit installiertem syslogd gesendet wird. und darauf hat man leider keinerlei einfluss.

      gruß.
      roger.

      --
      meine freundin sagt, ich wäre neugierig.
      so steht's zumindest in ihrem tagebuch.
  3. Nabend,

    moin!

    ich würde gern ein logfile mittels php auswerten, welches mein router an einen syslog-server gesendet hat.
    die einträge sehen wie folgt aus:

    Jan 27 11:19:10 192.168.1.1 Vigor: Local User: 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web

    damit ich das log auswerten kann, muss ich zunächst alle werte in ein array bekommen. leider gibt es kein trennzeichen zwischen den einzelnen spalten ("Vigor: Local User:" schießt da ein wenig quer).

    Dann sieht ein Logfile-Eintrag aber eher so aus:
    Jan 27 11:19:10 192.168.1.1 "Vigor: Local User:" 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web

    Zerleg den String doch erstmal an den "Gänsefüßchen":

    $log_entry = 'Jan 27 11:19:10 192.168.1.1 "Vigor: Local User:" 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web';

    $bla = explode('"', $log_entry);

    Jetzt hast du drei Teile, von denen du den mittleren behältst, und die anderen beiden weiter zerlegen kannst:

    $blo = explode(' ', $bla[0]);
    $bla = $bla[1];
    $bli = explode(' ', $bla[2]);

    Das sollten jetzt drei Arrays sein, die folgende Inhalte haben:

    $blo:
    [0] => 'Jan'
    [1] => '27'
    [2] => '11:19:10'
    [3] => '192.168.1.1'

    $bla:
    [0] => 'Vigor: Local User:'

    $bli:
    [0] => '192.168.1.64:1562'
    [1] => '->'
    [2] => '216.239.59.104:80'
    [3] => '(TCP)Web'

    Die kannst du jetzt "zusammenstricken" ... ;-)

    MffG
    EisFuX

    --
    ... Suchmaschinen-Blog ...
    1. moin!

      Jan 27 11:19:10 192.168.1.1 Vigor: Local User: 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web
      ("Vigor: Local User:" schießt da ein wenig quer).

      Dann sieht ein Logfile-Eintrag aber eher so aus:
      Jan 27 11:19:10 192.168.1.1 "Vigor: Local User:" 192.168.1.64:1562 -> 216.239.59.104:80 (TCP)Web

      nein, weil es gibt keine gänsefüßchen. ich hab die nur zur verdeutlichung gesetzt. ganz oben steht ein copy&paste aus dem logfile und da sind keine dabei.

      aber danke für deine mühe. war sehr umfangreich.

      gruß.
      roger.

      --
      meine freundin sagt, ich wäre neugierig.
      so steht's zumindest in ihrem tagebuch.