在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
有没有什么办法可以让那些在其中有重定向的命令工作?这有解决方法吗?还有其他方法可以做得更好吗?
答案 0 :(得分:4)
你的重定向是荒谬的(没有冒犯)。
此:
echo 1 > /proc/sys/net/ipv4/ip_forward >/dev/null 2>&1
意愿:
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级别,甚至在命令执行和执行重定向之前,因为它是在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
$
标准错误没有错误!这是因为重定向的顺序。
答案 1 :(得分:1)
<强>解决强>
echo 1 > /proc/sys/net/ipv4/ip_forward ip_forward 2>/dev/null
echo 1
是stdout部分,因此不必再重定向。我只需要通过添加2>/dev/null
来重定向stderr。