[gelöst] Datumsformat ändern

freddy4711

Neuer User
Mitglied seit
7 Jul 2007
Beiträge
155
Punkte für Reaktionen
0
Punkte
0
Hi...

ich bin gerade dabei, ein Shell-Script zur Auswertung der Logfiles zu schreiben. Habe das Script auch auf einem Ubuntu-Rechner mit einer Bash-Shell getestet. Da hat es einwandfrei funktioniert.

Nun habe ich es auf der Box in die debug.cfg eingetragen. Nach 'nem Reboot war im /var/tmp/ mein Skript zu finden und ließ sich auch ausführen.

Nun aber mein Problem:
Ich möchte das Datum des Logfiles Zeile für Zeile in einen UNIX-Timestamp umwandeln, um damit besser zu Arbeiten.

Ich habe eine while-Schleife, welche das Logfile zeilenweise bis zum Ende durchläuft.

Zuerst separiere ich das das Datum:
Code:
dat=$(echo $line|cut -d" " -f1-3)
Anschließend wandle ich das Datum mittels der DATE-Funktion in den UNIX-Timestamp um:
Code:
sec=$(date -d"$dat" +%s )
und gebe das Ganze wieder auf die Konsole aus...
Code:
echo "$line" |sed s/^"$dat"/$sec/

Leider funktioniert die Umrechnung ded Datums mit der DATE-Funktion auf der Box nicht.

Ich bekomme in jeder Zeile folgende Fehlermeldung:
Code:
date: invalid date 'Dec 16 14:XX:XX'

Kann mir jemand helfen?

Gruß Andreas
 
"date --help" zeigt die Datumsformate an, die das date der Busybox unterstützt.
Das normale date-Kommando unterstützt anscheinend einiges mehr, dafür muß man suchen, bis man die Dokumentation dafür findet.

Da die Busybox auf kleinen Platzverbrauch ausgelegt ist, kann ich nachvollziehen, daß nicht alle Formate unterstützt werden.
 
Das Datumsformat der Busybox DATE-Funktion ist sehr eingeschränkt...

ist es irgendwie möglich, die DATE-Funktion der GNU-Coreutils zu implementieren?

Gruß Andreas
 
Leider kenne ich mich damit noch nicht so aus.

Aber was muss ich tun, um die Date-Funktion aus GNU-Coreutils in die Freetz-Firmware einzubauen.

Gruß Andreas
 
Schonmal danach gegoogelt?
Ich bin auf sowas gestoßen:
Code:
awk 'BEGIN { print strftime("%c", 1141421607); exit }'
MfG Oliver

edit: Ups. Wenn man keine Ahnung hat einfach mal Fresse halt. :mrgreen:
 
Zuletzt bearbeitet:
Das ist die umgekehrte Richtung, Timestamp nach lesbarem Datum.

In der C-Library gibt es die Funktion strptime, die einen String einliest und daraus ein "struct tm" erstellt. Aus diesem kann man dann wiederum mit mktime ein Timestamp erstellen.

Evtl. sind diese Funktionen auch in awk vorhanden.

Ansonsten gibt es im freetz Wiki eine Anleitung, um eigene Pakete zu erstellen. Für die meisten Pakete (die Gnu Utilities gehören vermutlich dazu) ist das Cross-Compilieren relativ einfach.
 
Habe grad einmal nachgeschaut, aber die Funktion strptime() ist nicht in awk verfügbar.

Ich werde noch ein wenig im Netz suchen. Falls ich nichts mehr anderes finde, werde ich mich ans Einbauen der GNU-Coreutils machen.

Spätestens dann werde ich mich wieder melden :rolleyes:

Gruß Andreas
 
Hi...

hab nochmal ein bisschen rumgebastelt - und habe nun folgende Lösung gefunden. Ist wahrscheinlich nicht die Beste, aber funktionieren tut sie...

Mir gefällt nur nicht, wie ich die Monatsangaben umrechne...aber leider gibt es für die Freetz-Shell (ash) keine Möglichkeit, Arrays einzubauen? Oder bin ich da falsch informiert? Denn gefunden habe ich im Netz nix...

Hier mein Script:
Code:
#!/bin/sh

# date2timestamp.sh - Datumsumwandlung für die Busybox-Date-Funktion

cat - | while read line
do
  datum=$(echo $line|cut -d" " -f1-3)
  monthName=$(echo $line|cut -d" " -f1)
  day=$(echo $line|cut -d" " -f2)  
  hour=$(echo $line|cut -d" " -f3|cut -d":" -f1) 
  min=$(echo $line|cut -d" " -f3|cut -d":" -f2) 
  sec=$(echo $line|cut -d" " -f3|cut -d":" -f3)

  case $monthName in
    Jan ) month="1";;
    Feb ) month="2";;
    Mar ) month="3";;
    Apr ) month="4";;
    May ) month="5";;  
    Jun ) month="6";;  
    Jul ) month="7";;
    Aug ) month="8";;
    Sep ) month="9";;
    Oct ) month="10";;
    Nov ) month="11";;
    Dec ) month="12";;
  esac
    
  timestamp=`date -d"$month$day$hour$min.$sec"`
  echo "$line" |sed s/^"$dat"/$timestamp/
done

Gruß Andreas
 
Zunächst einmal könntest Du die Aufteilung machen, ohne so viele Unterprozesse zu starten. Jede Konstruktion mit $() startet eine sub-Shell, mit in Deinem Beispiel jeweils 2-3 Prozessen, und das etliche Male für jede einzelne Zeile.
Das geht effizienter mit:
Code:
while IFS=' :' read monthName day hour min sec line; do
Auch das "cat -" ist unnötig.

