在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:
- 重定向
echo
的标准输出为/proc/sys/net/ipv4/ip_forward
; - 重定向
echo
的标准输出为/dev/null
- 重定向
echo
的标准错误到文件描述符1
点,即/dev/null
。
因此,在全球范围内,重定向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/null
? echo
很少写入标准错误。实际上,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
,并重定向:
- 其标准输出到
/dev/null
; - 然后其标准误差到其标准输出点的位置(即
/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
。