重定向的意外输出

时间:2017-06-28 00:52:59

标签: bash vim io-redirection

重定向STDOUT和STDERR时遇到一个奇怪的问题。以下按预期工作:

$ gvim --version > /tmp/version.out
$ ls -l /tmp/version.out
-rw-r--r--. 1 blah blah 3419 Jun 27 17:28 /tmp/version.out

输出文件中有 3419 个字符,当我查看该文件时,它包含了我的期望。

但是,当我执行以下操作时,它无法正常工作:

$ gvim --version > /tmp/version.out 2> /tmp/version.err
$ ls -latr /tmp/version.*
-rw-r--r--. 1 blah blah 0 Jun 27 17:29 /tmp/version.out
-rw-r--r--. 1 blah blah 0 Jun 27 17:29 /tmp/version.err

请注意,.out和.err文件这次都是零长度。我用 ls 命令尝试了这个,它按预期工作:

$ ls . /ZZZ > /tmp/ls.out 2> /tmp/ls.err
$ ls -l /tmp/ls.*
-rw-r--r--. 1 blah blah 50 Jun 27 17:45 /tmp/ls.err
-rw-r--r--. 1 blah blah 33 Jun 27 17:45 /tmp/ls.out

这里,STDERR被正确地重定向:

$ cat /tmp/ls.err
ls: cannot access /ZZZ: No such file or directory

我对 gvim --version 进行了分析,并确认它正在尝试将版本信息写入STDOUT(fd 1)。无论哪种方式都没关系,因为我试图捕获STDOUT和STDERR。

这里发生了什么?

2 个答案:

答案 0 :(得分:5)

恭喜,您刚刚在gvim中发现了一个错误! 正确的程序是file a new issue on GitHub

您应首先尝试该错误的其他变体,以便开发人员更轻松地进行调试。

例如,仅重定向STDERR也会导致错误,因为没有写入输出。还有返回成功(0),这显然是一个错误。

$ gvim --version 2> /tmp/version.err
$ echo $?
0

只需查看代码,就可以在version printing中的某个位置搜索错误,或者在泛型--version参数处理中的任何位置搜索not being done by gtk

回答你的问题

发生了什么事?

gvim的开发人员制作的程序错误,除非您有编码经验,否则我不建议您努力寻找其根本原因{{1或者如果你想学习,vim如何运作。在这种情况下,您的最佳镜头是fork the repo,在修复后,提交拉取请求,以便每个人都可以从您的工作中受益。

答案 1 :(得分:1)

当标准错误不是终端时,触发错误的特定条件似乎是。当我尝试将标准错误重定向到另一个终端设备时,--version消息仍然打印到标准输出。

ek@Io:~$ gvim --version 2>/dev/null
ek@Io:~$ tty
/dev/pts/1
ek@Io:~$ who
ek       tty7         2017-07-05 02:48 (:0)
ek       pts/1        2017-07-10 09:10 (192.168.10.3)
ek       pts/3        2017-07-10 09:23 (192.168.10.3)
ek@Io:~$ gvim --version 2>/dev/pts/3
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 24 2016 16:44:48)
....

显然Vim会调用isatty(2)来帮助确定它是否应该使用终端。来自gui.c的评论:

  

如果仍然启动并且没有地方输入文本,则返回TRUE。   对于GTK和X11,我们检查stderr是不是tty,这意味着我们(可能)是从桌面启动的。还要检查stdin,“vim>& file”   允许在stdin上输入。

但该评论的其余部分(即我没有强调的部分)以及多个文件中isatty(2)的实例,使得不应立即明白应该更改的内容。

在源树上运行grep -RF 'isatty(2)'显示此内容在gui.cmessage.cmain.c中使用。 (当然,意味着该错误存在于所有这些文件中。)您也可以查看all the instances of isatty in the source code

无论如何,作为jirislav says,这应该被报告为一个错误 - 即使问题的完整解释尚不明显。我能够使用当前的上游源(commit 163095f)重现这一点。