Con bash, come posso inserire l'errore standard in un altro processo?


138

È noto come convogliare lo standard output di un processo in un altro input standard di processi:

proc1 | proc2

Ma cosa succede se voglio inviare l'errore standard di proc1 a proc2 e lasciare l'output standard nella sua posizione corrente? Penseresti che bashavrebbe un comando sulla falsariga di:

proc1 2| proc2

Ma, ahimè, no. C'è un modo per fare questo?


Puoi fare un reindirizzamento così semplice in rc, che è un'altra shell. Ad esempio: proc1 |[2] proc2. Non è carino? Non dentro bashperò.
Rolf

Risposte:


169

C'è anche una sostituzione del processo . Il che rende un processo sostitutivo di un file.
È possibile inviare stderra un file come segue:

process1 2> file

Ma puoi sostituire un processo per il file come segue:

process1 2> >(process2)

Ecco un esempio concreto che invia stderrsia allo schermo che accodato a un file di registro

sh myscript 2> >(tee -a errlog)

23
Questo risponde correttamente alla domanda dichiarata e dovrebbe essere la risposta accettata da @paxdiablo
mmlb

Ci ho provato Non ha funzionato ( weston --help 2> >(less)), e ha rotto il mio guscio, ho dovuto uscire e riconnettermi.
Rolf

1
@Rolf se entrambi weston --help e lesssi aspettano di avere un'interazione tastiera, ma solo 1 di loro riceve, allora si può essere in una situazione imbarazzante. Prova invece a fare test con qualcosa del genere grep. Inoltre potresti scoprire che entrambi gli input da mouse / tastiera stanno andando al secondo comando invece che a weston.
BeowulfNode42,

88

Puoi usare il seguente trucco per scambiare stdout e stderr. Quindi basta usare la normale funzionalità pipe.

( proc1 3>&1 1>&2- 2>&3- ) | proc2

Fornito stdouted stderrentrambi puntati allo stesso posto all'inizio, questo ti darà ciò di cui hai bisogno.

Quello che fa il x>ybit è cambiare l'handle del file xcosì ora invia le sue informazioni a dove l'handle del file ypunta attualmente. Per il nostro caso specifico:

  • 3>&1crea un nuovo handle 3che verrà inviato all'handle corrente1 (stdout originale), solo per salvarlo da qualche parte per il punto finale sotto.
  • 1>&2modifica maniglia 1(stdout) all'uscita della corrente maniglia 2(stderr originale).
  • 2>&3- modifica handle 2 (stderr) all'uscita della corrente maniglia 3(stdout originale) quindi chiude maniglia 3(via -alla fine).

È effettivamente il comando di scambio che vedi negli algoritmi di ordinamento:

temp   = value1;
value1 = value2;
value2 = temp;

3
Qual è il valore di usare 1>&2-qui piuttosto che solo 1>&2? Non capisco perché vorremmo chiudere FD 2, se vogliamo riaprirlo / riassegnarlo immediatamente.
dubiousjim,

1
@dubiousjim, nessun vantaggio in quel caso particolare, sospetto di averlo fatto solo per essere coerente - la chiusura del file handle 3 è una buona idea per liberarlo.
paxdiablo,

Buon punto, @ovgolovin, non riesco a credere che nessuno l'abbia raccolto tra sette mesi da quando ho fatto quella modifica. Risolto secondo il tuo suggerimento.
paxdiablo,

cercando di far funzionare gcc's make (che è colorato sul mio sistema) con questo "(make 3> & 1 1> & 2- 2> & 3-) | less -R" considerando "(ls -al 3> & 1 1> & 2- 2> & 3-) | less -R "funziona come previsto.
non sincronizzato il

Sembra che le tue spiegazioni siano tornate in primo piano per i secondi due reindirizzamenti. 1> & 2- imposta l'handle di file 2 (stderr originale) per gestire 1 (stdout originale) 2> & 3- imposta l'handle di file 3 (stdout copiato) per gestire 2 (stderr originale). Per favore, correggimi se sbaglio. a proposito, immagino che il trattino su 2 sia per impedire che nuovi dati stderr vengano inviati a questo buffer mentre vengono popolati con i dati da stdout.
fabbro

70

Bash 4 ha questa funzione:

Se si usa `| & ', l'errore standard di command1 è collegato all'ingresso standard di command2 attraverso la pipe; è una scorciatoia per 2> & 1 |. Questo reindirizzamento implicito dell'errore standard viene eseguito dopo qualsiasi reindirizzamento specificato dal comando.

zsh ha anche questa funzione.

-

Con altre / vecchie shell, basta inserire questo esplicitamente come

FirstCommand 2> & 1 | OtherCommand


14
Dalla lettura dei documenti, che fa sia errore standard e l'uscita in contrasto con appena stderr, ma è bello sapere. È ora di iniziare a guardare Bash 4, credo.
paxdiablo,

L'attuale manuale di bash dice "Se | & viene utilizzato, errore standard del comando, oltre al suo output standard, è collegato all'input standard del comando2". Questo non è esplicitamente ciò che l'OP vuole.
Peter - Ripristina Monica il

@ PeterA.Schneider: L'OP dice "lascia l'output standard andando nella sua posizione attuale" che può essere ambiguo.
In pausa fino a nuovo avviso.

Non riesco a vedere alcuna ambiguità. Il tuo suggerimento (1) unisce i due flussi. (2) OtherCommandscrive i dati combinati da qualche parte, forse da qualche altra parte. Quindi non sono gli stessi dati e potenzialmente vanno altrove. Si tratta del contrario del desiderio del PO, non è vero?
Peter - Ripristina Monica il

@ PeterA.Schneider: dove altro è la posizione corrente dell'output standard? Se l' proc1output su stdout e su stderr e vuoi che stderr vada allo stdin di proc2(che è dove sta andando lo stdout di proc1), allora la mia risposta lo ottiene. Ho dato all'OP quello che aveva chiesto , forse non quello che intendeva dire chiedere. Qui sta la potenziale ambiguità. L'OP ha accettato la risposta che scambia stdout e stderr e non è ciò che ha chiesto.
In pausa fino a nuovo avviso.

27

Lo scambio è ottimo in quanto risolve il problema. Nel caso non avessi nemmeno bisogno dello stdout originale, puoi farlo in questo modo:

proc1 2>&1 1>/dev/null | proc2

L'ordine è vitale; non vorresti:

proc1 >/dev/null 2>&1 | proc1

Come questo reindirizzerà tutto a /dev/null!


0

Nessuno di questi ha funzionato molto bene. Il modo migliore che ho trovato di fare quello che volevi è:

(command < input > output) 2>&1 | less

Questo funziona solo per i casi in cui commandnon è necessario l'input da tastiera. per esempio:

(gzip -d < file.gz > file) 2>&1 | less

ridurrebbe gli errori di gzip

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.