2009-10-02 8 views
93

Es bien sabido cómo tubería que la salida estándar de un proceso en otros procesos de entrada estándar:Con bash, ¿cómo puedo canalizar el error estándar en otro proceso?

proc1 | proc2 

pero lo que si quiero enviar el error estándar de proc1 a Proc2 y dejar la salida estándar de ir a su actual ¿ubicación? Se podría pensar bash tendría un comando en la línea de:

proc1 2| proc2 

Pero, por desgracia, no. ¿Hay alguna manera de hacer esto?

+0

Puede hacer una redirección tan simple en 'rc', que es otro shell. Por ejemplo: 'proc1 | [2] proc2'. ¿No es agradable? No en 'bash' sin embargo. – Rolf

Respuesta

75

Puede usar el siguiente truco para swapstdout y stderr. Entonces solo usa la funcionalidad de tubería normal.

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

Siempre stdout y stderr tanto señaló la misma posición en la salida, lo que le dará lo que necesita.

Lo que hace:

  • 3>&1 crea un nuevo identificador de archivo 3 que se fija para la corriente 1 (stdout el original) sólo para guardarlo en algún lugar.
  • 1>&2- establece stdout para llegar al controlador de archivo actual 2 (stderr original) luego cierra 2.
  • 2>&3- establece stderr para llegar al controlador de archivo actual 3 (stdout original) y luego cierra 3.

Es efectivamente el comando de cambio que se ve en la clasificación:

temp = value1; 
value1 = value2; 
value2 = temp; 
+3

¿Cuál es el valor de usar '1> & 2-' aquí en lugar de simplemente '1> & 2'? No entiendo por qué querríamos cerrar fd '2', si vamos a reabrir/reasignar inmediatamente. – dubiousjim

+1

@dubiousjim, no hay ventaja en ese caso en particular, sospecho que lo hice solo para ser consistente - cerrando el archivo handle 3 es una buena idea para liberarlo. – paxdiablo

+0

Probablemente haya olvidado '&' en explicaciones de viñeta. – ovgolovin

56

Bash 4 tiene esta característica:

Si `| & 'se usa, el error estándar de command1 se conecta a la entrada estándar de command2 a través de la tubería; es una abreviatura de 2> & 1 |. Esta redirección implícita del error estándar se realiza después de cualquier redirección especificada por el comando.

zsh también tiene esta característica.

-

Con otras cáscaras/de mayor edad, acaba de entrar en este explícitamente como

FirstCommand 2> & 1 | OtherCommand

+11

Al leer los documentos, se obtienen resultados de error estándar * y * en lugar de solo stderr, pero es bueno saberlo. Es hora de empezar a mirar bash 4, creo. – paxdiablo

+0

El manual bash actual dice "If | & se usa, comando error estándar, ** además de su salida estándar, ** está conectado a la entrada estándar del comando2". Esto no es explícitamente lo que quiere el OP. –

+0

@ PeterA.Schneider: El OP dice "deje la salida estándar yendo a su ubicación actual" que puede ser ambigua. –

18

El intercambio es excelente ya que resuelve el problema.En caso de que ni siquiera necesita la salida estándar original, puede hacerlo de esta manera:

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

El orden es vital; que no le gustaría:

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

ya que esto redirigir todo para /dev/null!

108

También hay process substitution. Lo que hace que un proceso sustituya a un archivo.
Puede enviar stderr a un archivo de la siguiente manera:

process1 2> file 

pero se puede sustituir un proceso para el archivo de la siguiente manera:

process1 2> >(process2) 

Aquí está un ejemplo concreto que envía stderr tanto a la pantalla y se agrega a un archivo de registro

sh myscript 2> >(tee -a errlog) 
+14

Esto responde correctamente a la pregunta planteada y debería ser la respuesta aceptada por @paxdiablo – mmlb

+0

Intenté esto. No funcionó ('weston --ayuda 2>> (menos)'), y rompió mi caparazón, tuve que salir y volver a iniciar sesión. – Rolf

Cuestiones relacionadas