
Ich kann die Ausgabe eines Skripts direkt innerhalb des Skripts in eine Protokolldatei umleiten, indem ich Folgendes verwende exec
:
#!/bin/bash
exec > stdout.log 2>&1
echo hello world
less
Ist es möglich, die Ausgabe anstelle einer Datei umzuleiten ? Ich habe es versucht
#!/bin/bash
exec > >(less) 2>&1
# output some text
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done
aber dies schlägt auf seltsame Weise fehl ... die kleinere Eingabeaufforderung ist sichtbar, aber Sie landen wieder am Terminal.
Ich möchte dies am Anfang des Skripts einrichten (damit es bedingt sein kann, abhängig von Argumenten, TTY usw.).
Antwort1
Sie sollten Ihr Skript auf den less
untergeordneten Prozess warten lassen, da es sonst vor diesem beendet wird und less
sich plötzlich außerhalb der Vordergrundprozessgruppe befindet und nicht mehr in der Lage ist, Befehle vom Terminal zu lesen oder die Terminaleinstellungen wiederherzustellen.
Um außerdem zu verhindern, less
dass Sie ewig auf das Ende der Eingabe warten müssen, sollte Ihr Skript die Pipe dorthin schließen.
Alles in allem:
exec > >(less) 2>&1
trap 'exec >&- 2>&-; wait' EXIT
# >&- 2>&- => close stdout and stderr => cause EOF on less' stdin
seq 1 50000
# the rest of your script
Dies ist jedoch nicht sehr schön, nicht auf die meisten anderen Shells portierbar und basiert auf einem nicht dokumentierten (und unzuverlässigen) Verhalten von Bash: Es wait
funktioniert nicht richtig, wenn Ihr exec > >(...)
Skript mehr als eine hat, und es wartet außerdem auf andere Hintergrundprozesse, die mit gestartet wurden &
.
Eine bessere Idee wäre, Ihr Skript sich selbst aufrufen zu lassen und dabei eine Umgebungsvariable zu verwenden, um eine Endlosrekursion zu vermeiden:
if [ ! "$CALLED_MYSELF" ]; then
set -o pipefail # supported in bash, but not in all the shells
CALLED_MYSELF=1 "$0" "$@" 2>&1 | less
exit
fi
seq 1 50000
# the rest of your script
Antwort2
Versuchen Sie einfach dies (ohne die exec
Zeile):
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done | less
(aktualisieren)
Wenn Sie das gesamte Skript einbinden möchten, können Sie das Skript umschließen mit{ ... }
#!/bin/bash
{
# output some text
for (( i=1; i <= 500; i++)) do echo "hello world $i"; done
# whatever output you want...
} | less