Am 15.08.2011 08:39, schrieb David Haller: > Hallo, > > 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. >> LASTENTRY=`dmesg | tail -n1`; LASTTIME=${LASTENTRY%%]*}; grep >> ${LASTTIME#[} /var/log/syslog | cut -c-15 >> >> Geht sogar ohne sed/awk, auf cut konnte ich zum Schluß nicht ganz >> verzichten. > > Da ich den Krams schon im Cache habe (sonst kommt noch die Ladezeit > der Tools (und evtl. der Subshells) ins Spiel): Wenn man die Genauigkeit nicht benötigt, kann ich grep auch weglassen und mir trotzdem cut/sed/awk sparen. LASTENTRY=`dmesg | tail -n1`; LASTTIME=${LASTENTRY%%.*}; BOOT=`cat /proc/uptime`; date -d "$((${BOOT%%.*} - ${LASTTIME#[})) seconds ago"; > 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, 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 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 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. 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}; > 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. Insgesamt ist das damit auch ein schön kurzer Einzeiler, der nur 1 zusätzliches Programm (gawk) benötigt. Sehr gut. :-) Ich bin zwar nicht der awk-Guru, aber wenn ich es mal einsetze, dann auch möglichst ohne Verkettungen mit anderen Programmen. Damit sollten wir dem OP jetzt genügend Anregungen für seinen Programmierspaß gegeben haben. ;-) Wobei mein Spaß daran auch nicht zu kurz kam. :-) Gruß Rico
Attachment:
smime.p7s
Description: S/MIME Kryptografische Unterschrift