Vervielfältigung ist hier wirklich der wichtige Teil.
Mal sehen, wohin die Dateideskriptoren vor der Umleitung gehen. Dies ist normalerweise das aktuelle Terminal, zB:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Wenn wir jetzt ls -l
ohne Umleitung anrufen , gehen Ausgabe- und Fehlermeldungen zu meinem Endgerät unter /dev/pts/1
.
Wenn wir das zuerst STDOUT
in eine Datei umleiten ( ls -l > dirlist
), sieht es so aus:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Wenn wir dannSTDERR
zu einem Duplikat von STDOUT
's file descriptor ( ls -l > dirlist 2>&1
) umleiten , gehen wir STDERR
zu einem Duplikat von /home/bon/dirlist
:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
Wenn wir zuerstSTDERR
zu einem Duplikat von STDOUT
's file descriptor ( ls -l 2>&1
) umleiten würden :
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
und dann STDOUT
zu einer Datei ( ls -l 2>&1 > dirlist
), würden wir dies bekommen:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Hier geht STDERR
es noch zum Terminal.
Sie sehen, die Reihenfolge in der Manpage ist korrekt.
Umleitung testen
Jetzt können Sie das selbst testen. Mit sehen ls -l /proc/$$/fd/
Sie, wo STDOUT
(mit fd 1) und STDERR
(mit fd 2) der aktuelle Prozess abläuft:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Lassen Sie uns ein kleines Shell-Skript erstellen, das zeigt, wohin Ihre Dateideskriptoren zeigen. Auf diese Weise erhalten wir beim Aufrufen immer den Status ls
, einschließlich der Umleitung von der aufrufenden Shell.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(Mit CtrlDsenden Sie ein Dateiende und beenden so das cat
Lesen des Befehls von STDIN
.)
Rufen Sie nun dieses Skript mit verschiedenen Kombinationen von Umleitungen auf:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
Sie sehen, dass die Dateideskriptoren 1 (für STDOUT
) und 2 (für STDERR
) variieren. Zum Spaß könnten Sie auch umleiten STDIN
und das Ergebnis sehen:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Frage an den Leser: Wo steht der Dateideskriptor 255? ;-))