подавить сообщения stderr в скрипте bash

49

Рассмотрим следующее (слегка глупое) имя сценария 'test1.sh':

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

Когда я запускаю его, я получаю не только вывод echo, но и сообщение bash о смерти сна на stderr:

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

В этом случае я хотел бы подавить распечатку в stderr. Я знаю, что могу сделать это в командной строке, как в:

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

... но есть способ , чтобы подавить его из в сценарии? (Я знаю, что могу обернуть его во второй скрипт и сделать так, чтобы оболочка перенаправила его, но должно быть что-то более простое ...)

fearless_fool
источник
Вы пытались добавить редирект 2> / dev / null после сна pkill?
Рахул
@rahul: да, я сделал - pkill не генерирует сообщение, bash есть.
fearless_fool
Я использовал kill вместо pkill и не получал stderr. странно ..
Рахул
@rahul: это может быть встроенная или не встроенная вещь? Вы тоже пробовали это с pkill?
fearless_fool
да, я верю, что это так. Я получаю ту же ошибку с pkill, но не с kill. При использовании kill я использовал pid вместо имени proc.
Рахул

Ответы:

73

Вы правы; pkill не генерирует сообщение, bash есть. Вы предлагаете

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

это возможное решение. Как указывает UVV, эквивалентное действие внутри скрипта

exec 2> /dev/null

Это перенаправляет stderr для сценария /dev/null из этого оператора, пока он не будет изменен обратно. Неуклюжие способы изменить это назад включают

exec 2> /dev/tty

который перенаправляет stderr в терминал. Это вероятно (но не обязательно), где это было первоначально.

Или же

exec 2>&1

который устанавливает stderr таким же, как stdout, и, скорее всего, ошибается.

Более надежный способ

Exec 3> & 2
exec 2> / dev / null
(делайте вещи там, где вы не хотите видеть stderr.) 
exec 2> & 3

который сохраняет исходный stderr в файловом дескрипторе 3, а затем восстанавливает его.

Другие способы подавления только объявления о смерти процесса включают

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

а также

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

которые изменяют stderr только для сгруппированных команд.

Скотт
источник
Это такой отличный, подробный ответ. Спасибо, сэр!
Кинан Лоуренс
Существуют ли опасности, связанные с сохранением stdinи stderrсозданием новых файловых дескрипторов, отправкой исходных дескрипторов /dev/nullи последующим их восстановлением?
Алексей Магура
Что ж, я полагаю, что если вы запустили программу, которая (без вашего ведома) записала в файловый дескриптор 3 (или 4), эта операция потерпит неудачу при нормальных обстоятельствах. Но программа может быть написана так, чтобы игнорировать сбой и продолжать работу, не сообщая об этом; тогда ты никогда не узнаешь Но если ваш файловый дескриптор 1 (или 2) был «припаркован» на файловом дескрипторе 3 (или 4), то эта программа внезапно записывает в stdout или stderr вашего скрипта. Но это очень надуманный пример и все же минимальная опасность. Вы что-то имели в виду?
Скотт
1
Я предпочитаю групповой командный подход Скотта, то есть{ sleep 10 & pkill sleep;} 2> /dev/null
fearless_fool
9

В соответствии с этим вы можете сделать что-то вроде следующего:

#!/bin/bash
exec 2>/dev/null
ls -al test
УВВ
источник