Leiten Sie die Ausgabe innerhalb des Skripts an Less um.

Leiten Sie die Ausgabe innerhalb des Skripts an Less um.

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

lessIst 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 lessuntergeordneten Prozess warten lassen, da es sonst vor diesem beendet wird und lesssich 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, lessdass 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 waitfunktioniert 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 execZeile):

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

verwandte Informationen