Tuberías stdout y stderr en bash?

156

Parece que las versiones más nuevas de bash tienen el &>operador, que (si lo entiendo correctamente), redirige tanto stdout como stderr a un archivo (se &>>agrega al archivo, como Adrian aclaró).

¿Cuál es la forma más sencilla de lograr lo mismo, pero en lugar de utilizar otro comando?

Por ejemplo, en esta línea:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError

Me gustaría que grep coincida con el contenido tanto en stdout como en stderr (efectivamente, combínelos en una sola secuencia).

Nota : esta pregunta es sobre tuberías, no sobre redireccionamientos, por lo que no es un duplicado de la pregunta que actualmente está marcada como duplicado.

Andrew Ferrier
fuente
Consulte la segunda respuesta ( stackoverflow.com/a/637834/1129642 ) en la pregunta vinculada para conocer la forma correcta de canalizar stdout y stderr. No hay necesidad de otra pregunta.
Marki555
44
@triplee No es un duplicado exacto, ¿verdad? ¿Pipe vs redirigir a archivo?
Benjamin W.
@BenjaminW Hay al menos una respuesta allí que resuelve ambos escenarios, aunque no es la respuesta aceptada. Esta es una pregunta bastante común, por lo que probablemente podríamos encontrar un duplicado mejor, o pedirle a un moderador que las combine, o incluso, en el peor de los casos, crear un canónico completamente nuevo para este tema. Si encuentra un mejor engañado, propongalo por todos los medios. Gracias por adelantado.
tripleee
12
@tripleee Resuelve, sí, pero ninguna de las respuestas utiliza el |&acceso directo, que creo que es, con mucho, la solución más conveniente para "redirigir stdout y stderr a una tubería".
Benjamin W.
3
Esto no es un duplicado de la pregunta vinculada, y no estaba claro que la respuesta de Marko hizo lo que quería. Además, no menciona | &. Votación para reabrir.
Martin Bonner apoya a Mónica

Respuestas:

163

(Tenga en cuenta que se &>>file agrega a un archivo mientras &>redirige y sobrescribe un archivo previamente existente).

Para combinar stdouty stderrredirigiría el último al primero usando 2>&1. Esto redirige stderr (descriptor de archivo 2) a stdout (descriptor de archivo 1), por ejemplo:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std
stderr
$

stdoutva a stdout, stderrva a stderr. grepsolo ve stdout, por lo tanto stderrimprime en la terminal.

Por otra parte:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std
$

Después de escribir en stdout y stderr, 2>&1redirige stderr de nuevo a stdout y grepve ambas cadenas en stdin, por lo tanto, filtra ambas.

Puede leer más sobre la redirección aquí .

Con respecto a su ejemplo (POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError

o, usando >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError
Adrian Frühwirth
fuente
Gracias por la aclaración sobre &>>. He corregido mi pregunta.
Andrew Ferrier
18
Agregué su ejemplo a mi respuesta, en caso de que no fuera obvio en base a mis ejemplos dados. Como nota al margen, también puede usar el específico de bash en |&lugar de 2>&1 |.
Adrian Frühwirth
13
Nota al |&margen sobre el acceso directo propuesto por @ AdrianFrühwirth para futuros lectores: esta función solo es compatible con la bashversión 4+. Si está utilizando 3 o menos, debe seguir 2>&1 |.
tomocafé
3
La redirección de Bash se explica muy bien aquí . @ AdrianFrühwirth ha hecho un buen trabajo, el enlace pegado va aún más lejos. A veces, desearía que la documentación oficial de Bash fuera tan buena.
David Andreoletti
112

Bash tiene una abreviatura para 2>&1 |, a saber |&, qué tuberías son stdout y stderr (consulte el manual ):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

Esto se introdujo en Bash 4.0, consulte las notas de la versión .

Benjamin W.
fuente
Gracias por agregar esto para completar. Voy a mantener la otra respuesta correcta ya que muchas personas todavía usan bash pre-4.0. Pero esto es útil.
Andrew Ferrier
9
Quizás lo más notable es que el Bash que se incluye en macOS es demasiado antiguo para admitir esto.
Flimm
@Flimm pero el zsh no lo es
Trenton
1
Como ksh usa | & para coproc, parece una mala elección para una taquigrafía innecesaria. Odio ver líneas con una pila de duplicaciones y redireccionamientos tanto como el próximo tipo, pero hay algo que decir por ser explícito ... y me disculpo porque este comentario no agrega mucho. Solo quería expresar disgusto por la taquigrafía sin rechazar una respuesta realmente útil, porque es bueno que la gente vea esto. No sabía esto, así que gracias por avisarme.
Paul Hodges
@PaulHodges Estoy de acuerdo en que no es portátil, principalmente me gusta usarlo para sesiones interactivas de Bash para evitar escribir demasiado.
Benjamin W.