Senden Sie stdout und stderr an Datei, Syslog und Terminal

8

Bei einigen Cloud-Computern, die ich starte, versuche ich, mich bei einer bestimmten Datei, einem bestimmten Syslog und dem Terminal / der Konsole anzumelden.

Am Anfang meiner Maschinen-Setup- / Cloud-Init-Skripte habe ich Folgendes:

#!/bin/bash
exec &> >(tee "/tmp/box-setup.log" | logger -t box-setup)
apt-get install -y some-package

Dies funktioniert hervorragend beim Senden von Ausgaben an eine Datei und ein Syslog, leitet jedoch keine Weiterleitungen an das Terminal weiter.

Im Allgemeinen ist es kein großes Problem, keine Terminalausgabe zu haben, außer wenn ich von einer Remote-Konsole aus debugge. In diesem Fall bin ich völlig blind, da die Konsole während der Ausführung des Bash-Skripts leer ist.

Gibt es eine einfache Möglichkeit, die bashUmleitung oder was auch immer zu verwenden, um alle Ausgaben (Standardausgabe zusammen mit Standardfehler) gleichzeitig an eine Datei, ein Syslog und das Terminal zu leiten?

Ich verwende Ubuntu 16.04.

Jonathan Oliver
quelle

Antworten:

8

Fügen Sie eine verschachtelte Prozessersetzung und eine andere hinzu, teewie:

exec &> >(tee >(tee "/tmp/box-setup.log" | logger -t box-setup))

Die erste teeinnerhalb der Hauptprozessersetzung sendet STDOUT / STDERR an das Terminal und auch an die verschachtelte Prozessersetzung. Die teeInnenseite, die den Inhalt in der Datei /tmp/box-setup.logund der Pipe speichert, wird auch zum Senden der Ausgabe an loggerSTDIN verwendet.

heemayl
quelle
Ich bin verwirrt über mehrere Tee-Aufrufe, es wird sich in n Streams teilen, sollte dies nicht gleichwertig sein? exec &> >(tee /tmp/box-setup.log >(logger -t box-setup))
ThorSummoner
3

Ich bin völlig blind, weil die Konsole leer ist, während das Bash-Skript ausgeführt wird.

Möglicherweise möchten Sie dieses Problem auf eine andere Weise lösen: Führen Sie Ihr Bash-Skript im Hintergrund aus und führen Sie less /tmp/box-setup.logF aus, um den Bildschirm weiter zu aktualisieren, während der angezeigten Datei Zeilen hinzugefügt werden (wie tail -f).

Wenn das Ausführen des Skripts im Hintergrund ein Problem darstellt, verwenden Sie tmuxoder screen, um mehrere Sitzungen auf eine SSH-Verbindung zu multiplexen. Verwenden Sie denselben lessBefehl in einer anderen Shell.


Das ursprüngliche Problem:

teekann an mehrere Ziele kopieren. Machen Sie eines davon mit der /dev/ttyspeziellen Datei zum Terminal . Ich denke, es bezieht sich immer auf die Kontrolle des aktuellen Prozesses. Oder wahrscheinlich besser, /dev/stderrda tee's stderr immer noch mit dem stderr der Shell verbunden ist. (Auf diese Weise können Sie das Skript mit &> / dev / null zum Schweigen bringen.)

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

Übrigens ist dies gleichbedeutend mit aber effizienter als (tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...).

Es wäre möglich, ein Dateideskriptor-Klonen zu verwenden, um teedas stdout des ursprünglichen Skripts anstelle von stderr anzugeben.

Peter Cordes
quelle
1

Fügen Sie einfach /dev/stderr(Ihre Wahl) als Ausgabe hinzu tee.

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

Standardausgabe und Standardfehler werden zusammengeführt. Es gibt keine Möglichkeit, sie getrennt zu halten, wenn Sie ihre Reihenfolge beibehalten möchten, was normalerweise wünschenswert ist. Es spielt keine Rolle, ob beide sowieso zum selben Ort (z. B. zum Terminal) gehen.

Gilles 'SO - hör auf böse zu sein'
quelle
tee's stdout ist die Pipe zum Logger, nicht das Terminal. Es ist stderrzu diesem Zeitpunkt immer noch das Terminal, basierend auf exec &> >(tee /dev/stderr > /dev/null)der erwarteten Arbeit in einer interaktiven Shell. stderrscheint eine bessere Idee zu sein als meine /dev/ttyIdee, da Sie damit das Skript einfach mit einer Umleitung schließen können, wenn Sie möchten.
Peter Cordes