suprimir mensagens stderr em um script bash

49

Considere o seguinte nome de script (um pouco bobo) 'test1.sh':

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

Quando o executo, recebo não apenas a saída do eco, mas também o relatório do bash sobre a morte do sono no stderr:

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

Nesse caso, eu gostaria de suprimir a impressão em stderr. Eu sei que posso fazer isso na linha de comando, como em:

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

... mas existe uma maneira de suprimi-lo de dentro do script? (Eu sei que poderia envolvê-lo em um segundo script e fazer com que o wrapper o redirecionasse, mas deve haver algo mais fácil ...)

fearless_fool
fonte
você tentou adicionar o redirecionamento 2> / dev / null após o pkill dormir?
rahul 14/02
@rahul: sim, eu fiz - o pkill não está gerando a mensagem, o bash é.
Fearless_fool
Eu usei kill em vez de pkill e não entendi o stderr. estranho ..
rahul 14/02
@rahul: poderia ser uma coisa integrada ou não integrada? Você também experimentou com pkill?
fearless_fool
sim, acredito que sim. Eu recebo o mesmo erro com pkill, mas não com kill. Ao usar o kill, usei o pid em vez do nome do proc.
rahul

Respostas:

73

Você está certo; pkill não está gerando a mensagem, o bash é. Você sugere que

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

é uma solução possível. Como UVV aponta, a ação equivalente de dentro do script é

exec 2> /dev/null

Isso redireciona o stderr para o script /dev/null dessa declaração até que seja alterado novamente. Desajeitadas maneiras de mudar de volta incluem

exec 2> /dev/tty

que redireciona o stderr para o terminal. É provavelmente (mas não necessariamente) onde estava originalmente.

Ou

exec 2>&1

que define stderr como igual a stdout e provavelmente está errado.

Uma maneira mais confiável é

exec 3> & 2
exec 2> / dev / null
(faça coisas onde você não deseja ver o stderr.) 
exec 2> & 3

que salva o stderr original no descritor de arquivo 3 e depois o restaura.

Outras maneiras de suprimir apenas o anúncio da morte do processo incluem

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

e

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

que alteram o stderr apenas para os comandos agrupados.

Scott
fonte
Essa é uma resposta ótima e detalhada. Obrigado senhor!
Keenan Lawrence
Existem perigos associados ao salvamento stdine stderraos novos descritores de arquivo, enviando os descritores originais para /dev/nulle depois restaurá-los?
Alexej Magura
Bem, suponho que, se você executasse um programa que (sem o seu conhecimento) gravou no descritor de arquivo 3 (ou 4), essa operação falharia em circunstâncias normais. Mas o programa poderia ser escrito para ignorar a falha e continuar sem reportá-la; então você nunca saberia. Mas se o descritor de arquivo 1 (ou 2) estivesse "estacionado" no descritor de arquivo 3 (ou 4), esse programa repentinamente gravaria no stdout ou stderr do seu script. Mas esse é um exemplo bem elaborado, e ainda há um risco mínimo. Você tinha algo em mente?
Scott
1
FWIW, eu sou a favor da abordagem de comando agrupado de Scott, ie{ sleep 10 & pkill sleep;} 2> /dev/null
fearless_fool
9

De acordo com isso, você pode fazer algo como o seguinte:

#!/bin/bash
exec 2>/dev/null
ls -al test
UVV
fonte