Shell:将标准输出重定向到/dev/null,将标准错误输出重定向到标准输出

69

我在cyberciti.biz的评论中看到了这个有趣的问题。

我发现我甚至无法用一行sh命令以灵活的方式完成这个问题。

根据我的思路,解决方案是:

tmp_file=`mktemp`
(./script 2>$tmp_file >/dev/null; cat $tmp_file) | ./other-script
rm tmp_file

但是你看,这不是同步的,而且很丑陋。

欢迎分享你对此的看法。:)


3
你尝试过./script.sh 2>&1 >/dev/null吗? - cnicutar
@cnicutar,看来我一开始就理解错了。我以为 2>&1 会将 stderr 重定向到 stdout,然后 1>/dev/null 将它们两个都重定向到 /dev/null。好吧,我需要重新学习一些 shell。 - shouya
1
在我的情况下,2>&1 需要放在结尾,例如:if ping -c 1 fake.x > /dev/null 2>&1;then echo true;else echo false;fi - Jonathan Cross
3个回答

136

你想要什么

./script 2>&1 1>/dev/null | ./other-script

这里的顺序很重要。假设stdin(fd 0),stdout(fd 1)和stderr(fd 2)最初都连接到一个tty,因此

0: /dev/tty, 1: /dev/tty, 2: /dev/tty

首先要设置的是管道。将“other-script”的标准输入连接到管道上,同时将“script”的标准输出也连接到同一个管道上,因此,到目前为止,“script”文件描述符的情况如下:

0: /dev/tty, 1: pipe, 2: /dev/tty

接下来,重定向会从左到右进行。 2>&1 使文件描述符 2 去到当前文件描述符 1 所在的地方,也就是管道。

0: /dev/tty, 1: pipe, 2: pipe
最后,1>/dev/null 将 fd1 重定向到 /dev/null
0: /dev/tty, 1: /dev/null, 2: pipe

最终结果是,脚本的标准输出被静音处理,而其标准错误输出被发送到管道中,最终进入了另一个脚本的标准输入。

请参见http://bash-hackers.org/wiki/doku.php/howto/redirection_tutorial

还要注意,1>/dev/null>/dev/null同义,但更加明确。


在我的编辑评论中,我错误地引用了stdin而不是stdout,尽管编辑本身仍然是正确的。我无法看到如何修复编辑评论或评论编辑审查,所以在这里提到。 - DVS
@geirha 很好。如果我们需要将输出重定向到>/dev/null,并将stderr同时输出到文件和屏幕上怎么办?谢谢 - Manohar Reddy Poreddy
1
@ManoharReddyPoreddy 要将输出同时输出到终端和文件中,请使用 tee 命令。./script 2>&1 >/dev/null | tee file - geirha
显然这在zsh中不起作用。它最终将脚本的stdout和stderr重定向到管道中。我在想,这是一个bug还是一个特性。 - Olaf Klischat
我想在我的互联网连接中断时仅记录时间戳。 以下命令按预期工作。ping www.google.com 2>&1 1>/dev/null | perl -nle 'print scalar(localtime), " ", $_' - Kharthigeyan

6
这个怎么样:
./script 3>&1 1>/dev/null 2>&3 | ./other-script

该想法是“备份”stdout描述符,关闭原始的stdout,然后将strerr重定向到保存的stdout。它与geirha提供的解决方案非常相似,但更加明确(bash编码很容易变得非常模糊)。

-6

那是因为你不能这样做。STDOUT 和 STDERR 只是两个文件,由文件描述符表示,这些描述符只是整数,具体来说是 1 和 2。

你要求的是将描述符 2 设置为/dev/null,然后将描述符 3 设置为相同的文件描述符 2,并将输出发送到其他地方。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接