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 ...)

temerario
fuente
¿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.

Scott
fuente
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
UVV
fuente