2012-02-17 16 views
10

2>&1 il reindirizzamento nella shell Bourne prende l'output inviato a un descrittore di file 2 (per impostazione predefinita, errore standard) e lo invia invece al descrittore di file 1 (per impostazione predefinita un output standard).Cosa fa il reindirizzamento "2 <& 1" nella shell Bourne?

Ma cosa fa il reindirizzamento 2<&1?

Invia stderr a stdin?

La mia teoria è che stava mandando stdin allo stderr (ad esempio stesso di 1>&2), ma sperimentalmente, che non è il caso:

$ 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 

Nota che standard output e l'errore standard sia andato a depositare out3 dove stdout è stato reindirizzato.

+0

Come nota - questo è stato un (presunto) bug di un co lavoratore inserito quando ha erroneamente usato '<' invece di '>'. Sono solo in trincea per capire esattamente cosa sta facendo Shell. Finora, SEMBRA come se fosse uguale a '2> & 1' – DVK

+0

' bash --version'? –

+0

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

risposta

6

L'operatore <& duplica un “input "Descrittore di file. Secondo IEEE Std 1003.1-2001 (aka Single Unix Specification v3, il successore di POSIX), si suppone che sia un errore dire 2<&1 se 1 non è un descrittore di file aperto per l'input. Tuttavia, sembra che bash sia pigro e non interessa se il descrittore di file è aperto per l'input o per l'output.

Così sia 2<&1 e 2>&1 semplicemente eseguire la chiamata di sistema dup2(1, 2), quale file copie descrittore 1 nel descrittore di file 2.

Puoi controllare eseguendo un comando come questo, dal momento redirezioni vengono eseguite da sinistra a destra:

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

Poi in un'altra finestra, eseguire lsof sul processo sleep. Vedrai che entrambi i descrittori di file 1 e 2 puntano a /dev/null. Esempio (sul mio 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

Quindi, tu 'say' 2 <& 1' è ** efficacemente ** equivalente a '2> & 1' in Bash (specialmente per comando che non legge da STDIN), anche se teoricamente non dovrebbe essere, corretto? – DVK

+0

Non proprio. '2 <& 1' equivale a' 1> & 2'. –

+0

scusa, non sembra che strambichi il mio test (vedi la domanda). ERR è stato reindirizzato su OUT, apparentemente, non viceversa – DVK

0

Da man bash sotto RIDIREZIONE:

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. 

Quindi, nel caso di , sembra che 2 (stderr) è fatto per essere una copia di 1 (stdout). L'ho provato con il contrario stdout stdout stderr.

Così in un programma di test:

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

Quando eseguito sulla linea di comando, ciao è uscita stderr non stdout

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

Il test ha verificato il reindirizzamento sbagliato. So cosa fa 2> & 1 - per favore leggi attentamente la domanda – DVK

+0

Il test nella mia risposta era per 1 & 1 si stava solo assicurando che 1 <& 2 effettivamente duplicasse lo stderr – vmpstr

4

Guardando il codice parser nel sorgente per Bash, sembra che 2>&1 è trattata nello stesso modo come 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); 
     } 

Guardando attraverso la fonte reindirizzamento redir.c, le costanti r_duplicating_input e r_duplicating_output sembrano essere trattati allo stesso modo. Come nella funzione make_redirection in make_cmd.c.

Test con un semplice programma che stampa "yay" per stdout e "no" a stderr, posso confermare i risultati del test:

$ ./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, ottima risposta pure – DVK