Das case kannst Du evtl. umgehen, indem Du eine Zuweisung an an Variablen machst, ungefähr so:
Code:
mon_Jan=1
mon_Feb=2
...
mon_Dez=12
eval mon=\$mon_$monthName
Die Zuweisung der 12 Werte kann dabei auch vor der Schleife stehen.
Ob es effizienter ist als das case, weiß ich auch nicht.

Andererseits, wenn Dir Effizienz wichtig ist (je nach Größe der Datei), dann wären einige Zeilen in C sicher besser.
 
Ich habe die Aufgabe leider nicht ganz verstanden. Was ist der Ist-Zustand und was ist Soll-Zustand vom Datumsformat? Was soll gemacht werden? Ein Datum in einer Datei verändert werden?
Ich würde aus meinem Bauchgefühl sed dafür nehmen. Busybox-sed ist zwar auch etwas eigenartig, aber damit geht schon einiges. Zwar bekommt man damit keinen sed-Einzeiler, aber Konstrukte wie in etwa:
Code:
sed -e "s/Jan/01/g;s/Feb/02/g;"
können schon weiter helfen. Man kann mit sed auch gut die Reihenfolge ändern, z.B. "2. Jan" anstatt "Jan 2" überall schreiben. Und mit busybox-sed geht sowas definitiv.

Für grep/sed-Manipulationen (busybox grep geht übrigens auch, und sogar mit -e!) sollte man allerdings etwas besser Kontext kennen, sprich den Inhalt der Logdatei, um die Suche besser einzugrenzen. Z.B. wenn das Datum am Anfang jeder Zeile steht, erleichtert es die Suche enorm.

Deswegen poste hier am besten 2-3 Zeilen als Beispiel und was du daraus machen willst.

MfG
 
Hi...

vom Format her sieht mein Logfile ja so aus:
Code:
Dec 18 00:00:26 Speedport_W_701V_33-04-56 ...
Dec 18 00:00:26 Speedport_W_701V_33-04-56 ...
Dec 18 00:09:55 Speedport_W_701V_33-04-56 ...
Dec 18 00:10:01 Speedport_W_701V_33-04-56 ...

Nun möchte ich für eine Logfile-Analyse das Datum in einen UNIX-Timestamp umwandeln, da dieser einfacher zu Handhaben ist...
Code:
1229555426 Speedport_W_701V_33-04-56 ...
1229555426 Speedport_W_701V_33-04-56 ...
1229555401 Speedport_W_701V_33-04-56 ...
1229555395 Speedport_W_701V_33-04-56 ...

Mein Script, welches ich mit Hilfe der Tips von RalfFriedl angepasst habe, sieht jetzt so aus:
Code:
#!/bin/sh
#date2timestamp.sh - Datumsumwandlung fuer die Busybox-Date-Funktion

month_Jan="1"
month_Feb="2"
month_Mar="3"
month_Apr="4"
month_May="5"
month_Jun="6"
month_Jul="7"
month_Aug="8"
month_Sep="9"
month_Oct="10"
month_Nov="11"
month_Dec="12"

while IFS=' :' read monthName day hour min sec line;
do
  eval month=\$month_$monthName

  timestamp=`date -d"$month$day$hour$min.$sec" +%s`
  echo "$line" |sed s/^"$datum"/$timestamp/
done

Das Script rufe ich wie folgt auf:
Code:
logread | grep <irgendetwas> | /var/tmp/date2timetamp.sh

Es funktioniert auch soweit. Bis auf eine kleine Sache; beim Ersetzen des Alten Datums durch den generierten Timestamp wird das Leerzeichen zum Logtext entfernt. Und ich habe es bis jetzt nicht hinbekommen, dieses wieder einzufügen.
Code:
1229555395Speedport_W_701V_33-04-56 ...

Gruß Andreas
 
Bist Du sicher, daß Dein Skript genau so aussieht?
Code:
  echo "$line" |sed s/^"$datum"/$timestamp/

Speziell diese Zeile ist seltsam, weil $datum vorher im Skript nicht definiert wird.
Ok, mir ist klar, was passiert. $datum ist leer, also wird /^/$timestamp/ ersetzt, also $timestamp am Anfang der Zeile eingefügt. Was Du nicht beachtet hast, ist, daß durch das read der Wert von line nicht die komplette Zeile ist, sonder nur die Meldung selbst, ohne das Datum.

Ersetze diese Zeile durch
Code:
  echo "$timestamp $line"
dann sollte es gehen.
 
Hi...

alles klar. So klappt es...

Habe mich auch schon gefragt, warum das mit der Variable $datum noch funktioniert...


Nun habe ich noch ne Frage unabhängig von diesem Problem...

Wie kann ich den Hostnamen der Box ändern?

IST:
Code:
Speedport_W_701V_33-04-56
SOLL (z.B.):
Code:
router

Dankeschön...

Gruß Andreas
 
Code:
echo "$timestamp $line" | sed 's/Speedport_W_701V_33-04-56/router/'
 
Hi...

nein...ich meine wirklich den Hostnamen der Box ändern.

Gruß Andreas
 
Code:
hostname router
Das Leben kann sooo einfach sein :cool:
 
ok...manchmal sieht man vor lauter Bäumen den Wald nicht mehr...:rolleyes:

Danke...

Gruß Andreas
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.