suprimir mensajes stderr en un script bash


49

Considere el siguiente nombre de script (ligeramente tonto) 'test1.sh':

#/bin/bash
#
sleep 10 &
echo sleep pid = $!
pkill sleep

Cuando lo ejecuto, obtengo no solo la salida del eco, sino el informe de bash de la muerte del sueño en stderr:

$ ./test1.sh
sleep pid = 3551
./test1.sh: line 5:  3551 Terminated              sleep 10

En este caso, me gustaría suprimir la impresión a stderr. Sé que puedo hacerlo en la línea de comando, como en:

$ ./test1.sh 2> /dev/null

... pero ¿hay una manera de suprimir desde dentro de la secuencia de comandos? (Sé que podría envolverlo en un segundo script y hacer que el contenedor lo redirija, pero debe haber algo más fácil ...)


¿Intentaste agregar la redirección 2> / dev / null después de dormir pkill?
— rahul

@rahul: sí, pkill no está generando el mensaje, bash sí.
— fearless_fool

Solía ​​matar en lugar de pkill y no obtengo el stderr. extraño ..
— rahul

@rahul: ¿podría ser una cosa incorporada o no incorporada? ¿Lo probaste también con pkill?
— fearless_fool

Sí, creo que lo es. Me sale el mismo error con pkill, pero no con kill. Mientras usaba kill, usaba el pid en lugar del nombre del proceso.
— rahul

Respuestas:


73

Tienes razón; pkill no genera el mensaje, bash sí. Sugieres que

$ ./test1.sh 2> /dev/null

Es una posible solución. Como señala UVV, la acción equivalente dentro del script es

exec 2> /dev/null

Esto redirige el stderr para el script /dev/null desde esta declaración hasta que se vuelva a cambiar. Las formas torpes de cambiarlo de nuevo incluyen

exec 2> /dev/tty

que redirige stderr a la terminal. Esto es probablemente (pero no necesariamente) donde estaba originalmente.

O

exec 2>&1

lo que establece que stderr sea lo mismo que stdout, y es probable que esté equivocado.

Una forma más confiable es

exec 3> y 2
exec 2> / dev / null
(haz cosas donde no quieras ver el stderr.) 
exec 2> & 3

que guarda el stderr original en el descriptor de archivo 3 y luego lo restaura.

Otras formas de suprimir solo el anuncio del proceso de muerte incluyen

(sleep 10 & pkill sleep) 2> /dev/null

y

{ sleep 10 & pkill sleep;} 2> /dev/null

que cambian el stderr solo para los comandos agrupados.


Esta es una gran respuesta detallada. ¡Gracias Señor!
— Keenan Lawrence

¿Hay algún peligro asociado con guardar stdiny stderrcon nuevos descriptores de archivos, enviar los descriptores originales /dev/nully luego restaurarlos?
— Alexej Magura

Bueno, supongo que, si ejecuta un programa que (sin que usted lo sepa) escribió en el descriptor de archivo 3 (o 4), esa operación fallaría en circunstancias normales. Pero el programa podría escribirse para ignorar el fallo y continuar sin informarlo; entonces nunca lo sabrías. Pero si su descriptor de archivo 1 (o 2) estaba "estacionado" en el descriptor de archivo 3 (o 4), entonces ese programa de repente estaría escribiendo en el stdout o stderr de su script. Pero ese es un ejemplo muy artificial, y todavía un peligro mínimo. ¿Tenías algo en mente?
— Scott

1
FWIW, estoy a favor del enfoque de comando agrupado de Scott, es decir{ sleep 10 & pkill sleep;} 2> /dev/null
— fearless_fool

9

De acuerdo con esto , podría hacer algo como lo siguiente:

#!/bin/bash
exec 2>/dev/null
ls -al test
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.