Pregunta ¿Cómo pipetear stderr, y no stdout?


Tengo un programa que escribe información para stdout y stderry necesito grep a través de lo que viene stderr, sin tener en cuenta stdout.

Por supuesto puedo hacerlo en 2 pasos:

command > /dev/null 2> temp.file
grep 'something' temp.file

pero preferiría poder hacer esto sin archivos temporales. ¿Hay algún truco de tubería inteligente?


760
2018-02-26 15:53


origen


Respuestas:


Primero redirige stderr a stdout: la tubería; luego redireccione stdout a /dev/null (sin cambiar dónde va stderr):

command 2>&1 >/dev/null | grep 'something'

Para obtener más información sobre la redirección de E / S en toda su variedad, consulte el capítulo sobre Redirecciones en el manual de referencia de Bash.

Tenga en cuenta que la secuencia de redirecciones de E / S se interpreta de izquierda a derecha, pero las canalizaciones se configuran antes de que se interpreten las redirecciones de E / S. Las descripciones de archivos como 1 y 2 son referencias para abrir descripciones de archivos. La operacion 2>&1 hace que el descriptor de archivo 2 aka stderr se refiera a la misma descripción de archivo abierto que el descriptor de archivo 1 al que se refiere stdout (ver dup2() y open()) La operacion >/dev/null luego cambia el descriptor de archivo 1 para que haga referencia a una descripción de archivo abierto para /dev/null, pero eso no cambia el hecho de que el descriptor de archivo 2 se refiere a la descripción de archivo abierto al que apuntaba el descriptor de archivo 1, es decir, el conducto.


902
2018-02-26 15:55



O para intercambiar la salida de stderr y stdout sobre el uso: -

command 3>&1 1>&2 2>&3

Esto crea un nuevo descriptor de archivo (3) y lo asigna al mismo lugar que 1 (stdout), luego asigna fd 1 (stdout) al mismo lugar que fd 2 (stderr) y finalmente asigna fd 2 (stderr) al mismo colocar como fd 3 (stdout). Stderr ahora está disponible como stdout y stdout antiguo conservado en stderr. Esto puede ser excesivo, pero con suerte brinda más detalles sobre los descriptores de archivos bash (hay 9 disponibles para cada proceso).


311
2018-03-04 18:18



En Bash, también puede redireccionar a una subcadena usando sustitución de procesos:

command > >(stdlog pipe)  2> >(stderr pipe)

Para el caso que nos ocupa:

command 2> >(grep 'something') >/dev/null

172
2018-02-09 19:14



Combinando la mejor de estas respuestas, si lo haces:

command 2> >(grep -v something 1>&2)

... entonces todo stdout se conserva como stdout y todo stderr se conserva como stderr, pero no verá ninguna línea en stderr que comience con la cadena "algo".

Esto tiene la ventaja única de no revertir o descartar stout y stderr, ni arrastrarlos juntos, ni usar ningún archivo temporal.


138
2018-04-10 21:05



Es mucho más fácil visualizar cosas si piensas en lo que realmente está pasando con "redirecciones" y "tuberías". Los redireccionamientos y las canalizaciones en bash hacen una cosa: modificar dónde apuntan los descriptores de archivo de proceso 0, 1 y 2 (ver / proc / [pid] / fd / *).

Cuando un tubo o "|" el operador está presente en la línea de comando, lo primero que ocurre es que bash crea un fifo y apunta el FD 1 del comando del lado izquierdo a este fifo, y apunta el FD 0 del comando del lado derecho al mismo fifo.

A continuación, se evalúan los operadores de redirección para cada lado de izquierda a derecha, y la configuración actual se usa cada vez que se produce una duplicación del descriptor. Esto es importante porque dado que el tubo se configuró primero, el FD1 (lado izquierdo) y el FD0 (lado derecho) ya han cambiado de lo que normalmente podrían haber sido, y cualquier duplicación de estos reflejará ese hecho.

Por lo tanto, cuando escribe algo como lo siguiente:

command 2>&1 >/dev/null | grep 'something'

Esto es lo que sucede, en orden:

  1. se crea una tubería (fifo). El "comando FD1" apunta a esta tubería. "grep FD0" también apunta a esta tubería
  2. El "comando FD2" apunta hacia donde actualmente apunta el "comando FD1" (el conducto)
  3. "comando FD1" apunta a / dev / null

Por lo tanto, toda la salida que el "comando" escribe en su FD 2 (stderr) hace su camino hacia la tubería y es leída por "grep" en el otro lado. Toda la salida que "comando" escribe en su FD 1 (stdout) hace su camino a / dev / null.

Si, en cambio, ejecuta lo siguiente:

command >/dev/null 2>&1 | grep 'something'

Esto es lo que sucede:

  1. se crea una tubería y se señalan "comando FD 1" y "grep FD 0"
  2. "comando FD 1" apunta a / dev / null
  3. El "comando FD 2" apunta hacia donde actualmente FD 1 apunta (/ dev / null)

Entonces, todos stdout y stderr de "comando" van a / dev / null. Nada va a la tubería y, por lo tanto, "grep" se cerrará sin mostrar nada en la pantalla.

También tenga en cuenta que los redireccionamientos (descriptores de archivos) pueden ser de solo lectura (<), solo escritura (>) o de lectura y escritura (<>).

Una nota final. Si un programa escribe algo en FD1 o FD2, depende completamente del programador. Una buena práctica de programación dicta que los mensajes de error deben ir a FD 2 y la salida normal a FD 1, pero a menudo encontrará una programación descuidada que mezcla los dos o ignora la convención.


82
2017-08-20 18:09



¿Estás usando bash? Si es así:

command >/dev/null |& grep "something"

http://www.gnu.org/software/bash/manual/bashref.html#Pipelines


28
2018-04-18 21:56



Para aquellos que desean redirigir stdout y stderr permanentemente a los archivos, grep on stderr, pero mantengan el stdout para escribir mensajes en un tty:

# save tty-stdout to fd 3
exec 3>&1
# switch stdout and stderr, grep (-v) stderr for nasty messages and append to files
exec 2> >(grep -v "nasty_msg" >> std.err) >> std.out
# goes to the std.out
echo "my first message" >&1
# goes to the std.err
echo "a error message" >&2
# goes nowhere
echo "this nasty_msg won't appear anywhere" >&2
# goes to the tty
echo "a message on the terminal" >&3

9
2017-11-14 08:59



Esto redirigirá command1 stderr a command2 stdin, mientras deja command1 stdout como está.

exec 3>&1
command1 2>&1 >&3 3>&- | command2 3>&-
exec 3>&-

Tomado de LDP


5
2017-10-07 07:39