IO-重定向:这些示例中缺少的输出行发生了什么?

IO-重定向:这些示例中缺少的输出行发生了什么?

当我们重定向 shell 脚本的输出时,我注意到一些相当奇怪的行为,该脚本本身将其一些输出重定向到 /dev/stdout 或 /dev/stderr。

外壳脚本

$ cat test.sh
#!/bin/bash -x
echo stdout
echo stderr >&2
echo '/dev/stdout' > /dev/stdout
echo '/dev/stderr' > /dev/stderr

基线:无重定向

$ ./test.sh
+ echo stdout
stdout
+ echo stderr
stderr
+ echo /dev/stdout
/dev/stdout
+ echo /dev/stderr
/dev/stderr

如果我们不执行任何重定向,一切都会按我们的预期显示。

重定向标准输出

$ ./test.sh > out
+ echo stdout
+ echo stderr
stderr
+ echo /dev/stdout
+ echo /dev/stderr
/dev/stderr

$ cat out
/dev/stdout

当我们重定向 stdout 时,“/dev/stdout”行会按预期重定向,但“stdout”行不再出现在任何地方。

将流重定向到单独的文件

$ ./test.sh > out 2> err

$ cat out
/dev/stdout

$ cat err
/dev/stderr

不仅“stderr”,而且“bash -x”行也消失了。

将流重定向到同一文件

$ ./test.sh > out 2>&1

$ cat out
/dev/stderr

在最后一种情况下,我们丢失了上一个示例中的所有内容,并且之前成功重定向到该文件的“/dev/stdout”也丢失了。


在 shell 脚本中使用 exec 行进行重定向,例如exec 1>out; exec 2>&1;,产生与从命令行重定向相同的行为。

问题:为什么缺少的行会丢失,脚本的每一行会发生什么(包括通过命令行重定向执行的隐式执行行)从而导致这种情况发生?优选地,后者的答案将描述所涉及的系统调用(dup2?)。

答案1

因为您正在重定向到文件

echo '/dev/stdout' > /dev/stdout
echo '/dev/stderr' > /dev/stderr

将覆盖(而不是附加到)文件。当您不重定向时,您不会注意到这一点,因为您只能附加到 stdout/stderr。

用。。。来代替

echo '/dev/stdout' >> /dev/stdout
echo '/dev/stderr' >> /dev/stderr

一切都恢复正常了。

相关内容