重定向命令后重定向stdout和stderr



在bash脚本中,我正在使用以下命令启用IP转发:

echo 1 > /proc/sys/net/ipv4/ip_forward

但是,我也想包括我自己的错误消息,因此我必须将Stdout和STDERR重定向到/dev/null,看起来如下:

echo 1 > /proc/sys/net/ipv4/ip_forward >/dev/null 2>&1

这适用于没有重定向符号的命令,例如:

route add default gw 10.8.0.1 > /dev/null 2>&1

有什么办法可以为确实有重定向的命令做这项工作吗?有解决方法吗?我可以做得更好吗?

您的重定向是毫无意义的(无罪)。

这个:

echo 1 > /proc/sys/net/ipv4/ip_forward >/dev/null 2>&1

Will:

  1. 重定向echo的标准输出为/proc/sys/net/ipv4/ip_forward;
  2. 重定向echo的标准输出为/dev/null
  3. 重定向echo的标准错误到文件描述符1点,即 /dev/null

因此,在全球范围内,重定向2取消重定向1:什么都不会转到/proc/sys/net/ipv4/ip_forward

我想您想将echo的标准输出重定向到/proc/sys/net/ipv4/ip_forwardecho的标准误差为/dev/null。这是通过:

实现的
echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null

但请继续阅读,我相信那不是您要寻找的答案!


为什么要将echo的标准错误重定向到/dev/nullecho很少写入标准错误。实际上,echo唯一会写入标准错误的时间是在有写入错误时。有几种方式可能发生:

  • 如果磁盘已满(可以使用/dev/full模拟):

    $ echo hello >/dev/full
    bash: echo: write error: No space left on device
    $ echo hello >/dev/full 2>/dev/null
    $
    

    (未在重定向2>/dev/null显示的错误消息)。

  • 如果echo的标准已关闭:

    $ ( exec >&-; echo hello )
    bash: echo: write error: Bad file descriptor
    $ ( exec >&-; echo hello 2> /dev/null )
    $
    

    (未在重定向2>/dev/null显示的错误消息)。

可能还有其他情况,echo输出到标准错误。但是以下当然不在其中:

  • echo的标准输出重定向到不存在的文件描述符:

    $ echo hello >&42
    bash: 42: Bad file descriptor
    $ echo hello >&42 2>/dev/null
    bash: 42: Bad file descriptor
    $
    

    重定向2>/dev/null没有修复任何内容;您实际上可以看到错误来自bash,而不是来自echo(后者将具有bash: echo:作为前缀)。

  • 无需写入许可即可将echo的标准输出重定向到文件:

    $ touch testfile
    $ chmod -w testfile
    $ echo hello > testfile
    bash: testfile: Permission denied
    $ echo hello > testfile 2>/dev/null
    bash: testfile: Permission denied
    $
    

    与上述相同,重定向2>/dev/null没有修复任何内容。

以前的情况并未由2>/dev/null修复,因为该错误发生在BASH的级别,甚至在执行命令并执行重定向之前,因为在重定向的那一刻,它会遇到错误:无法打开。用于编写和输出错误消息到标准输出的流。‡

现在,我想您正在尝试修复以下方案:当用户没有足够的权利写入/proc/sys/net/ipv4/ip_forward时:

$ echo 1 >/proc/sys/net/ipv4/ip_forward
bash: /proc/sys/net/ipv4/ip_forward: Permission denied
$

标准错误上的错误消息不能使用简单的重定向‡ 重定向:

$ echo 1 >/proc/sys/net/ipv4/ip_forward 2>/dev/null
bash: /proc/sys/net/ipv4/ip_forward: Permission denied
$

重定向在重定向级别发生的错误(即执行命令之前的)的标准方法是使用分组:

$ { echo 1 >/proc/sys/net/ipv4/ip_forward; } 2>/dev/null

现在可以解释您为答案发布的解决方案的原因:让我们浏览一下,我们会看到一些东西表明您不完全了解重定向(希望这篇文章能帮助您了解一些事情);您的代码是:

function ip_forward
{
    echo 1 > /proc/sys/net/ipv4/ip_forward
}
ip_forward >/dev/null 2>&1

这将运行函数ip_forward,并重定向:

  1. 其标准输出到/dev/null;
  2. 然后其标准误差到其标准输出点的位置(即/dev/null)。

但是该功能ip_forward不会输出任何内容到标准输出!因此,重定向>/dev/null仅是用于重定向的2>&1部分。实际上,您的代码完全等同于:

function ip_forward
{
    echo 1 > /proc/sys/net/ipv4/ip_forward
}
ip_forward 2>/dev/null

但是(由于您仅使用函数构造作为实现所需目标的一种方式,而不是因为您想要一个功能),最好将代码写入:

echo 1 2>/dev/null >/proc/sys/net/ipv4/ip_forward

{ echo 1 > /proc/sys/net/ipv4/ip_forward; } 2>/dev/null

(后者是首选)。

对不起这个长篇文章!


‡ 我们应该注意的是:重定向顺序。当Bash读到它们时,它们是从左到右进行的。我们首先重定向标准误差,然后将标准输出转为不存在/不易加的流?

$ echo hello 2>/dev/null >&42
$

是的,它有效。

‡ 好吧,可以,,如果您了解了以前的脚注:

$ echo 1 2>/dev/null >/proc/sys/net/ipv4/ip_forward
$ echo $?
1
$

标准错误没有错误!那是由于重定向的顺序。

已解决

echo 1 > /proc/sys/net/ipv4/ip_forward ip_forward 2>/dev/null

echo 1是stdout零件,因此不必重定向。我只需要添加2>/dev/null

重定向stderr。

最新更新