tail -f, Zeilenumbruch einfügen, nachdem das Protokoll 3 Sekunden lang inaktiv ist?

14

tail -f error.logWie füge ich bei a einen Zeilenumbruch programmgesteuert ein, nachdem 3 Sekunden lang nichts an die Datei angehängt wurde?

(Sobald ein Zeilenumbruch hinzugefügt wurde, sollte kein weiterer Zeilenumbruch hinzugefügt werden, bis der Protokolldatei weitere Textzeilen hinzugefügt wurden.)

Diese Zeilen werden beispielsweise an error.log angehängt:

foo
bar
boo [[wait 4 seconds]]
2far
2foo
2bar
2boo [[wait 40 seconds]]
2far

Dies wäre die Ausgabe in der Konsole:

foo
bar
boo

2far
2foo
2bar
2boo

2far
Cedric
quelle
Sie könnten wahrscheinlich meine Funktion in askubuntu.com/a/993821/158442 anpassen oder tsZeitstempel zur Ausgabe hinzufügen und die Zeitstempel verarbeiten
muru
1
Erwähnenswert ist, dass Sie, wenn Sie es interaktiv tun, die Eingabetaste ein paarmal drücken können. :)
Wildcard

Antworten:

12

Sie können das immer von Hand implementieren tail -f(also hier, es sei denn, Sie kommentieren das aus seek(), eher so, tail -n +1 -fals würden wir die gesamte Datei sichern), perlzum Beispiel mit:

perl -e '
  $| = 1;
  # seek STDIN, 0, 2; # uncomment if you want to skip the text that is
                      # already there. Or if using the ksh93 shell, add
                      # a <((EOF)) after < your-file
  while (1) {
    if ($_ = <STDIN>) {
      print; $t = 0
    } else {
      print "\n"            if $t == 3;
      # and a line of "-"s after 10 seconds:
      print "-" x 72 . "\n" if $t == 10;
      sleep 1;
      $t++;
    }
  }' < your-file

Oder lassen tail -fSie das Tailing durchführen und verwenden Sie perl, um die Zeilenumbrüche einzufügen, wenn 3 Sekunden lang keine Eingabe erfolgt:

tail -f file | perl -pe 'BEGIN{$SIG{ALRM} = sub {print "\n"}} alarm 3'

Diese gehen davon aus, dass die Ausgabe selbst nicht verlangsamt wird (wie wenn die Ausgabe an eine Pipe geht, die nicht aktiv gelesen wird).

Stéphane Chazelas
quelle
Ich habe lange
gebraucht,
Ich habe das erste ausprobiert und ALLE Dateien vor der Hand gedruckt, daher ist es nicht optimal. Der zweite wirkt wie ein Zauber. Ich habe das "tail -n 0 -f $ 1 |" Option (-n 0), um die Anzeige der alten Dateizeilen zu vermeiden.
Cedric
Kleine Frage: Wie kann ich die zweite Lösung so ändern, dass nach 10 Sekunden eine zusätzliche Strichzeile (-------) angezeigt wird? (Ich habe mehrere Möglichkeiten ausprobiert, kann aber nichts zum Laufen bringen)
Cedric
1
@ Cedric, siehe Bearbeiten für Ihren ersten Punkt. Ihre zweite Anforderung wäre mit dem ersten Ansatz einfacher.
Stéphane Chazelas
8

bash+ dateLösung:

while IFS= read -r line; do        
    prev=$t         # get previous timestamp value
    t=$(date +%s)   # get current timestamp value
    [[ ! -z "$prev" ]] && [[ "$((t-prev))" -ge 3 ]] && echo ""
    echo "$line"    # print current line
done < <(tail -f error.log)
RomanPerekhrest
quelle
In Bash können Sie $SECONDSZeitintervalle zählen. Ich denke, es ist die Anzahl der Sekunden, die seit dem Start der Shell vergangen sind, nicht dass es wichtig ist, einen Unterschied zu machen.
Ilkkachu
@ilkkachu oder read -toder $TMOUT. $SECONDSist eingebrochen bashund mksh. time bash -c 'while ((SECONDS < 3)); do :; done'dauert zwischen 2 und 3 Sekunden. Verwenden Sie stattdessen lieber zsh oder ksh93 (mit typeset -F SECONDS)
Stéphane Chazelas
@ StéphaneChazelas, ich glaube nicht, dass es anders ist als mit date +%s. Beide geben die Zeit in vollen Sekunden an, was zur Folge hat, dass das Intervall von beispielsweise 1,9 bis 4,0 wie 3 volle Sekunden aussieht, obwohl es wirklich 2,1 ist. Es ist schwierig, das zu umgehen, wenn Sie nicht auf die Sekundenbruchteile zugreifen können. Aber ja, sie sollten hier wahrscheinlich schlafen, anstatt sich zu beschäftigen, und read -tkönnten dann genauso gut benutzt werden. Auch wenn Sie manuell schlafen, time bash -c 'while [[ $SECONDS -lt 3 ]]; do sleep 1; done'funktioniert gut.
Ilkkachu
1
ksh93 und zsh sind damit in Ordnung (zsh nicht). Selbst mit der Ganzzahl $ SECONDS wird durch die Einstellung SECONDS=0sichergestellt, dass $SECONDSin genau 1 Sekunde 1 erreicht wird. Dies ist nicht der Fall, bashda es verwendet wird time(), um $SECONDSstattdessen zu verfolgen gettimeofday(). Ich habe vor einiger Zeit Bugs bei mksh, zsh und bash gemeldet, nur zsh wurde behoben. (Guter Punkt über das Problem ist das gleiche mit date +%s). Beachten Sie, dass es sich hier nicht um eine Busyloop handelt, da wir von der Ausgabe tail -füber eine Pipe lesen .
Stéphane Chazelas
+1 und heftiger Schlag haben eine „Verknüpfung“ mit dem integrierten in printfemulieren , dateohne externe Werkzeuge oder Befehl Substitution: printf -v t '%(%s)T' -1.
David Foerster
6

PythonLösung (mit dynamischem Zeitlückenargument ):

tailing_by_time.py Skript:

import time, sys

t_gap = int(sys.argv[1])    # time gap argument
ts = 0
while True:
    line = sys.stdin.readline().strip()    # get/read current line from stdin
    curr_ts = time.time()                  # get current timestamp
    if ts and curr_ts - ts >= t_gap:
        print("")                          # print empty line/newline
    ts = curr_ts
    if line:
        print(line)                        # print current line if it's not empty

Verwendung:

tail -f error.log | python tailing_by_time.py 3
RomanPerekhrest
quelle