Ich möchte jeder Ausgabezeile eines Befehls einen Zeitstempel voranstellen. Zum Beispiel:
foo
bar
baz
würde werden
[2011-12-13 12:20:38] foo
[2011-12-13 12:21:32] bar
[2011-12-13 12:22:20] baz
... wobei der vorangestellte Zeitpunkt der Zeitpunkt ist, zu dem die Zeile gedruckt wurde. Wie kann ich das erreichen?
Antworten:
moreutils beinhaltet
ts
was das ganz nett macht:command | ts '[%Y-%m-%d %H:%M:%S]'
Es ist auch keine Schleife mehr erforderlich. Auf jeder Ausgabezeile ist ein Zeitstempel angebracht.
Sie möchten wissen, wann der Server wieder hochgefahren wurde, den Sie neu gestartet haben? Einfach ausführen
ping | ts
, Problem gelöst: D.quelle
tail -f /tmp/script.results.txt | ts
ssh -v 127.0.0.1 2>&1 | ts
-s
es für nützlich , auf den Parameter hinzuweisen . Wie das zeigt die Laufzeit des Befehls. Ich persönlich benutze gerne beidests
undts -s
gleichzeitig. Sieht ungefähr so aus:command | ts -s '(%H:%M:%.S)]' | ts '[%Y-%m-%d %H:%M:%S'
. Dies stellt die Protokollzeilen wie folgt voran:[2018-12-04 08:31:00 (00:26:28.267126)] Hai <3
Erstens, wenn Sie erwarten, dass diese Zeitstempel tatsächlich ein Ereignis darstellen, denken Sie daran, dass es wichtig ist, dies so nahe wie möglich an die Zeit zu halten, die die ursprüngliche Zeile haben würde, da viele Programme eine Zeilenpufferung durchführen (einige aggressiver als andere) statt eines Zeitstempels einer stattfindenden Aktion gedruckt worden.
Möglicherweise möchten Sie auch überprüfen, ob in Ihrem Befehl noch keine Funktion dafür integriert ist. Gibt beispielsweise
ping -D
in einigenping
Versionen die Zeit seit der Unix-Epoche vor jeder Zeile aus. Wenn Ihr Befehl jedoch keine eigene Methode enthält, gibt es einige Methoden und Tools, die verwendet werden können, unter anderem:POSIX-Shell
Beachten Sie, dass viele Shells ihre Zeichenfolgen intern als Zeichenfolgen speichern. Wenn die Eingabe das Nullzeichen (
\0
) enthält, wird die Zeile möglicherweise vorzeitig beendet.GNU awk
Perl
Python
Rubin
quelle
stdbuf -o 0
verringert werden. Wenn das Programm die Ausgabepufferung jedoch manuell verarbeitet, hilft dies nicht (es sei denn, es gibt eine Option zum Deaktivieren / Verringern der Größe des Ausgabepuffers).python -u
... for x in sys.stdin
Iteriert über Zeilen, ohne sie zuerst alle in den Speicher zu puffern.Probieren Sie für eine zeilenweise Delta-Messung gnomon aus .
quelle
ts
Live-Prozessen aus. Whilets
ist besser für nicht interaktive Prozesse geeignet.Ryans Beitrag bietet zwar eine interessante Idee, scheitert jedoch in mehrfacher Hinsicht. Beim Testen mit
tail -f /var/log/syslog | xargs -L 1 echo $(date +'[%Y-%m-%d %H:%M:%S]') $1
ist mir aufgefallen, dass der Zeitstempel derselbe bleibt, auch wenn erstdout
später mit einem Unterschied in Sekunden auftritt. Betrachten Sie diese Ausgabe:Meine vorgeschlagene Lösung ist ähnlich, bietet jedoch eine ordnungsgemäße Zeitstempelung und verwendet eher eine etwas tragbarere
printf
als eineecho
Warum
bash -c '...' bash
? Weil aufgrund der-c
Option das erste Argument zugewiesen wird$0
und nicht in der Ausgabe angezeigt wird. Konsultieren Sie die Handbuchseite Ihrer Shell für die korrekte Beschreibung von-c
Das Testen dieser Lösung mit
tail -f /var/log/syslog
und (wie Sie wahrscheinlich erraten konnten) Trennen und Wiederherstellen der Verbindung zu meinem WLAN hat gezeigt, dass sowohl Nachrichtendate
als auchsyslog
Nachrichten den richtigen Zeitstempel aufweisenBash könnte durch eine bourne-artige Shell ersetzt werden, entweder mit
ksh
oderdash
zumindest mit denen, die eine-c
Option haben.Mögliche Probleme:
Die Lösung erfordert
xargs
das Vorhandensein von POSIX-kompatiblen Systemen, sodass die meisten Unix-ähnlichen Systeme abgedeckt werden sollten. Funktioniert offensichtlich nicht, wenn Ihr System nicht POSIX-kompatibel ist oder nicht über Folgendes verfügtGNU findutils
quelle
Ich hätte es vorgezogen, oben zu kommentieren, aber ich kann nicht, seriös. Wie auch immer, das obige Perl-Beispiel kann wie folgt ungepuffert werden:
Das erste '$ |' Hebt die Puffer von STDOUT auf. Der zweite setzt stderr als aktuellen Standardausgangskanal und hebt die Pufferung auf. Da select die ursprüngliche Einstellung von $ | zurückgibt, setzen wir auch $ | zurück, indem wir select in select einschließen auf die Standardeinstellung STDOUT.
Und ja, Sie können 'n Paste so ausschneiden, wie es ist. Ich habe es aus Gründen der Lesbarkeit mehrfach ausgekleidet.
Und wenn Sie wirklich präzisieren möchten (und Time :: Hires installiert haben):
quelle
Die meisten Antworten schlagen vor zu verwenden
date
, aber es ist langsam genug. Wenn Ihre Bash-Version größer als 4.2.0 ist, ist es besser,printf
stattdessen eine Bash-Version zu verwenden. Wenn Sie ältere Bash-Versionen unterstützen müssen, können Sielog
Funktionen abhängig von der Bash-Version erstellen :Siehe Geschwindigkeitsunterschiede:
UPD: Stattdessen ist
$(date +"${TIMESTAMP_FORMAT}")
es besser, die Ausführung zu verwenden$(exec date +"${TIMESTAMP_FORMAT}")
oder sogar$(exec -c date +"${TIMESTAMP_FORMAT}")
zu beschleunigen.quelle
Sie können dies mit
date
und tunxargs
:Erläuterung:
xargs -L 1
weist xargs an, den Befehl continue für jede Eingabezeile auszuführen, und übergibt dabei die erste Zeile.echo `date +'[%Y-%m-%d %H:%M:%S]'` $1
Im Grunde wird das Datum mit dem Eingabeargument am Ende wiedergegebenquelle
$1
. Das ist kein guter Stil. Zitieren Sie immer die Variablen. Darüber hinaus verwenden Sieecho
, was nicht portabel ist. Es ist in Ordnung, funktioniert aber auf einigen Systemen möglicherweise nicht richtig.date
jede Zeile neu bewerten können, oder ist es so ziemlich hoffnungslos?