Powielanie jest tutaj naprawdę ważną częścią.
Zobaczmy, dokąd zmierzają deskryptory plików przed przekierowaniem. Zwykle jest to aktualny terminal, np .:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Teraz, jeśli dzwonimy ls -l
bez przekierowania, komunikaty wyjściowe i komunikaty o błędach trafiają do mojego terminala pod /dev/pts/1
.
Jeśli najpierw przekierujemy STDOUT
do pliku ( ls -l > dirlist
), wygląda to tak:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Kiedy następnie przekierować STDERR
do dwóch egzemplarzach z STDOUT
„s deskryptorze pliku ( ls -l > dirlist 2>&1
), STDERR
przechodzi do duplikat /home/bon/dirlist
:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
Jeśli najpierw przekierowalibyśmy STDERR
do duplikatu STDOUT
deskryptora pliku ( ls -l 2>&1
):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
a następnie STDOUT
do file ( ls -l 2>&1 > dirlist
), otrzymalibyśmy to:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Tutaj STDERR
nadal jedzie do terminala.
Widzisz, kolejność na stronie podręcznika jest poprawna.
Testowanie przekierowania
Teraz możesz to sprawdzić samodzielnie. Używając ls -l /proc/$$/fd/
, zobaczysz, gdzie STDOUT
(z fd 1) i STDERR
(z fd 2) idą do bieżącego procesu:
$ 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
Utwórzmy mały skrypt powłoki, który pokazuje, gdzie są skierowane deskryptory plików. W ten sposób zawsze otrzymujemy stan podczas połączenia ls
, w tym wszelkie przekierowania z powłoki wywołującej.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(Za pomocą CtrlDwysyłasz plik na końcu pliku, a więc przerywasz cat
czytanie komendy od STDIN
.)
Teraz wywołaj ten skrypt z różnymi kombinacjami przekierowań:
$ ./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
Widać, że deskryptory plików 1 (dla STDOUT
) i 2 (dla STDERR
) różnią się. Dla zabawy możesz również przekierować STDIN
i zobaczyć wynik:
$ ./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
(Pytanie do czytelnika: Gdzie wskazuje deskryptor pliku 255? ;-))