这两个bash命令之间有区别吗?
$ some_command 1>file.log 2>&1
和
$ some_command 1>file.log 2>file.log
答案 0 :(得分:4)
此命令:
some_command 1>file.log 2>file.log
重定向stdout和stderr的方法不正确。
如果您使用noclobber
设置set -o noclobber
选项,则实际上会导致此错误:
-bash: file.log : cannot overwrite existing file
但是,如果您使用noclobber
然后
set +C
选项
some_command 1>file.log 2>file.log
虽然使用
更好,但不会产生上述错误some_command 1>file.log 2>&1
答案 1 :(得分:1)
是的区别。
bash$ (echo foo; echo bar 1>&2) 1>test.out 2>&1
bash$ cat test.out
foo
bar
bash$ (echo foo; echo bar 1>&2) 1>test.out 2>test.out
bash$ cat test.out
bar
bash$
作为anubhava notes,如果设置了noclobber
,则第二个变体甚至根本不运行(即使您先删除test.out
文件)。但是如果没有设置这个选项,就像我在这里的例子那样,bash在这里做的是打开文件两次,而不是打开它一次然后使用dup
系统调用。
在这种情况下,关键区别在于dup
- ed文件描述符与其原始文件共享其搜索偏移量,而单独的open
则没有。因此:
在上面的第一个test.out
示例中,stdout(描述符1)和stderr(描述符2)共享搜索偏移量,该偏移量最初为零。 echo foo
命令运行,将其输出发送到其stdout,该stdout将转到偏移量为0的文件,并写入包括换行符在内的四个字节。这会使偏移量最多变为4. echo bar
命令然后运行,将其输出发送到stderr, 1 ,它将转移到偏移量为4的文件,记住偏移量为共享 - 并将bar
和换行符写入文件。 (然后将偏移量提升到8,但没有其他任何东西使用该文件,因此它将被关闭并且丢弃偏移量。)
然而,在第二个test.out
示例中,stdout和stderr具有单独的搜索偏移量。两者都在偏移0处向test.out
打开。echo foo
命令运行,将foo
和换行符写入stdout并将偏移量更新为4.然后运行echo bar
命令,将bar
和换行符写入stderr,但再次返回0 ,覆盖前一个字符串。 (和以前一样,偏移量突然增加到4次,但一切都完成了,两个描述符关闭,丢弃了偏移量。)
这就是为什么第一次测试在文件中以两行结束,但第二次测试只有一行。
1 从技术上讲,echo bar
也写入了它的stdout,但我们使用1>&2
将stderr(描述符2)dup
转到stdout(描述符1)。和以前一样,这个dup
会导致偏移量被共享。请注意,dup
重定向仅在echo bar
命令的持续时间内继续,之后所有内容都将恢复。这种回归是我们必须在测试本身中对两个echo
命令加以括号的原因,以便test.out
的外部重定向在两个 echo
调用中持续存在。 (从技术上讲,我们重定向运行两个fork
命令的echo
- ed子shell的描述符。)