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

Sta*_*sen 2 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

有什么方法可以使此功能适用于确实有重定向的命令吗?有解决方法吗?还有其他方法我可以做得更好吗?

gni*_*urf 5

您的重定向毫无意义(无意冒犯)。

\n\n

这:

\n\n
echo 1 > /proc/sys/net/ipv4/ip_forward >/dev/null 2>&1\n
Run Code Online (Sandbox Code Playgroud)\n\n

将要:

\n\n
    \n
  1. echo将的标准输出重定向到/proc/sys/net/ipv4/ip_forward;
  2. \n
  3. echo将标准输出重定向到/dev/null
  4. \n
  5. echo的标准错误重定向到文件描述符指向的1位置,即/dev/null.
  6. \n
\n\n

因此,在全局范围内,重定向 2 取消了重定向 1:没有任何内容会转到/proc/sys/net/ipv4/ip_forward!

\n\n

我猜您想echo将 的标准输出重定向到 ,/proc/sys/net/ipv4/ip_forward并将echo的标准错误重定向到/dev/null。这是通过以下方式实现的:

\n\n
echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null\n
Run Code Online (Sandbox Code Playgroud)\n\n

但请继续阅读,我相信这不是您正在寻找的答案!

\n\n
\n\n

为什么要将echo的标准错误重定向到/dev/null?\necho很少写入标准错误。事实上,只有在echo出现写入错误时才会写入标准错误。有几种可能发生这种情况的方式:

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

    \n\n
    $ echo hello >/dev/full\nbash: echo: write error: No space left on device\n$ echo hello >/dev/full 2>/dev/null\n$\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    (重定向时不显示任何错误消息2>/dev/null)。

  • \n
  • ifecho的标准输出已关闭:

    \n\n
    $ ( exec >&-; echo hello )\nbash: echo: write error: Bad file descriptor\n$ ( exec >&-; echo hello 2> /dev/null )\n$\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    (重定向时不显示任何错误消息2>/dev/null)。

  • \n
\n\n

可能还有其他情况echo输出为标准错误。但以下肯定不在其中:

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

    \n\n
    $ echo hello >&42\nbash: 42: Bad file descriptor\n$ echo hello >&42 2>/dev/null\nbash: 42: Bad file descriptor\n$\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    重定向2>/dev/null并不能解决任何问题;您实际上可以看到错误来自于bash而不是来自echo(后者将作为bash: echo:前缀)。

  • \n
  • echo的标准输出重定向到没有写权限的文件:

    \n\n
    $ touch testfile\n$ chmod -w testfile\n$ echo hello > testfile\nbash: testfile: Permission denied\n$ echo hello > testfile 2>/dev/null\nbash: testfile: Permission denied\n$\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    与上面相同,重定向2>/dev/null不会解决任何问题。

  • \n
\n\n

前面的情况没有被 修复2>/dev/null,因为错误发生在 Bash 级别,甚至在执行命令和执行重定向之前,因为在重定向时 Bash 遇到错误:它无法打开用于写入的流并将错误消息输出到标准输出。

\n\n

现在我猜您正在尝试修复以下情况:当用户没有足够的权限写入时/proc/sys/net/ipv4/ip_forward

\n\n
$ echo 1 >/proc/sys/net/ipv4/ip_forward\nbash: /proc/sys/net/ipv4/ip_forward: Permission denied\n$\n
Run Code Online (Sandbox Code Playgroud)\n\n

标准错误上的错误消息无法通过简单的重定向进行重定向

\n\n
$ echo 1 >/proc/sys/net/ipv4/ip_forward 2>/dev/null\nbash: /proc/sys/net/ipv4/ip_forward: Permission denied\n$\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
$ { echo 1 >/proc/sys/net/ipv4/ip_forward; } 2>/dev/null\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在这解释了为什么您作为答案发布的解决方案有效:让我们仔细研究一下,我们会发现有些东西表明您没有完全理解重定向(希望这篇文章将帮助您理解一些事情);你的代码是:

\n\n
function ip_forward\n{\n    echo 1 > /proc/sys/net/ipv4/ip_forward\n}\nip_forward >/dev/null 2>&1\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
    \n
  1. 其标准输出到/dev/null
  2. \n
  3. 然后将其标准误差指向其标准输出点(即/dev/null)。
  4. \n
\n\n

但该函数ip_forward不会向标准输出输出任何内容!所以重定向对重定向的部分>/dev/null有用。事实上,您的代码完全等同于:2>&1

\n\n
function ip_forward\n{\n    echo 1 > /proc/sys/net/ipv4/ip_forward\n}\nip_forward 2>/dev/null\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是(因为您只是使用函数构造来实现您想要的\xe2\x80\x94,而不是因为您想要一个函数),所以最好将代码编写为:

\n\n
echo 1 2>/dev/null >/proc/sys/net/ipv4/ip_forward\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者

\n\n
{ echo 1 > /proc/sys/net/ipv4/ip_forward; } 2>/dev/null\n
Run Code Online (Sandbox Code Playgroud)\n\n

(后者是首选)。

\n\n

抱歉这篇长文!

\n\n
\n\n

\n有一点我们应该注意:重定向的顺序。Bash 读取它们时,它们是从左到右执行的。我们首先重定向标准错误,然后将标准输出重定向到不存在/不可写的流怎么样?

\n\n
$ echo hello 2>/dev/null >&42\n$\n
Run Code Online (Sandbox Code Playgroud)\n\n

没错,它有效。

\n\n

\n好吧,可以,如果你理解前面的脚注:

\n\n
$ echo 1 2>/dev/null >/proc/sys/net/ipv4/ip_forward\n$ echo $?\n1\n$\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n