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

时间:2016-06-21 13:42:31

标签: bash redirect

在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

有没有什么办法可以让那些在其中有重定向的命令工作?这有解决方法吗?还有其他方法可以做得更好吗?

2 个答案:

答案 0 :(得分:4)

你的重定向是荒谬的(没有冒犯)。

此:

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

意愿:

  1. echo的标准输出重定向到/proc/sys/net/ipv4/ip_forward;
  2. echo的标准输出重定向到/dev/null
  3. echo的标准错误重定向到文件描述符1指向的位置,即/dev/null
  4. 因此,在全局范围内,重定向2取消了重定向1:没有任何内容可以转到/proc/sys/net/ipv4/ip_forward

    我想您要将echo的标准输出重定向到/proc/sys/net/ipv4/ip_forward,将echo的标准错误重定向到/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级别,甚至在命令执行和执行重定向之前,因为它是在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)。
    3. 但是函数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
      $
      

      标准错误没有错误!这是因为重定向的顺序。

答案 1 :(得分:1)

<强>解决

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

echo 1是stdout部分,因此不必再重定向。我只需要通过添加2>/dev/null来重定向stderr。