2016-01-22 9 views
5

Ich habe ein Programm, das seine Ausgabe in eine * .out-Datei protokolliert, wenn es ausgeführt wird. Ich habe ein Bash-Skript eingerichtet, um mehrere verschiedene Zeiten laufen zu lassen, so dass jeder Lauf in eine andere * .out-Datei schreibt. Ich fand, dass ich die letzte * .out-Datei wie folgt tail könnte:Die letzte Datei beenden

watch tail $(ls -tr *.out | tail -n1) 

Das Problem scheint zu sein, dass die Referenzierung $() wird nur einmal ausgeführt. Wenn der erste Lauf abgeschlossen ist, wird die watchtail die gleiche * .out-Datei fortgesetzt, obwohl es jetzt eine neuere * .out-Datei gibt.

Wie kann ich dies ändern, um nach einem Lauf zur nächsten * .out-Datei zu gelangen?

Ich habe versucht, ein paar Schachteln von Anführungszeichen und Klammern, aber ich verstehe nicht wirklich die Details der Referenzierung. Die Angelegenheit wird durch die Tatsache kompliziert, dass watch seinen Befehl an sh übergibt, obwohl ich bash verwende.

Bonuspunkte: es wäre großartig, wenn dies geändert werden könnte zu tail -f statt nur watch alle n Sekunden zu wiederholen.

+2

hm..ich verstehe den Anwendungsfall wirklich nicht. Möchten Sie ein paar Dateien in Echtzeit lesen? Wenn ja, ist es einfacher, 'tail -f * .out' zu verwenden. – pivanchy

+0

Ich stimme generell mit @pivanchy überein, obwohl es erwähnenswert ist, dass POSIX' tail' nicht garantiert, mehrere Dateien gleichzeitig zu verarbeiten. – kojiro

+0

@pivanchy das ist die Lösung. Ich wusste nicht, dass es so einfach ist. –

Antwort

2

ich behandeln auch mit diesem Problem und kam schließlich zu dieser Lösung:

watch "ls -t1 | sed q | xargs tail" 

Need ein bisschen hacky für den Bonus zu bekommen. Der Befehl tail unterstützt auch ein Argument --pid, das tail stirbt, sobald die referenzierte PID stirbt. Hört sich gut an? Hier einige Muster, das Sie verwenden:

while true; do ls -t1 | sed q | xargs lsof -F np | sed 's/.\(.*\)/\1/g' | xargs tail -f --pid 2>/dev/null ; done 

Diese im Grunde verfolgt die aktuelle Datei und startet tail, wenn die Datei Schreibvorgang beendet ist.

+0

Danke! Ich musste einfach einen einfachen Dateifilter hinzufügen: 'watch ls -t1 * .out | sed q | xargs tail "' –

+1

@JeffIrwin Probieren Sie auch das Edit aus. Es sieht nicht mehr auf die Datei, sondern folgt direkt der Ausgabe (mit Tail). – steffen

+1

Die Bearbeitung funktioniert großartig! Ich werde nicht einmal versuchen, alle Pipelines zu verstehen. –

1

Also, ich werde ein wenig meine aktuelle Antwort duplizieren: Tail the most recent file

Sie sehr einfachen Befehl verwenden könnten Ihr Problem zu beheben:

tail -f *.out 

Schwanz arbeitet mit mehreren Dateien zu und es ist möglich, zu verwenden, um es wie:

tail -f file1 file2 file3 

so, wie Sie sehen können, ist es sehr leistungsfähig und einfach Werkzeug und Sie müssen nicht mit linux-Befehl spielen s

1

Wenn alle Dateien beginnen existieren, und Sie haben eine moderne Implementierung von tail, die mehrere Dateien verarbeiten kann,

tail -f *.out 

scheint die beste Lösung zu sein. Aber wenn Sie nicht alle Dateien haben, wäre es am einfachsten, wenn Sie sie erst einmal erstellt hätten. *.out wird nur auf die Dateien erweitert, die Sie bereits haben.

Wenn Sie jedoch die Dateinamen für tail -f nicht kennen können, bevor Sie beginnen, müssen Sie den Tail neu starten, wenn während des Tailings neue Outfiles erstellt werden.In diesem Fall, da Sie nur auf die jeweils zu einem Zeitpunkt outfile ein Schreiben, könnten Sie tun:

inotifywait -m -e create -q . | while read dir event file; do 
    kill %tail 
    tail -f "$file" & 
done 
kill %tail 

(Die obige inotifywait erfordert, die in inotify-tools auf Debian-basierten Systemen wie Ubuntu enthalten ist.) Es Uhren das aktuelle Verzeichnis für neu erstellte Dateien, Tails, welche Datei auch immer erstellt wurde, im Hintergrund, und beendet den vorherigen Tail-Befehl, wenn eine neue Datei erstellt wird.

Verwandte Themen