在bash脚本中抑制stderr消息


48

考虑以下(略微愚蠢的)脚本名称“ test1.sh”:

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

运行它时,不仅得到回声的输出,而且还得到bash关于stderr睡眠死亡的报告:

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

在这种情况下,我想将打印输出抑制为stderr。我知道我可以在命令行中做到这一点,如下所示:

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

......但有没有办法从抑制其的脚本?(我知道我可以将其包装在第二个脚本中,并让包装器将其重定向,但是必须有一些更简单的方法...)


您是否尝试在pkill睡眠后添加重定向2> / dev / null?
rahul 2015年

@rahul:是的,我做到了– pkill不是生成消息,bash是。
fearless_fool 2015年

我使用kill而不是pkill,并且没有得到stderr。很奇怪..
rahul 2015年

@rahul:它可以是内置的还是非内置的?您是否也尝试过使用pkill?
fearless_fool 2015年

是的,我相信是。我用pkill遇到了同样的错误,但是用kill却没有。在使用kill时,我使用了pid而不是proc名称。
rahul 2015年

Answers:


72

你是对的; 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相同,并且可能是错误的。

一个更可靠的方法是

执行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。


这是一个很棒的详细答案。谢谢你,先生!
基南·劳伦斯

保存stdinstderr新文件描述符,将原始描述符发送到/dev/null然后还原它们是否存在任何危险?
Alexej Magura

好吧,我想,如果您运行了一个程序(您不为人所知)写入文件描述符3(或4),则该操作在正常情况下将失败。但是可以编写该程序以忽略故障并继续运行而不报告故障。那么你永远不会知道。但是,如果文件描述符1(或2)“停放在”文件描述符3(或4)上,则该程序将突然写入脚本的stdout或stderr。但这是一个非常人为的例子,并且危险仍然很小。你有什么想法吗?
斯科特(Scott)

1
FWIW,我赞成Scott的分组指挥方法,即{ sleep 10 & pkill sleep;} 2> /dev/null
fearless_fool

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.