Re: Bash Einzeiler Zeit+Datum letzter Eintrag dmesg
Hallo,
Am Mon, 15 Aug 2011, Rico Koerner schrieb:
>Am 15.08.2011 08:39, schrieb David Haller:
>> Am Sun, 14 Aug 2011, Rico Koerner schrieb:
>>> David hat mich durch den Hinweis auf syslog bei der Fehlersuche jetzt
>>> noch auf einen anderen Lösungsweg gebracht. Da die Zeile aus dmesg auch
>>> in einer Zeile im Syslog auftaucht, braucht man doch gar nicht anfangen
>>> zu rechnen sondern einfach nur die passende Zeile aus dem syslog
>>> ziehen.
>>
>> Haaalt! Konkretes Beispiel: bei mir schreibt syslog-ng z.B. firewall
>> und /dev/sr0 betreffende Einträge in jew. eigene Logs (die würden mir
>> sonst das eigentliche nur zumüllen). Ergo müßte ich man in mehreren
>> Dateien rumgreppen ... Der letzte Eintrag in dmesg findet sich bei mir
>> grad nur(!) in /v/l/firewall.
>
>Ja, jeder Ansatz hat seine eigenen Vor- und Nachteile.
>Auch die Vorgabe "ohne root" war mir nicht bewußt. Wem die Gruppe adm
>noch zu großzügig ist, kann es ja auch mit ACLs auf syslog versuchen.
>Wenn die Logs abweichend sind, scheitert mein Ansatz natürlich auch,
>u.U. müssten dann mehrere Logs durchsucht werden.
>Dafür ist das Ergebnis genauer, weil die Abweichung zwischen den Zählern
>nicht verfälschen.
>
>> dmesg ist also schon der richtige Ansatz.
>
>Das hab ich ja nicht verworfen.
>
>>> Dort steht die Zeit ja schon am Anfang der Zeile. Somit wird immer die
>>> korrekte Zeit ausgegeben.
>
>Nein, eben nicht. Die Abweichung wurde ja nun schon mehrfach
>festgestellt. Nur deshalb hab ich den Weg verfolgt.
Wie gesagt, ich denke das ist ein Sonderfall. Leider hat Frank keine
"Rohdaten" (uptime, timestamp in dmesg/syslog) mit denen dann
weitergerechnet wird geliefert.
[..]
>> Und die andere Variante, die ebenfalls /proc/uptime ausliest dürfte
>> noch lahmer sein.
>
>Lassen wir mal die Vermutungen beiseite und führen das aus.
>Mein Rechner ist allerdings insgesamt nicht so schnell,
Och, meiner auch nicht, war zum Kaufzeitpunkt vor ~1.5 Jahren schon
eine der langsamsten CPUs (Athlon II X2 250 (2x3.0 GHz)). Mir war
Single-Core Leistung eben wichtiger als 4 Kerne[0] ;)
>Die Ausgangsvariante:
>~# time { for i in {1..1000}; do let lastentry=$(dmesg|tail -n 1|cut -f1
>-d"."|cut -c2-|cut -f2 -d" "); let boot=$(cut -f1 -d. /proc/uptime); let
>lastdate=$boot-$lastentry; date -d "$lastdate seconds ago"; done >
>/dev/null; }
>
>real 0m17.204s
>user 0m5.704s
>sys 0m16.753s
>
>AWK:
>~# time { for i in {1..1000}; do date -d "$(dmesg | gawk -F'[][ ]+'
>'BEGIN{getline<"/proc/uptime";u=$1;} END{printf("%i\n",u-$2);}') seconds
>ago"; done > /dev/null; }
>
>real 0m13.924s
>user 0m5.468s
>sys 0m9.261s
*hehe*
>Syslog:
>~# time { for i in {1..1000}; do LASTENTRY=`dmesg | tail -n1`;
>LASTTIME=${LASTENTRY%%]*}; grep ${LASTTIME#[} /var/log/syslog | cut
>-c-15; done > /dev/null; }
>
>real 0m15.713s
>user 0m5.204s
>sys 0m11.057s
Wobei man hier ergänzen sollte: 'cut -c' oder andere zeichenabhängiger
Kram sind immer "fragil". Musterbasierte wie cut -fN -dX, die awk-
oder sed-Variante sind robuster.
>Bash only:
>~# time { for i in {1..1000}; do LASTENTRY=`dmesg | tail -n1`;
>LASTTIME=${LASTENTRY%%.*}; BOOT=`cat /proc/uptime`; date -d
>"$((${BOOT%%.*} - ${LASTTIME#[})) seconds ago"; done > /dev/null; }
>
>real 0m15.433s
>user 0m4.112s
>sys 0m11.569s
>
>Ja, awk ist hier am schnellsten.
>Erstaunlicherweise ist grep+cut nicht wesentlich schlechter als
>cat+date. Suchen wir doch mal den Zeitfresser.
Wie gesagt: Prozesse starten ist "teuer". Das schlägt hier wohl durch.
>Ich klammer mal die einzelnen Aufrufe aus der Schleife aus:
>~# time { LASTENTRY=`dmesg | tail -n1`; for i in {1..1000}; do
>LASTTIME=${LASTENTRY%%.*}; BOOT=`cat /proc/uptime`; date -d
>"$((${BOOT%%.*} - ${LASTTIME#[})) seconds ago"; done > /dev/null; }
>
>real 0m4.661s
>user 0m1.264s
>sys 0m3.132s
>
>dmesg|tail schluckt schon mal >10s, also schon mal 2/3 der Gesamtzeit.
>
>~# time { for i in {1..1000}; do dmesg; done > /dev/null; }
>real 0m7.649s
>user 0m2.636s
>sys 0m5.152s
>
>Den größten Teil davon benötigt dmesg selbst, ist also nicht vermeidbar.
>Bleiben ca. 3s für tail.
>
>~# time { BOOT=`cat /proc/uptime`; for i in {1..1000}; do
>LASTENTRY=`dmesg | tail -n1`; LASTTIME=${LASTENTRY%%.*}; date -d
>"$((${BOOT%%.*} - ${LASTTIME#[})) seconds ago"; done > /dev/null; }
>
>real 0m12.770s
>user 0m3.708s
>sys 0m9.517s
>
>cat ist auch mit ca. 3s dabei
>
>
>~# time { for i in {1..1000}; do LASTENTRY=`dmesg | tail -n1`;
>LASTTIME=${LASTENTRY%%.*}; BOOT=`cat /proc/uptime`; done; date -d
>"$((${BOOT%%.*} - ${LASTTIME#[})) seconds ago" > /dev/null; }
>
>real 0m12.775s
>user 0m3.960s
>sys 0m9.365s
>
>date ebenfalls.
>
>> Mantra: Prozesse starten, Disk- und Console-I/O ist lahm!
>Dann spar dir doch auch den seq-Aufruf, das kann die bash auch allein. ;-)
>
>-- for i in `seq 1 1000`;
>++ for i in {1..1000};
Ach, alte Gewohnheit, hab 10 Jahre mit bash-2.x programmiert ... Und
1. es ist genau 1 Aufruf pro Durchlauf (und nicht _in_ der Schleife)
2. Der Unterschied ist gar nicht mal groß (kleinster und größer Wert
aus 3 Durchläufen):
$ time for i in `seq 1 1000000`; do :; done
real 0m2.588s
real 0m2.691s
$ time for i in {1..1000000}; do :; done
real 0m2.245s
real 0m2.273s
Grob geschätzt: die ~0.4s Unterschied sind dem einmaligen Start von
'seq' geschuldet ;) _IN_ der Schleife addieren sich Programmstarts
aber massiv. Und deswegen ist z.B. auch perl statt bash + nochwas sehr
bald "schneller" (und awk noch früher), solange man nicht allzuviele
Module nachlädt[1]. Andererseits kann man mit perl und perl-Modulen
eben dann auch bequem sehr viel mehr machen und auf externe Programme
verzichten, ich sach nur z.B. "Mime" oder "Date" oder eigene 'sort'
Routinen ;) Ist ne Erfahrungssache und gilt ebenso für python oder
sonstwas. Ich mag halt perl (wenn bash/sed/awk nimmer sinnvoll ist).
>> Oh, da fällt mir ein: das 'date' kann man sich (mit GNU awk) auch noch
>> sparen:
>>
>> real 0m4.050s
>> user 0m0.220s
>> sys 0m0.452s
>
>Nur um hier auch den Vergleichswert auf der selben Maschine zu haben:
>~# time { for i in {1..1000}; do dmesg | gawk -F'[][ ]+' ' BEGIN {
>getline < "/proc/uptime"; u = $1; } END { print strftime("%c", systime()
>- (u - $2) ); }'; done > /dev/null; }
>
>real 0m10.197s
>user 0m2.996s
>sys 0m7.248s
>
>ca. 4s bei date gespart, also ähnlich dem Ergebnis vom ausklammern oben.
*hehe*
>Insgesamt ist das damit auch ein schön kurzer Einzeiler, der nur 1
>zusätzliches Programm (gawk) benötigt. Sehr gut. :-)
Noch ein Mantra/ne Faustregel: wer in einer Pipe mehr als genau ein
'cut', 'sed', 'awk' oder 'perl' (python) verwendet, der macht was
falsch. Mit dem jew. nächstgenannten Tool kann man eigentlich immer
das geforderte effektiver erledigen.
>Ich bin zwar nicht der awk-Guru, aber wenn ich es mal einsetze, dann
>auch möglichst ohne Verkettungen mit anderen Programmen.
Gilt auch für sed, perl und andere ;) awk ist für mich oft eine
bequeme und "schlanke" Zwischenstufe zwischen sed und perl. Mit awk
kann man richtig programmieren (Variablen, Funktionen, usw., was mit
sed nicht geht). Ich hab z.B. ein 'headntail' (Version 0.0.1a (alpha),
(c)2003) als awk-Script, das mir z.B. die ersten und letzten 10 Zeilen
einer Datei ausgibt:
$ seq 10 | headntail -2 | xargs
1 2 9 10
Mit head/tail kommt man um zweimalige Lesen der Datei nicht rum, mein
Script macht das zwar auch, aber einmal nur zum Zeilenzählen mit
'wc -l'[2].
War auf jedenfall eine sehr lehrreiche awk-Programmierübung für
mich[3] und ist sogar teils sinnvoll kommentiert ;)
>Damit sollten wir dem OP jetzt genügend Anregungen für seinen
>Programmierspaß gegeben haben. ;-)
>
>Wobei mein Spaß daran auch nicht zu kurz kam. :-)
Prima. So soll es sein :)
-dnh, der die Tage endlich mal das ISO von seiner ersten Linux-CD
gezogen hat: Debian-1.3.1_chip_ed.iso vom Dec. 1997 aka "bo" :)
Auch deswegen lunger ich hier auf der ML rum, obwohl ich aktuell
kein Debian im Einsatz habe ...
[0] und mein Hauptrechner davor war seit 2000 ein 500 MHz Athlon, der
langsamste den's je gab ;) Allerdings hab ich seit ~4 Jahren nen
Zweitrechner mit nem Athlon 64 X2 3800+EE (2x2.0 GHz), der
inzwischen nur noch Fileserver macht (und dessen NT zu sterben
scheint *grumpf*).
[1] da bremst aber v.a. das Finden und Laden (I/O) der Module
[2] ob das awk-intern evtl. effizienter ginge habe ich nie ausprobiert
[3] bei Interesse (->per PM kundtun bitte) mail ich das gern per PM
oder lad's ggfs. auf meine Webseite.
--
Wenn der Mailserver platzt, werden halt nochmal 80 GB dazugesteckt.
Ist billiger als die Arbeitszeit zum Aufräumen. -- Marc Haber
Reply to: