and shell sh io-redirection

shell - and - Redireccionamiento IO-Intercambio stdout y stderr



linux shell expansion (4)

El wiki de bash hackers puede ser muy útil en este tipo de cosas. Hay una forma de hacerlo que no se menciona entre estas respuestas, así que pondré mis dos centavos.

La semántica de >&N , para N numérico, significa redirigir al destino del descriptor de archivo N. La palabra objetivo es importante, ya que el descriptor puede cambiar de destino más tarde, pero una vez que copiamos ese objetivo, no nos importa. Esa es la razón por la cual el orden en el que declaramos de redirección es relevante.

Así que puedes hacerlo de la siguiente manera:

./myscript.sh 2>&1 >/dev/null

Eso significa:

  1. redirigir stderr al destino de stdout, que es la secuencia de salida de stdout. Ahora stderr copió el objetivo de stdout

  2. cambia stdout a / dev / null. Esto no afectará a stderr, ya que "copió" el objetivo antes de que lo cambiáramos.

No es necesario un tercer descriptor de archivo.

Es interesante cómo no puedo simplemente hacer >&- , en lugar de >/dev/null . Esto realmente cierra la salida estándar, por lo que recibo un error (en el objetivo de stderr, esa es la salida estándar real, por supuesto: D)

line 3: echo: write error: Bad file descriptor

Puede ver que el orden es relevante al tratar de intercambiar las redirecciones:

./myscript.sh >/dev/null 2>&1

Esto no funcionará, porque:

  1. Establecemos el objetivo de stdout a /dev/null
  2. Establecimos el objetivo de stderr al objetivo de stdout, que es /dev/null nuevamente.

Dado un script de shell:

#!/bin/sh echo "I''m stdout"; echo "I''m stderr" >&2;

¿Hay una manera de llamar a ese script de modo que solo se imprima stderr, cuando la última parte del comando es 2> / dev / null, es decir

$ > sh myscript.sh SOME_OPTIONS_HERE 2>/dev/null I''m stderr

O alternativamente:

$ > sh myscript.sh SOME_OPTIONS_HERE >/dev/null I''m stdout

Es una pregunta al final de un conjunto de diapositivas de conferencias, pero después de casi un día de trabajo, estoy casi seguro de que es una especie de error tipográfico. El pivote no funciona. 2> y - no funciona. Me he quedado sin ideas!


En aras de la integridad, basado en un comentario de @ 200_success arriba, probablemente sea mejor mover el descriptor de archivo 3 usando 1>&3- :

$ (sh myscript.sh 3>&2 2>&1 1>&3-) 2>/dev/null I''m stderr $ (sh myscript.sh 3>&2 2>&1 1>&3-) >/dev/null I''m stdout

En lugar de intercambiar descriptores de archivos por proceso, utilizando exec puede intercambiar stdin y stderr para todos los siguientes comandos lanzados por el shell actual:

$ (exec 3>&2 2>&1 1>&3- ; sh myscript.sh ; sh myscript.sh ) 2>/dev/null I''m stderr I''m stderr $ (exec 3>&2 2>&1 1>&3- ; sh myscript.sh ; sh myscript.sh ) >/dev/null I''m stdout I''m stdout


Mover un descriptor de archivo ( 1>&3- ) no es portátil, no todas las implementaciones de shell POSIX lo admiten. Es un ksh93-ism y un bash-ism. (Más información aquí https://unix.stackexchange.com/questions/65000/practical-use-for-moving-file-descriptors )

También es posible cerrar FD 3 en su lugar después de realizar las redirecciones.

ls 3>&2 2>&1 1>&3 3>&-

Imprime el contenido del directorio de trabajo actual en stderr.

La sintaxis 3>&- o 3<&- cierra el descriptor de archivo 3.


% (sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null I''m stderr % (sh myscript.sh 3>&2 2>&1 1>&3) >/dev/null I''m stdout