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
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
@jokester grazie!Quindi se '1' non è un nome di file, che cos'è? Solo memoria? –
Dovresti ricevere "/ dev/null: autorizzazione negata", dato che stai cercando di eseguire '/ dev/null' come comando. Dovrebbe essere '>/dev/null', non' |/Dev/null'. –