GNU/Linux >> Tutoriales Linux >  >> Linux

Canalice solo STDERR a través de un filtro

TL;DR:

$ cmd 2> >(stderr-filter >&2)

Ejemplo:

% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%

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 , entonces mira aquí.

Explicación

De lejos, la forma más fácil de hacer esto es redirigir STDERR a través de la sustitución de procesos:

La sustitución de procesos permite hacer referencia a la entrada o salida de un proceso mediante un nombre de archivo. Toma la forma de

>(list)

La lista de procesos se ejecuta de forma asíncrona y su entrada o salida aparece como un nombre de archivo.

Entonces, lo que obtienes con la sustitución de procesos es un nombre de archivo.

Al igual que podrías hacer:

$ cmd 2> filename

puedes hacer

$ cmd 2> >(filter >&2)

El >&2 filter de redirección STDOUT de nuevo al STDERR original.


TL; DR:(bash y zsh)

$ cmd 2> >(stderr-filter >&2)

Ejemplo:

% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%

Muchas respuestas en la red de 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 los descriptores de archivos con nombre no son compatibles con POSIX sh .

El otro problema con lo anterior es que el comando no se puede canalizar a más comandos sin volver a cambiar STDOUT y STDERR a sus valores originales.

Para permitir la canalización hacia adelante en POSIX sh , (y aún suponiendo que FD 3 no se use) se complica:

(cmd 2>&1 >&3 3>&- | stderr-filter >&2 3>&-) 3>&1

Entonces, dada la suposición y la sintaxis retorcida de esto, es probable que sea mejor usar el bash más simple /zsh sintaxis que se muestra en el TL;DR anterior y se explica aquí.

demostración práctica, grepping solo stderr:

$ ls -l . noexistABC noexistXYZ
ls: cannot access 'noexistABC': No such file or directory
ls: cannot access 'noexistXYZ': No such file or directory
.:
total 4
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 bar.txt
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 foo.txt
drwxrwxr-x 2 frank frank 4096 Aug 19 12:26 someFolder


$ ( ls -l . noexistABC noexistXYZ 2>&1 >&3 3>&- | grep ABC >&2 3>&-) 3>&1
.:
ls: cannot access 'noexistABC': No such file or directory
total 4
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 bar.txt
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 foo.txt
drwxrwxr-x 2 frank frank 4096 Aug 19 12:26 someFolder

Aquí hay un ejemplo, inspirado en 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 del enlace anterior:

  1. Primero guarde la salida estándar como &3 (&1 se convierte en 3)
  2. A continuación, envíe stdout a stderr (&2 se convierte en 1)
  3. Enviar stderr a &3 (stdout) (&3 se convierte en 2)
  4. cerrar &3 (&- se convierte en 3)

Un uso ingenuo de la sustitución de procesos parece permitir el filtrado de stderr por separado de stdout :

:; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 )
out
e:err

Tenga en cuenta que stderr sale en stderr y stdout en stdout , que podemos ver envolviendo todo en otra subcapa y redirigiendo a los archivos o y e

( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e

Linux
  1. Filtro Rsync:¿Copiar un solo patrón?

  2. ¿Alguna forma de usar Xargs a través de una tubería?

  3. ¿Redirigir y canalizar la salida?

  4. ¿Cómo imprimo un mensaje a stderr en Go?

  5. ¿Por qué el tráfico de red de Linux solo pasa por eth0?

Cómo monitorear el progreso de los datos a través de una tubería usando el comando 'pv'

6 opciones de filtro de tráfico de red tcpdump

¿Hacer Tail -f Exit en una tubería rota?

¿Cómo redirigir solo Stderr?

¿Encontrar solo el destino del enlace simbólico?

Tubería B a D? – A &&B || C | ¿D?