当/ dev / null对普通用户不可写时,如何重定向stdout / stderr

时间:2014-05-24 11:23:36

标签: linux bash shell scripting

如何暂时禁用bash脚本中的stdout或stderr?

当然,最常见的方法是将stdout或stderr重定向到/ dev / null 但在某些系统上,/ dev / null对于普通用户来说可能是不可写的 我正在写一些旨在便携的脚本,所以我不喜欢使用/ dev / null

有些博客/帖子说>& - 可以关闭stdout,但是当我在bash终端中尝试 echo 123>& - 时,它只是消息失败" bash:echo:写错误:文件描述符错误"

当然,我可以通过将stdout或stderr重定向到这样的tmp文件来实现:
some_command>的/ tmp /空
但我想要的是一个更优雅的#34;方式

我想也许我可以通过使用这样的管道实现这一点:
some_command | :

但通过这种方式,它可能会污染"原始命令的退出代码

2 个答案:

答案 0 :(得分:0)

这是一种可能的方法来做你想要的事情:

( my_cmd 3>&1 1>&2 2>&3- ) | :

这会暂时将stdout发送到新的文件句柄3并将stderr重定向到stdout,以便stderr管道进入命令(在此情况1}})。然后将新文件句柄路由回:。这些会避免将stdout的{​​{1}}加入stdoutmy_cmd in在使用后关闭句柄。

要检查上述之后:的存在状态,请检查环境变量-my_cmd是一个$PIPESTATUS[0]环境数组变量,用于保存最后一个管道中每个管道命令的退出状态。

我认为真正正确的答案是调查为什么$PIPESTATUS不是世界可写的。不是这样的是非标准的系统配置,可能会导致系统问题。相比之下,上述解决方法有点混乱。

答案 1 :(得分:0)

根据我之前写的内容和@nos上面的评论,这是一个例子:

(假设您当前目录中没有名为'zzz'的文件,并且'。'可读)

#!/bin/bash
set -o pipefail
ls . 2>&1 |:
echo $?
ls zzz 2>&1 |:
echo $?

管道成功并以静默方式失败并维护退出代码。请注意,您可能仍然可以创建一个管道示例,但这不会产生所需的结果。我还没想出一个,但这并不意味着它不在那里。正如许多人已经指出的那样,最好的答案是修复系统,使/ dev / null是世界可写的。

编辑:将/ bin / sh更改为/ bin / bash,尽管这可能不是必需的。但由于我没有对真正的Bourne Shell进行过测试,所以我决定谨慎行事。

编辑:另一个脚本,显示了几种不同的重定向,并使用|&的{​​{1}}快捷方式。如果你运行它,你会注意到一些2>&1 |失败返回141退出状态而不是预期的2.这是一个破坏的管道退出状态,但仍然代表失败。

ls

当我试图摧毁stdout但保持stderr时,我使用了两个子shell。你可以在没有外层的情况下做到这一点。事实上,这可能会更好。您没有收到损坏的管道错误,而是获得1退出状态。