在Tcl中分离stdout和stderr会除去stderr的最后一行
我不是Tcl程序员,但我需要修改一个Tcl脚本,该脚本调用一个外部命令并尝试分离在Tcl中分离stdout和stderr会除去stderr的最后一行,tcl,stdout,stderr,Tcl,Stdout,Stderr,我不是Tcl程序员,但我需要修改一个Tcl脚本,该脚本调用一个外部命令并尝试分离stdout和stderr。下面是脚本当前如何执行此操作的一个简单示例 #!/usr/bin/tclsh8.4 set pipe [open "|cmd" r] while {[gets $pipe line] >= 0} {puts $line} catch "close $pipe" errorMsg puts "$errorMsg" 这里,cmd是一个外部命令,为了这个示例,我将用下面的shell脚本
stdout
和stderr
。下面是脚本当前如何执行此操作的一个简单示例
#!/usr/bin/tclsh8.4
set pipe [open "|cmd" r]
while {[gets $pipe line] >= 0} {puts $line}
catch "close $pipe" errorMsg
puts "$errorMsg"
这里,cmd
是一个外部命令,为了这个示例,我将用下面的shell脚本替换它。(我正在Linux机器上工作,但是您可以修改它以写入stdout
和stderr
,但是这适合您的系统。)
当我执行cmd
时,我得到了预期的以下四行:
% ./cmd
A
B
C
D
但是,当我执行我的Tcl脚本时,我得到:
% ./test.tcl
A
B
D
这是一个更普遍现象的例子,即catch
似乎吞下了stderr
的最后一行以外的所有内容
对我来说,实现这一点的“明显”方法是尝试模仿stdout
,它显然可以工作并打印输出的所有行。但是,当前的实现是基于使用open“| cmd”
获取Tcl通道,这需要运行外部命令。我不知道如何在不打开外部命令的情况下创建通道,即使我知道,这种方法也会出现后续问题。(我如何将close
的输出输入通道?如果我需要打开一个新通道来获得我正在关闭的每个通道的输出,那么我不需要无限多的通道吗?)
如果有人知道为什么errorMsg
会删除初始行或其他不存在此问题的方法,请告诉我
我知道会出现这种情况,所以我会提前说,短期内切换到Tcl 8.5可能不是我的选择,因为我不控制运行此脚本的环境。有趣的是,如果您将cmd脚本的最后一行更改为
echo“D”,它将按预期工作>>/dev/stderr
@SchelteBron这很吸引人,但有点奇怪,因为我不认为
和>
之间的区别对stdout
和stderr
很重要。这表明我可以通过更改cmd
而不是Tcl脚本来修复该行为,在我的例子中,Tcl脚本对我来说实际上更容易。我正在阅读更多关于如何工作的内容,这可能是unix文件系统如何处理stderr
的文件描述符与Tcl如何存储文件描述符之间有趣的交互作用的一个例子。这与Tcl无关,而是与Bash有关。请参阅上的讨论。那么,实际上,您应该将cmd示例更改为使用csh
。尽管如此,它仍然是一个执行shell脚本的问题,与Tcl无关。
% ./test.tcl
A
B
D