¿Hay alguna forma, en bash, de canalizar STDERR a través de un filtro antes de unificarlo con STDOUT? Es decir, quiero
STDOUT ────────────────┐
├─────> terminal/file/whatever
STDERR ── [ filter ] ──┘
más bien que
STDOUT ────┐
├────[ filter ]───> terminal/file/whatever
STDERR ────┘
Respuestas:
Aquí hay un ejemplo, modelado a partir de cómo intercambiar descriptores de archivos en bash . La salida de a.out es la siguiente, sin el prefijo 'STDXXX:'.
STDERR: stderr output STDOUT: more regular ./a.out 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g' more regular stdErr output
Citando el enlace anterior:
fuente
3>&2 2>&1 1>&3-
.Un uso ingenuo de la sustitución de procesos parece permitir el filtrado por
stderr
separado destdout
::; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) out e:err
Tenga en cuenta que
stderr
sale en la partestderr
ystdout
en lastdout
que podemos ver envolviendo todo el asunto en otro subnivel y redirigir a los archivoso
ye
( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e
fuente
$
como símbolo del sistema. Luego se escriben a menudo ejemplos de concha como:$ cat /var/log/syslog | fgrep ...
. Sin embargo, esta línea no es copiable debido a la extensión$
.:;
parece un indicador pero es básicamente un shell no-op; para que pueda seleccionar y pegar toda la línea de forma segura.TL; DR:
Ejemplo:
Esto funcionará tanto en bash como en zsh. Bash es bastante omnipresente en estos días, sin embargo, si realmente necesita una solución (realmente retorcida) para POSIX
sh
, consulte aquí .Explicación
De lejos, la forma más fácil de hacer esto es redirigir STDERR mediante la sustitución de procesos :
Entonces, lo que obtienes con la sustitución de procesos es un nombre de archivo.
Como podrías hacer:
tu puedes hacer
El STDOUT de
>&2
la redirecciónfilter
vuelve al STDERR original.fuente
exec 2> >(while .. read .. echo)
en un script que se ejecuta como un servicio systemd. journald captura fd2 del servicio e infiere el nivel de registro de un prefijo '<N>': anteponer<2>
a las líneas de salida, y obtiene el nivel de ERROR asignado a los registros de diario. Pero a veces systemd fue más rápido para matar a todo el grupo de procesos al salir del principal antes de que pudiera registrar su último, ¡el mensaje más importante!TL; DR: (bash y zsh)
Ejemplo:
Muchas respuestas en la red StackExchange tienen la forma:
cat /non-existant 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
Esto tiene una suposición incorporada: que el descriptor de archivo 3 no se usa para otra cosa.
En su lugar, utilice un descriptor de archivo con nombre y
{ba,z}sh
asignará el siguiente descriptor de archivo disponible> = 10:cat /non-existant {tmp}>&1 1>&2 2>&$tmp {tmp}>&- | sed 's/e/E/g'
Tenga en cuenta que POSIX no admite descriptores de archivos con nombre
sh
.El otro problema con lo anterior es que el comando no se puede canalizar a otros comandos sin volver a intercambiar STDOUT y STDERR a sus valores originales.
Para permitir la tubería en adelante en POSIX
sh
, (y aún asumiendo que FD 3 no se usa) se vuelve complicado :Entonces, dada la suposición y la sintaxis retorcida de esto, es probable que sea mejor usar la sintaxis
bash
/ más simple que sezsh
muestra en el TL; DR anterior y se explica aquí .fuente
Encuentro el uso de la sustitución del proceso bash más fácil de recordar y usar ya que refleja la intención original casi literalmente. Por ejemplo:
$ cat ./p echo stdout echo stderr >&2 $ ./p 2> >(sed -e 's/s/S/') | sed 's/t/T/' sTdout STderr
utiliza el primer comando sed como filtro solo en stderr y el segundo comando sed para modificar la salida unida.
Tenga en cuenta que el espacio en blanco después de 2> es obligatorio para que el comando se analice correctamente.
fuente
La última parte de esta página de Advanced Bash Scripting Guide es "redireccionar solo stderr a una tubería".
Esto puede ser lo que quieras. Si no, alguna otra parte de la ABSG debería poder ayudarte, es excelente.
fuente
Eche un vistazo a las tuberías con nombre:
fuente
cat - err
romperá la intercalación de stdout y stderr?