2013-06-08 2 views
11

che sto leggendo su reindirizzamento dei dati per /dev/null e così ho provato un semplice test:Come funziona cmd>/dev/null 2> & 1?

ping a.b.c # which results in an address not found 

Se provo questo:

ping a.b.c > /dev/null # prints the same error message as the one above 

Tuttavia, se faccio questo:

ping a.b.c > /dev/null 2>&1 # The error message is gone 

L'ultima soluzione è la soluzione desiderata, ma cosa sta succedendo con questo 2>&1? Le mie ricerche finora suggeriscono che 2 rappresenta stderr e 1 rappresenta stdout. Quindi, se lo leggo in questo modo, sembra che sto creando un file stderr e reindirizzando stdout ad esso?

In tal caso, cosa fa il comando & in questo comando?

+3

e permette di bash sanno che '1' non è un nome di file, ma' stderr'. Btw non devi usare '|', 'ping a.b.c 2>/dev/null' o' ping a.b.c &>/dev/null' dovrebbe farlo. – Jokester

+0

@jokester grazie!Quindi se '1' non è un nome di file, che cos'è? Solo memoria? –

+0

Dovresti ricevere "/ dev/null: autorizzazione negata", dato che stai cercando di eseguire '/ dev/null' come comando. Dovrebbe essere '>/dev/null', non' |/Dev/null'. –

risposta

12

Hai ragione, 2 è STDERR, 1 è STDOUT. Quando fai 2>&1 stai dicendo: "stampa a STDOUT (1) le cose che andrebbero a STDERR (2)". E prima, hai detto che il tuo STDOUT andrebbe a /dev/null. Pertanto, nulla è visto. Negli esempi 1 e 2 viene visualizzato il messaggio di output perché viene stampato su STDERR, in quanto un reindirizzamento regolare reindirizza solo STDOUT.

E quando lo fai il reindirizzamento, non si sta creando un STDERR, i processi hanno sempre un STDERR e un STDOUT momento della loro creazione.

+3

@nkon Se vuoi, puoi effettivamente _vedere_ quali descrittori di file sono collegati a un processo. Per farlo, trova il pid, ad es., 'Pgrep firefox'. Quindi 'ls -l/proc//fd' - noti che i file fds sono effettivamente rappresentati come collegamenti simbolici nella directory! Trovo ancora tutto affascinante e ho eseguito Debian dal 2002. – cmt

0

Prendere in considerazione il seguente codice che stampa la parola "stdout" su stdout e la parola "stderror" su stderror.

$ (echo "stdout"; echo "stderror" >&2) 
stdout 
stderror 

Nota che l'operatore '&' dice a bash che 2 è un descrittore di file (che punta al stderr) e non un nome di file. Se abbiamo omesso lo '&', questo comando dovrebbe stampare stdout sullo stdout e creare un file denominato "2" e scrivere stderror lì.

Sperimentando con il codice precedente, è possibile vedere esattamente come funzionano gli operatori di reindirizzamento. Ad esempio, cambiando il file quale dei due descrittori 1,2, viene reindirizzato a /dev/null le seguenti due righe di codice eliminano tutto dallo stdout e tutto da stderror rispettivamente (stampa ciò che rimane).

$ (echo "stdout"; echo "stderror" >&2) 1>/dev/null 
stderror 
$ (echo "stdout"; echo "stderror" >&2) 2>/dev/null 
stdout 

Ora, ci avviciniamo al nocciolo della questione (sostituendo il mio esempio per il vostro), perché

(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1 

produce nessuna uscita? Per capirlo veramente, consiglio vivamente di leggere questo webpage on file descriptor tables. Supponendo che tu abbia fatto quella lettura, possiamo procedere. Nota che i processi di Bash vanno da sinistra a destra; quindi Bash vede prima >/dev/null (che è lo stesso di 1>/dev/null) e imposta il descrittore di file 1 in modo che punti a/dev/null invece dello stdout. Fatto ciò, Bash si sposta quindi verso destra e vede 2>&1.Questo imposta il descrittore di file 2 in modo che punti allo stesso file come descrittore di file 1 (e non al descrittore di file 1 stesso !!!! (vedere this resource on pointers per ulteriori informazioni.) Poiché il descrittore di file 1 punta a/dev/null e descrittore di file 2 punti allo stesso file come file descrittore 1, il descrittore di file 2 ora indica anche/dev/null. Pertanto sia il file descrittori indicano/dev/null, e questo è il motivo per cui nessuna uscita viene reso.


per testare se si capisce davvero il concetto, provate ad indovinare l'uscita quando si passa l'ordine di reindirizzamento:

(echo "stdout"; echo "stderror" >&2) 2>&1 >/dev/null 

stderror

Il ragionamento è che la valutazione da sinistra a destra, Bash vede 2> & 1, e quindi imposta il file descrittore 2 al punto nello stesso posto come file descrittore 1, cioè stdout. Quindi imposta il descrittore di file 1 (ricorda che>/dev/null = 1>/dev/null) per puntare a>/dev/null, cancellando così tutto ciò che di solito verrebbe inviato allo standard out. Quindi tutto ciò che ci rimane è quello che non è stato inviato a stdout nella sottotitola (il codice tra parentesi) - cioè "stderror". La cosa interessante da notare è che anche se 1 è solo un puntatore allo stdout, il reindirizzamento del puntatore 2 a 1 tramite 2>&1 NON forma una catena di puntatori 2 -> 1 -> stdout. Se così fosse, come risultato del reindirizzamento di 1 a/dev/null, il codice 2>&1 >/dev/null darebbe la catena di puntatori 2 -> 1 ->/dev/null, e quindi il codice non genererebbe nulla, in contrasto con ciò che abbiamo visto sopra .


Infine, mi piacerebbe notare che c'è un modo più semplice per fare questo:

Dalla sezione 3.6.4 here, vediamo che siamo in grado di utilizzare l'operatore &> per reindirizzare sia stdout e stderr. Così, per reindirizzare sia lo stderr e stdout uscita di qualsiasi comando per \dev\null (che cancella l'uscita), c'è sufficiente digitare $ command &> /dev/null o in caso di mio esempio:

$ (echo "stdout"; echo "stderror" >&2) &>/dev/null 

takeaway chiave:

  • descrittori di file si comportano come i puntatori (anche se i descrittori di file non sono le stesse come puntatori di file)
  • Reindirizzamento di un descrittore di file "a" in un file des criptor "b" che punta al file "f", fa in modo che il descrittore di file "a" punti allo stesso punto del descrittore di file b - file "f". NON forma una catena di puntatori a -> b -> f
  • A causa di quanto sopra, l'ordine è importante, 2>&1 >/dev/null è! = >/dev/null 2>&1. Uno genera output e l'altro no!

avere finalmente uno sguardo a queste grandi risorse:

Bash Documentation on Redirection, An Explanation of File Descriptor Tables, Introduction to Pointers