Perché reindirizzare l'output su 2> & 1 e 1> & 2?


36

Mi sono imbattuto in diversi comandi che usano 2>&1e 1>&2, ma non riesco proprio a capirlo allo scopo di usarlo e quando dovrei usarlo.

Quello che ho capito

So che 1rappresenta lo standard out e 2rappresenta l'errore standard. Comprendo che 2>&1combina l'uscita 2di 1e viceversa.

Quello che non capisco

  1. Quando dovrei usarlo?
  2. A quale scopo serve?

Risposte:


39

A volte vuoi reindirizzare sia stdout che stderr nella stessa posizione, Questo è quando >&viene usato - punta un descrittore di file a un altro.


Ad esempio, se si desidera scrivere sia stdout che stderr nello stesso file (sia esso /dev/nullo output.txt), è possibile reindirizzarli separatamente, con

app 1>/dev/null 2>/dev/null

oppure puoi reindirizzare un descrittore di file al file e l'altro descrittore di file nel primo:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

Nel primo esempio, 2>&1indica il descrittore di file n. 2 verso il punto 1 già indicato. Il secondo esempio ottiene lo stesso, iniziando invece con stderr.

Come altro esempio, ci sono casi in cui stdout (descrittore di file n. 1) punta già alla posizione desiderata, ma non è possibile fare riferimento ad essa per nome (può essere associato a una pipe, un socket o simili). Ciò si verifica spesso quando si utilizza l'espansione del processo (gli operatori ` `o $( )), che normalmente acquisisce solo stdout, ma è possibile includere in esso stderr. In questo caso, useresti anche >&per indicare stderr a stdout:

out=$(app 2>&1)

Un altro esempio comune è un cercapersone o grepun'utilità simile, poiché la pipe funziona |normalmente solo su stdout, reindirizzare stderr a stdout prima di usare la pipe:

app 2>&1 | grep hello

Come sapere quale di 2>&1o 1>&2è corretto? Il descrittore di file già impostato va a destra >&e il descrittore di file che si desidera reindirizzare va a sinistra. ( 2>&1significa "punta il descrittore di file n. 2 al descrittore di file n. 1").


Alcune shell hanno scorciatoie per reindirizzamenti comuni; ecco alcuni esempi da Bash:

  • 1> può essere ridotto a solo >

  • 1>foo 2>&1a >&fooo&>foo

  • 2>&1 | program a |& program


Non avevo idea che fare app 1>/dev/null 2>&1avrebbe significato che 2> & 1 avrebbero indicato il file a cui 1 stava già reindirizzando. Presumo che potrei fare altrettanto facilmente app > /dev/null &>?
PeanutsMonkey,

Sto facendo fatica a capire the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left. Cosa intendi con il descrittore di file già impostato? Cosa significa il diritto di?
PeanutsMonkey,


Mi dispiace, a meno che tu non abbia intenzione di insegnarmi indicazioni, non seguo l'affermazione che hai fatto come precedentemente notato.
PeanutsMonkey,

1
Prendi ogni descrittore di file reindirizzare uno alla volta, da sinistra a destra, e applica queste regole in quell'ordine. Se prima dirigi stdout su un file, quindi reindirizza stderr verso dove ci sta puntando ora stdout, quindi stderr e stdout andranno allo stesso file. Se si scambiassero quei due reindirizzamenti, si otterrebbero risultati diversi (reindirizzare stderr su dove sta andando stdout ora , quindi spostare stdout per puntare a un altro file, mentre stderr continua dove è stato puntato).
Jason,

2

Una situazione in cui è necessaria è quando si desidera visualizzare l' straceoutput in un cercapersone. stracestampa il suo output su errore standard e le pipe generalmente collegano l' output standard all'input standard, quindi devi usare il reindirizzamento:

strace -p $pid 2>&1 | less

Cosa intendi con pipes generally connect standard output to standard input?
PeanutsMonkey,

