In welchen Stream schreibt Bash seine Eingabeaufforderung?

8

Ich versuche, alle Ausgaben von Bash (Eingabeaufforderung, Benutzereingabe, Ergebnisse) in eine Datei umzuleiten

Beispiel:

/bin/bash > file.txt 2>&1

Ich dachte, das würde funktionieren, aber ich bekomme keine Aufforderung. Kann mir jemand sagen, was ich falsch mache?

Gilles 'SO - hör auf böse zu sein'
quelle

Antworten:

9

Bash gibt die Eingabeaufforderung nur im interaktiven Modus aus. Das heißt, es wird normalerweise an das Terminal ausgegeben (/ dev / tty unter Linux). Das ist weder / dev / stdout noch / dev / stdin :)

Jetzt bin ich mir nicht sicher, aber ich kann mir vorstellen, dass Bash einen eingeschränkten interaktiven Modus zulässt, wenn es keine voll funktionsfähige Tty gibt. In diesem Fall würde ich erwarten, dass die Eingabeaufforderung in stdout geschrieben wird. Das habe ich nicht getestet.

Schöner Proof of Concept:

(for a in some set of words; do echo $a > /dev/tty; done) 2>&1 > /dev/null

gibt nur 1..10 aus, als ob es keine Umleitung gäbe. Wie bei der Eingabeaufforderung wird die Ausgabe direkt an das Terminal gesendet (was fehlschlägt, wenn es keine gibt).

TIPP: Wenn Sie möchten, dass alles gesammelt wird, schauen Sie sich das an

sehe sehen
quelle
Es wurden Hinweise hinzugefügt, wie möglicherweise mehr Bash-Ausgabe in eine Pipe gebracht werden kann
siehe
seqist ein sehr ungewöhnlicher externer Befehl und sollte nicht auf diese Weise verwendet werden. Wenn Sie verwenden bash, tun Sie etwas wie for x in {1..10}oder for ((x=1; x<=10; x++))stattdessen.
Chris Down
@ Chris: Guter Punkt, danke für das Heads-up
sehe
2

Um zu glauben, bashdass es sich im interaktiven Modus befindet (obwohl stdoutes nicht an ein Terminal gesendet wird), können Sie den bereits erwähnten scriptBefehl verwenden.

(
exec 1> >(tee bashlog.txt) 2>&1
script -q /dev/null /bin/bash -l
)

# alternative without script command
(
# bash: no job control in this shell
exec 1> >(tee bashlog.txt) 2>&1
/bin/bash -il
)

quelle
2

Die Eingabeaufforderung wird in stderr geschrieben, wie das Fachwerk (hier unter Solaris) zeigt:

$ truss -ft write -p 10501
10501:  write(2, " d", 1)               = 1
10501:  write(2, " a", 1)               = 1
10501:  write(2, " t", 1)               = 1
10501:  write(2, " e", 1)               = 1
10501:  write(2, "\n", 1)               = 1
10521:  write(1, " S a t u r d a y ,   S e".., 46)  = 46
10501:      Received signal #18, SIGCLD [caught]
10501:        siginfo: SIGCLD CLD_EXITED pid=10521 status=0x0000
10501:  write(2, " $  ", 2)             = 2
jlliagre
quelle
1

Der einfachste Weg wäre es

bash -i >/tmp/logfile 2>&1

Bash schreibt alles in /tmp/logfileBefehle und führt sie weiter aus, während Sie sie eingeben, aber im Terminal wird nichts angezeigt. Sie können es beenden, sobald Sie Ihre Terminalsitzung beenden - indem Sie Ctrl+ drücken Doder tippen exit.

Beachten Sie, dass, wenn Sie dasselbe ohne stderrUmleitung ausführen , nur die Begrüßungsnachricht in der Datei protokolliert wird. Der Rest funktioniert in Ihrem aktuellen Terminal. Die Antwort auf Ihre Frage zum Stream, an den Bash seine Eingabeaufforderung (und alle folgenden Befehle) ausgibt, scheint also zu lauten: stderr .

Oh ja, und der -iParameter zwingt bash einfach dazu, im interaktiven Modus ausgeführt zu werden. Hör nicht auf diese Leute - dafür brauchst du keine Zaubertricks;)

rozcietrzewiacz
quelle
+1 für die Verwendung <sub>zum Formatieren. Ich habe heute gerade etwas Neues gelernt. : D
Chris K