Linux Bash: In jede Ausgabezeile einen Zeitstempel

Hi!

Ich habe ein kleines Problem. Ich möchte eine Simulation in einer Linux Bash laufen lassen und in der Ausgabe in jeder ausgegebene Zeile einen Zeitstempel haben, wann diese Zeile ausgegeben wurde. Ich habe bereits etwas mit sed experimentiert:

./datei | sed -u -e i\ `date +%X.%N`

Das liefert zwar vor jeder Zeile einen Zeitstempel, allerdings wird der wohl einmal beim Aufruf geholt und es steht in jeder Zeile die gleiche Zeit. Wie könnte ich das sonst noch machen?

Gruß Martin

Hallo Martin.

Ich möchte in der Ausgabe in jeder ausgegebenen Zeile einen Zeitstempel haben.

Probier’s mal damit:

cat datei.txt | while read i; do printf "%s: $i\n" $(date +%X.%N); done

Gruß,
-Andreas.

Danke, das scheint zu funktionieren :smile:

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

So, jetzt doch ein Problem festgestellt. Der Befehl scheint erst einige Ausgabe zu Buffern bevor sie ausgegeben wird. Das führt dazu, dass viele Zeilen die gleiche Zeit bekommen, obwohl sie mit 10s Unterschied ausgegeben werden wenn ich das Programm normal starte…

Gruß Martin

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Martin.

Ich möchte in der Ausgabe in jeder ausgegebenen Zeile einen Zeitstempel haben.

cat datei.txt | while read i; do printf „%s: $i\n“ $(date +%X.%N); done

Der Befehl scheint erst einige Ausgabe zu Buffern bevor sie ausgegeben wird. Das führt dazu, dass viele Zeilen die gleiche Zeit bekommen, obwohl sie mit 10s Unterschied ausgegeben werden wenn ich das Programm normal starte…

Die verwendete Pipe der Form „a | b“ verwendet Zeilenpufferung ,
d.h. erst wenn der Prozess a eine komplette Zeile mit abschließendem Newline geschrieben hat, wird die Zeile an Prozess b weitergereicht.

Für Dich heißt das, das obige Lösung einen Zeitstempel erzeugt
für das vollständige Schreiben einer Ergebniszeile von Prozess a.

Mit folgendem Beispiel-Skript - slow-output.sh - als Erzeuger a,
wird die Funktionsweise deutlich:

#!/bin/bash
# Datei: slow-output.sh

echo -n "1a) $(date +%X.%N) ... "
sleep 5
echo "1b) $(date +%X.%N)"

echo -n "2a) $(date +%X.%N) ... "
sleep 5
echo "2b) $(date +%X.%N)"

Zudem scheint das printf noch eine Ausgabepufferung einzufügen,
deshalb habe ich es durch ein einfaches echo ersetzt:

$ ./slow-output.sh | while read i; do echo "$(date +%X.%N): $i"; done

01:18:42.468750000: 1a) 01:18:37.078125000 ... 1b) 01:18:42.312500000
01:18:47.812500000: 2a) 01:18:42.453125000 ... 2b) 01:18:47.687500000

Wie Du siehst entspricht der von echo hinzugefügte Zeitstempel bis auf wenige Millisekunden dem Zeitstempel b).

Willst Du einen Zeitstempel für den Beginn der Prozessausgabe von
a haben, wird es etwas komplizierter. Hier hilft folgendes Perl-Skript
timestamper.pl:

#!/usr/bin/perl -w
# Datei: timestamper.pl

# modules:
use strict;
use Term::ReadKey;
use Time::localtime; # for easier time member access
use Time::HiRes; # to get current microseconds

# variables:
my $firstKey;
my $remainingLine;

while (!eof()) { # run until input channel gets closed
 ReadMode('cbreak'); # switch to single-key processing
 while (not defined ($firstKey = ReadKey(-1))) {} # wait for first key of line

 my ($seconds, $microseconds) = Time::HiRes::gettimeofday();
 my $timestamp = localtime($seconds);
 my $time = sprintf("%02d:%02d:%02d.%06d", $timestamp-\>hour, $timestamp-\>min, $timestamp-\>sec, $microseconds);

 print "${time}: $firstKey";

 ReadMode('normal'); # back to line-processing
 $remainingLine = ReadLine 0;
 print $remainingLine;
}

Die Ausgabe dazu:

$ ./slow-output.sh | ./timestamper.pl

01:21:47.343750: 1a) 01:21:47.203125000 ... 1b) 01:21:52.453125000
01:21:52.562500: 2a) 01:21:52.562500000 ... 2b) 01:21:57.812500000

Nun entspricht der Zeitstempel knapp dem von a).

Gruß,
-Andreas.