2
Voglio dire che pipe ( |) prende l'output standard del primo comando e lo collega all'input standard del secondo comando.
jpalecek,

2

A volte si desidera reindirizzare entrambi stdout( 1) e stderr( 2) nella stessa posizione ( /dev/null, ad esempio). Un modo per raggiungere questo obiettivo sarebbe:

$ program 1>/dev/null 2>/dev/null

Ma molte persone accorciano questo reindirizzando stderra stdoutcon 2>&1:

$ program 1>/dev/null 2>&1

Una versione ancora più breve è:

$ program >&- 2>&-

1

2: È per quando si avrà un output proveniente sia dall'errore standard sia dall'output standard e si desidera che siano composti in un'unica stringa.

1: quando si desidera manipolare l'output sia dell'errore standard sia dell'output standard.


Cosa intendi con manipolare? La mia comprensione è che qualsiasi cosa reindirizzata >2viene inviata a / dev / null. O ho sbagliato completamente?
PeanutsMonkey,

Questo non è corretto Con manipolazione intendo dire pipe a grep o qualcosa di simile. Vedi qui per un esempio.
soandos,

0

Lo uso per iniziare un lavoro distaccato:

someProgram 2>&1 >& my.log &

quindi posso disconnettermi e someProgram sarà ancora in esecuzione. La funzionalità è fornita da GNU Screen, da tmux e da alcuni altri programmi, ma qui si ottiene senza alcuna dipendenza esterna.


1
Funziona solo finché non viene inviato SIGHUP al programma. Migliore utilizzo nohupo disownin tali casi.
slhck,

@slhck: ok. Ma se non invio SIGHUP al programma, nessuno lo farà, giusto?
Adobe,

No, il terminale di controllo avviserà i processi di disconnessione con SIGHUP. In pratica, se si esegue una shell remota tramite SSH e si esce, anche il processo morirà, ad esempio.
slhck,

@slhck: non può essere vero: lo uso da un paio di anni - esco da ssh e il processo è ancora in esecuzione.
Adobe,

Dovrò cercare questo in modo più dettagliato, ma mettere semplicemente i programmi in background non ha funzionato per me in tutti i casi e sicuramente non funziona nemmeno sul mio computer locale. Sembra che anche Zsh e Bash si comportino diversamente qui.
slhck,

0

Immagina che ci sia una directory chiamata trycon questi tre file:file file1 and file2.

Ora esegui questo comando:

cat file file1 file2 file3

I primi tre file si aprono ma catgenerano un errore durante l'apertura del quarto poiché non esiste.

Ora esegui:

cat file file1 file2 file3 1>outfile 2>&1

Non vedrete alcun output sullo schermo: In primo luogo 1>outfilesarà reindirizzare l'output del comando per outfilee poi sarà reindirizzare ( 2>&1) l'errore gettato durante il tentativo di aprire file3a outfile.

1>&2 funziona in modo simile e reindirizza il flusso di errori all'output standard.

Spero che sia di aiuto!


0

Scenario alternativo: i comandi del terminale mostrano l'output in un altro terminale

Utilizzare il ttycomando in ciascun terminale per identificarli:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Supponendo che questi TTY, per reindirizzare il primo stdout al secondo, eseguirlo nel primo terminale:

exec 1>/dev/pts/1

Nota: ora ogni output di comando verrà mostrato su pts / 1

Per ripristinare il comportamento predefinito stdout di pts / 0:

exec 1>/dev/pts/0

Guarda questo video per una dimostrazione.


0

Il caso del reindirizzamento di stderr su stdout è già stato trattato qui (ad es. Usarlo per filtrare i messaggi di errore (grep)).

L'altro caso sta reindirizzando stdout a stderr. Un caso d'uso comune (almeno per me) è di inviare avvisi / messaggi di errore stampati con "echo" (nei miei script shell) allo stderr (in modo che possano attirare più facilmente l'attenzione dell'utente).

Per esempio,

echo "file \"${file\" does not exist..." 1>&2
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.