Ich suche nach einer Möglichkeit, stdout und stderr optisch zu trennen, damit sie sich nicht vermischen und leicht zu erkennen sind. Idealerweise hätten stdout und stderr separate Bereiche auf dem Bildschirm, in denen sie angezeigt werden, z. B. in unterschiedlichen Spalten. Eine Ausgabe hätte beispielsweise so ausgesehen:
~$ some command
some useful output info
ERROR: an error
more output
ERROR: has occurred
another message
~$
würde stattdessen ungefähr so aussehen:
~$ some command |
some useful output info |
more output | ERROR: an error
another message | ERROR: has occurred
~$ |
Antwort1
Sie könnten screen
die vertikale Teilungsfunktion von GNU verwenden:
#! /bin/bash -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP
FIFO=$tmpdir/FIFO
mkfifo "$FIFO" || exit
conf=$tmpdir/conf
cat > "$conf" << 'EOF' || exit
split -v
focus
screen -t stderr sh -c 'tty > "$FIFO"; read done < "$FIFO"'
focus
screen -t stdout sh -c 'read tty < "$FIFO"; eval "$CMD" 2> "$tty"; echo "[Command exited with status $?, press enter to exit]"; read prompt; echo done > "$FIFO"'
EOF
CMD="$*"
export FIFO CMD
screen -mc "$conf"
Zu verwenden beispielsweise als:
that-script 'ls / /not-here'
Die Idee ist, dass screen mit einer temporären conf-Datei ausgeführt wird, die zwei Bildschirmfenster in einem vertikal geteilten Layout startet. Im ersten führen wir Ihren Befehl mit dem mit dem zweiten verbundenen stderr aus.
Wir verwenden eine benannte Pipe für das zweite Fenster, um dem ersten sein TTY-Gerät mitzuteilen, und auch für das erste, um dem zweiten mitzuteilen, wann der Befehl ausgeführt wurde.
Der andere Vorteil gegenüber Pipe-basierten Ansätzen besteht darin, dass stdout und stderr des Befehls immer noch mit TTY-Geräten verbunden sind, sodass die Pufferung nicht beeinträchtigt wird. Beide Bereiche können auch unabhängig voneinander nach oben und unten gescrollt werden (mithilfe screen
des Kopiermodus).
Wenn Sie eine Shell bash
interaktiv mit diesem Skript ausführen, werden Sie feststellen, dass die Eingabeaufforderung im zweiten Fenster angezeigt wird, während die Shell Ihre Eingabe im ersten Fenster liest, da diese Shells ihre Eingabeaufforderung auf stderr ausgeben.
Im Falle von bash
, derEchovon dem, was Sie eingeben, wird auch im zweiten Fenster angezeigt, da dasEchowird von der Shell (readline im Fall von bash
) auch auf stderr ausgegeben. Bei einigen anderen Shells wie ksh93
wird es im ersten Fenster angezeigt (EchoAusgabe durch den Terminalgerätetreiber, nicht durch die Shell), es sei denn, Sie versetzen die Shell mit oder in den emacs
- oder vi
-Modus .set -o emacs
set -o vi
Antwort2
Dies ist eine hässliche Lösung basierend auf dem annotate-output
Skript von DebianANNOTATE-OUTPUT(1). Ich bin nicht sicher, ob das das ist, wonach Sie suchen, aber es könnte ein guter Anfang sein:
#!/bin/bash
readonly col=150 # column to start error output
add_out ()
{
while IFS= read -r line; do
echo "$1: $line"
done
if [ ! -z "$line" ]; then
echo -n "$1: $line"
fi
}
add_err ()
{
while IFS= read -r line; do
printf "%*s %s %s: %s\n" $col "|" "$1" "$line"
done
if [ ! -z "$line" ]; then
printf "%*s %s: %s" $col "$1" "$line"
fi
}
cleanup() { __st=$?; rm -rf "$tmp"; exit $__st; }
trap cleanup 0
trap 'exit $?' 1 2 13 15
tmp=$(mktemp -d --tmpdir annotate.XXXXXX) || exit 1
OUT=$tmp/out
ERR=$tmp/err
mkfifo $OUT $ERR || exit 1
add_out OUTPUT < $OUT &
add_err ERROR < $ERR &
echo "I: Started $@"
"$@" > $OUT 2> $ERR ; EXIT=$?
rm -f $OUT $ERR
wait
echo "I: Finished with exitcode $EXIT"
exit $EXIT
Sie können es mit ./this_script another_script
oder testen command
.
Antwort3
Ich werde versuchen, den folgenden Teil Ihrer Frage zu analysieren:
würde stattdessen ungefähr so aussehen:
~$ irgendein Befehl einige nützliche Ausgabeinformationen | mehr Ausgabe | ERROR: ein Fehler eine weitere Nachricht | FEHLER: ist aufgetreten ~$
Wenn man das, was Sie wollen, aufschlüsseln möchte, wäre das:
1) Der stdout
Stream würde nicht jede Zeile mit einem beenden CR LF
, sondern mit einem '|'-Zeichen. Dies würde die beiden Streams natürlich nicht aneinander ausrichten, und eine Ausrichtung kommt nicht in Frage, da die Länge zukünftiger Zeilen, die dem hinzugefügt werden, vorhergesagt werden müsste stdout
, was natürlich unmöglich ist.
2) Angenommen, wir vergessen die Ausrichtung, würden wir dann einfach das ausgeben, stderr
nachdem es von einer Pipeline verarbeitet wurde, die am Anfang jeder Zeile „ERROR:“ hinzufügt. Ich nehme an, das ist ziemlich einfach, indem man ein einfaches Skript erstellt und sicherstellt, dass das stderr
immer durch dieses Skript ausgegeben wird.
Aber das würde eine Ausgabe wie diese erzeugen:
~$ irgendein Befehl einige nützliche Ausgabeinformationen| mehr Ausgabe| ERROR: ein Fehler eine weitere Nachricht| FEHLER: ist aufgetreten
Das ist nicht wirklich hilfreich, oder? Ich glaube auch nicht, dass es das ist, wonach Sie auch suchen!
Das Problem mit der ursprünglichen Frage ist meiner Meinung nach, dass Sie die serielle Natur jeder an einen Stream angehängten Zeile nicht berücksichtigen, im Zusammenhang mit der Tatsache, dass beide Streams asynchron geschrieben werden können.
Ich glaube, die nächstmögliche Lösung wäre die Verwendung von ncurses
.
Siehe.
[http://www.tldp.org/HOWTO/html_single/NCURSES-Programming-HOWTO/]
[http://invisible-island.net/ncurses/ncurses-intro.html#updating]
Um das zu tun, was Sie wollen, müssen Sie beide Streams puffern und sie kombinieren, um einen dritten Puffer zu erstellen, der Elemente aus beiden Puffern übernimmt. Dann laden Sie den dritten Puffer in den Terminalbildschirm, indem Sie den Terminalbildschirm löschen und ihn jedes Mal neu zeichnen, wenn sich der dritte Puffer ändert. Aber so ncurses
funktioniert es nun einmal, warum also das Rad neu erfinden und nicht von dort aus weitermachen?
In jedem Fall müssten Sieübernehmen Sie die Art und Weise, wie der Terminal-Bildschirm vollständig gemalt wird! Und richten Sie den Text in der neu gedruckten Version des Bildschirms nach Belieben neu aus. Ähnlich wie bei einem Videospiel mit Terminalzeichen.
Ich hoffe, meine Antwort hilft Ihnen dabei, die Einschränkungen dessen zu verdeutlichen, wonach Sie suchen ...
Entschuldigen Sie, dass ich das wiederhole, aber das größte Problem bei dem, was Sie gezeigt haben, ist, wie der „Prozessor“ der stdout
und stderr
Streams die Länge der zukünftigen hinzugefügten Zeilen im Voraus erkennt, um sie richtig auszurichten.