2012-02-17 11 views
10

2>&1 Przekierowanie w powłoce Bourne przyjmuje wyjście wysyłane do deskryptora pliku 2 (domyślnie, błąd standardowy) i wysyła go zamiast do deskryptora pliku 1 (domyślnie standardowe wyjście).Co robi przekierowanie "2 <i 1" w powłoce Bourne'a?

Ale co robi przekierowanie 2<&1?

Czy wysyła stderr na standardowe wejście?

Moja teoria było to, że wysyłając stdin do stderr (np samo jak 1>&2), ale eksperymentalnie, że nie jest to przypadek:

$ perl -e 'print "OUT\n"; print STDERR "ERR\n"; \ 
    while (<>) { print "IN WAS $_\n";}'   \ 
    > out3 2<&1 
df 
$ cat out3 
ERR 
OUT 
IN WAS df 

Zauważ, że standardowe wyjście i błąd standardowy zarówno poszedł złożyć out3 gdzie stdout został przekierowany.

+0

Na marginesie - było to (niby) ko-bug pracownik wstawił, gdy przez pomyłkę używał '<' zamiast '>'. Po prostu próbuję zrozumieć, co dokładnie robi z tym Shell. Jak na razie SEEMS wygląda tak, jakby był taki sam jak '2> & 1' – DVK

+0

' bash --version'? –

+0

@ user112358132134 - 'GNU bash, wersja 2.03.0 (1) -release (sparc-sun-solaris2.5.1)' – DVK

Odpowiedz

6

Operator <& powiela się „wejście "Deskryptor pliku. Zgodnie z IEEE Std 1003.1-2001 (inaczej Single Unix Specification v3, następca POSIX), powinien to być błąd, aby powiedzieć 2<&1, jeśli 1 nie jest deskryptorem pliku otwartym dla danych wejściowych. Jednak wydaje się, że bash jest leniwy i nie obchodzi go, czy deskryptor pliku jest otwarty na wejście lub wyjście.

więc zarówno 2<&1 i 2>&1 prostu wykonać wywołanie systemowe dup2(1, 2), która kopiuje plik deskryptora 1 do pliku deskryptora 2.

można sprawdzić, uruchamiając polecenie tak, ponieważ przekierowania są wykonywane od lewej do prawej:

sleep 99999 1>/dev/null 2<&1 

Następnie w innym oknie, uruchom lsof na proces sleep. Zobaczysz, że oba deskryptory plików 1 i 2 wskazują na /dev/null. Przykład (na komputerze Mac):

:; ps axww | grep sleep 
8871 s001 R+  0:00.01 grep sleep 
8869 s003 S+  0:00.01 sleep 99999 
:; lsof -p 8869 | tail -2 
sleep 8869 mayoff 1w CHR 3,2  0t0  316 /dev/null 
sleep 8869 mayoff 2w CHR 3,2  0t0  316 /dev/null 
+0

. "powiedzenie" 2 i 1 "w Bashu (szczególnie dla polecenia, które nie czyta ze STDIN), nawet jeśli teoretycznie nie powinno być, poprawne? – DVK

+0

Niezupełnie. '2 <& 1' jest równoważne' 1> i 2'. –

+0

Niestety, to nie wydaje się jibe z mojego testu (patrz pytanie). ERR został przekierowany do OUT, pozornie, nie na odwrót. – DVK

0

Od man bash pod PRZEKIEROWANIE:

Duplicating File Descriptors 
     The redirection operator 

       [n]<&word 

     is used to duplicate input file descriptors. If word 
     expands to one or more digits, the file descriptor 
     denoted by n is made to be a copy of that file descrip‐ 
     tor. If the digits in word do not specify a file 
     descriptor open for input, a redirection error occurs. 
     If word evaluates to -, file descriptor n is closed. If 
     n is not specified, the standard input (file descriptor 
     0) is used. 

więc w przypadku , wydaje się, że 2 (stderr) składa się kopię 1 (stdout). Przetestowałem to w inny sposób: 1<&2 powoduje, że stdout jest kopią stderr.

Więc w programie testowym:

#!/bin/bash 
echo hello 1<&2 

Po uruchomieniu na linii poleceń, cześć jest wyjście do stderr nie stdout

$ ./test > /dev/null 
hello 
$ ./test > /dev/null 2>&1 
$ 
+0

Test testował złe przekierowanie. Wiem, co 2> i 1 robi - proszę uważnie przeczytać pytanie. – DVK

+0

Test w mojej odpowiedzi był dla 1 i 1 upewniały się, że 1 vmpstr

4

Patrząc na kod parsera w źródło Bash, wydaje się, że 2>&1 jest traktowane w taki sam sposób jak 2<&1.

parse.y

| NUMBER LESS_AND NUMBER 
     { 
      redir.dest = $3; 
      $$ = make_redirection ($1, r_duplicating_input, redir); 
     } 
... 
| NUMBER GREATER_AND NUMBER 
     { 
      redir.dest = $3; 
      $$ = make_redirection ($1, r_duplicating_output, redir); 
     } 

Patrząc przez źródła przekierowania redir.c, stałe r_duplicating_input i r_duplicating_output wydają się być traktowane w ten sam sposób. Taki sam jak w funkcji make_redirection w make_cmd.c.

Testowanie za pomocą prostego programu, który drukuje „yay” na standardowe wyjście i „ba” na stderr, mogę potwierdzić wyniki swoich badań:

$ ./a.out > out 2>&1 
$ cat out 
nay 
yay 
$ ./a.out > out 2<&1 
$ cat out 
nay 
yay 
$ ./a.out > out 1>&2 
yay 
nay 
$ cat out 
$ ./a.out > out 1<&2 
yay 
nay 
$ cat out 
$ 
+0

+1, doskonała odpowiedź również – DVK