
Ich habe diese extrem einfache Funktion in meinem Skript:
# Used for debug tracing.
log()
{
:
echo "log: $1"
}
Die Idee besteht darin, die Protokollierung an einer einzigen Stelle anpassen/deaktivieren zu können. Sehr grob.
Jetzt möchte ich, dass mein Skript in der Release-Konfiguration absolut keine Ausgabe erzeugt. Die einzige Lösung, die mir eingefallen ist, aber äußerst unDRY:
TMPFILE='/tmp/tempfilewithpossiblyuniquename'
cmd 1>"$TMPFILE" 2>"$TMPFILE"
cat "$TMPFILE" | xargs log
rm "$TMPFILE"
fürjeder einzelne Befehl. Wie kann man das verbessern?
EDIT: Ich möchte sammelnalleAusgabe an stdout
und stderr
und durchleiten log()
. Dann log()
können Sie wählen, ob Sie alles ignorieren, in eine Datei protokollieren, drucken usw. möchten.
Antwort1
Erstens protokolliert diese Funktion nur das erste „Wort“ aller an sie gesendeten Informationen, da Sie $1
anstelle von verwenden "$*"
.
Zweitens gibt es (wie so oft bei POSIX) unzählige Möglichkeiten, so etwas zu tun. Ich würde wahrscheinlich etwas wie Folgendes wählen:
log() {
cat - >> "$logfile"
}
do_stuff | log
Sie könnten aber auch:
(
do_stuff
do_more_stuff
) >> "$logfile"
Was das vollständige Unterdrücken aller Ausgaben betrifft, so ist dies normalerweise etwas, das man am besten der aufrufenden Umgebung überlässt (z. B. ./thing 1> /dev/null 2> &1
), anstatt es sozusagen „im Code“ zu sperren. Das heißt:
squashout="true" # comment this out to stop killing output
if ! [[ "true" = "${squashout-false}" ]]; then
# Redirect stdout and stderr to the null device.
exec 1> /dev/null
exec 2> /dev/null
fi
Antwort2
Es ist einfach, absolut keine Ausgabe zu erstellen. Leiten Sie die Skripts einfach stdout
um stderr
nach /dev/null
:
exec >/dev/null 2>&1
Dies wirkt sich auf die Shell selbst und alle Befehle aus, die sie anschließend ausführt. Führen Sie dies bedingt aus, um auszuwählen, wohin die Ausgabe umgeleitet wird.
if [ "$output_to_file" = 1 ]; then
exec > "$outputfilename" 2>&1
elif [ "$output_suppress" = 1 ]; then
exec > /dev/null 2>&1
fi
Beachten Sie, dass das UnterdrückenalleAusgabe ist wahrscheinlich keine gute Idee. Der Benutzer möchte sehr wahrscheinlichmancheBenachrichtigung bei Fehlern.
Wenn Sie darauf bestehen, die Ausgabe durch die Funktion zu übergeben (und Bash/ksh/Zsh ausführen), können Sie die Prozesssubstitution verwenden:
#!/bin/bash
mangle_output() {
# do something smarter here
while read -r line; do
echo "output: $line";
done;
}
# redirect stdout and stderr to the function
exec > >(mangle_output) 2>&1
echo something that produces output
Beachten Sie jedoch, dass die Verarbeitung der Ausgabe mit einer Shell-Schleife keine gute Idee ist, zumindest ist es langsam. Siehe:Warum gilt die Verwendung einer Shell-Schleife zur Textverarbeitung als schlechte Praxis?. Wenn Sie lediglich eine Datei oder zu umleiten möchten /dev/null
, verwenden Sie einfach exec
zum Einrichten von Umleitungen.