Erfassen Sie die normale Ausgabe (stdout) zusammen mit der Fehlerausgabe (stderr)

Erfassen Sie die normale Ausgabe (stdout) zusammen mit der Fehlerausgabe (stderr)

Es gibt ein Skript, das über Cron mit der folgenden Zeile ausgeführt wird:

0 * * * * (/var/script.sh | tee -a /var/script.log)

Wie schreibe ich den Cron-Eintrag um, um sowohl die normale stdoutals auch die Fehlerausgabe zu erfassen stderr? Sie müssen in unterschiedlichen Dateien abgelegt werden.

Antwort1

cronJobs werden standardmäßig ausgeführt shund unabhängig davon, ob es shsich um ein Bourne- oder POSIX- shkompatibles System handelt, lautet die Syntax:

0 * * * * /var/script.sh 2>&1 | tee -a /var/script.log

Dies führt |dazu, dass die beiden Befehle auf beiden Seiten parallel ausgeführt werden, verbunden mit einer Pipe, wobei der Standardausgang (fd 1) des linken Befehls an das Schreibende der Pipe angeschlossen ist und der Standardeingang (fd 0) des rechten Befehls an das Lesende angeschlossen ist.

Durch Hinzufügen 2>&1zum linken lassen wir fd 2 (stderr) auf die gleiche Ressource verweisen, wie sie von fd 1 angezeigt wird: das Schreibende der Pipe, sodass sowohl die normale als auch die Fehlerausgabe von script.shan die Pipe zu gehen tee.

teeschreibt es sowohl in seine Standardausgabe (die im Fall eines Cron-Jobs entweder eine Pipe oder eine temporäre Datei ist, die zum Senden einer E-Mail an den Benutzer verwendet wird) als auch in script.log.

Diese Syntax funktioniert auch in der fishShell.

Mit (t)cshoder (4.0 oder neuer) können Sie außerdem Folgendes tun zsh:bash

SHELL=/bin/zsh # or tcsh, bash ...
0 * * * * /var/script.sh |& tee -a /var/script.log

(wo SHELL=/bin/zsherfahren Sie, wie Sie cronzur Interpretation der Befehlszeilen eine andere Shell verwenden sollen).

In fishwürden Sie &|anstelle von verwenden |&.

Mit rc(dem einstigen Nachfolger von sh) oder Ableitungen lautet die Syntax:

SHELL=/bin/rc # or es, akanga
0 * * * * /var/script.sh >[2=1] | tee -a /var/script.log

Mit zshkönnen Sie auch darauf verzichten, tee dank seiner MULT_IOSFunktion:

SHELL=/bin/zsh
0 * * * * /var/script.sh >&1 2>&2 >>& /var/script.log

Dies hätte außerdem den Vorteil, dass script.shder Beendigungsstatus von erhalten bliebe, und außerdem würde script.shstderr von zusätzlich zum ursprünglichen stderr gehen script.log(obwohl das bei einem Cron-Job keinen großen Unterschied macht, wo stdout und stderr im Allgemeinen sowieso an die gleiche Stelle gehen).

Einige Bourne/POSIX-ähnliche Shells ( zumindest bash, ksh93, zsh, yash, ) verfügen über eine Option, die Sie verwenden können, um Fehler in jeder Komponente einer Pipeline melden zu können:mkshpipefail

SHELL=/bin/ksh # or zsh, bash...
0 * * * * set -o pipefail && /var/script.sh 2>&1 | tee -a /var/script.log

Antwort2

cron möchte Sie über jeden Cron-Job informieren, der eine Ausgabe erzeugt. Es möchte Ihnen die Ergebnisse per E-Mail zusenden. Wenn Sie keine E-Mails von cron erhalten möchten, stellen Sie sicher, dass Ihre Jobs keine Ausgabe erzeugen: Verwenden Sie nicht tee, sondern leiten Sie die Ausgabe einfach um.

0 * * * * /var/script.sh >> /var/script.log 2>&1

Beachten Sie auch, dass ich die Klammern entfernt habe: Es hat keinen Sinn, das Skript in einer Subshell auszuführen.

verwandte Informationen