Wie leite ich die Ausgabe um und beende den Vorgang, wenn der Befehl fehlschlägt?

Wie leite ich die Ausgabe um und beende den Vorgang, wenn der Befehl fehlschlägt?

So protokolliere ich sowohl stdout als auch stderr in meinen Skripten (normalerweise Cronjobs):

#!/bin/bash
mylog() {
    echo "[`date '+%Y-%m-%d %H:%M:%S'`] $1"
}
(
mylog 'start'

some-command || mylog 'error' && exit 1

mylog 'end'
) >> /var/log/my-log.log 2>&1

In einigen Skripten verwende ich „return“ statt „exit“ und es funktioniert einwandfrei, aber jetzt heißt es, dass ich „return“ nicht verwenden kann, es sei denn, ich binde das Skript mit „src“ ein oder verwende es in einer Funktion. Also habe ich es in „exit“ geändert, aber das Problem ist, dass es nichts protokolliert, es scheint, als würde es die Ausgabeumleitung stoppen. Ein weiteres Problem ist, dass ich es später nicht mit „src“ einbinden kann, weil ich nur dieses Skript stoppen möchte, nicht alles.

Ich verwende die Ausgabeumleitung, weil ich alles protokollieren möchte, auch wenn kein Fehler aufgetreten ist. Und manchmal geben Befehle nicht einmal die richtigen Exit-Codes zurück, also kann ich dem nicht vertrauen.

Wie kann ich also bei einem Fehler „zurückkehren“? Ich kenne „set -e“, aber ich bevorzuge es, mehr Kontrolle darüber zu haben, wann das Skript gestoppt werden soll.

Irgendwelche Gedanken?

Antwort1

Ich kann das Verhalten, das Sie feststellen, nicht erklären, aber hier ist eine mögliche Lösung:

#!/bin/bash
meinlog() {
    echo "[$(Datum '+%Y-%m-%d %H:%M:%S')] $1"
}

mein Haupt() {
    (
        meinlog 'starten'

        irgendein Befehl || mylog 'Fehler' && return 1

        meinlog 'Ende'
    ) >> /var/log/my-log.log 2>&1
}

mein Haupt

Alternativ können Sie die Umleitung aus der mymainFunktionsdefinition entfernen und in den mymainFunktionsaufruf einfügen:

mymain >> /var/log/my-log.log 2>&1

mymain(Sie sollten dann auch die Klammern aus der Funktionsdefinition löschen können .) Alternativ, da Sie möchten, dass IO für diegesamteSkript können Sie die Umleitung getrennt von den Aktionsanweisungen aufteilen:

exec >> /var/log/mein-log.log
Ausführung 2>&1
mein Haupt

Da ich nicht verstehe, warum Ihr Ansatz fehlschlägt, kann ich nicht erklären, warum die oben genannten Vorgehensweisen eher wie gewünscht funktionieren. Es handelt sich jedoch um leicht unterschiedliche Vorgehensweisen, und das könnte gerade ausreichen. Übrigens habe ich es aus allgemeinen Gründen `date …`in $(date …)„nur“ geändert; ich glaube nicht, dass das irgendetwas mit Ihrem Problem zu tun hat.

Antwort2

Wie wäre es, den screenBefehl unter Linux zu verwenden? Dies wäre der Trick, es sei denn, Sie möchten unbedingt selbst eine Lösung programmieren.

verwandte Informationen