2010-08-23 75 views
4

我发现tcl exec命令从stdout先返回stderr,然后是stderr。例如,我下面的“测试脚本”的顺序生成消息:tcl exec首先读取stdout然后stderr?

puts "test started" 
puts stderr "some non-fatal error goes to stderr" 
puts "test passed" 

然后我执行这个脚本是这样的:

set ret [ catch { exec sh -c $cmd } msg ] 

和我从$味精得到的是:

test started 
test passed 
some non-fatal error goes to stderr 

这真的让我很难得到正确的结果。

有人可以让如果知道是否有可能获得为了从两个输出和错误消息,并且:

1)请不要重定向这样的,这可以让他们一切为了确实:

set ret [ catch {exec $cmd >&log.txt} msg ] 

2)我有打电话给 TCL脚本 TCL脚本,对不起

3)我也不能直接源.tcl测试脚本becau如果我的tcl脚本只是源 tcl脚本,那么在这两者之间就会调用其他脚本。

我使用tclsh的8.3

不知道这是否是太奢侈了。我希望有人可以弄清楚这一点。谢谢。

+1

有关更多提示,请参阅http://wiki.tcl.tk/stderr。 – 2010-08-23 14:57:14

回答

5

首先,让我们定义一个简单的命令进行测试的目的,我们可以肯定的意志测试正是我们所需要:

set cmd "echo a; echo b >&2; echo c" 

接下来,我们使用一些额外的帮助来处理输出和错误流的合并(几行为清楚起见拆分命令只有这样,我们能看到的catch包装物上,并在包裹exec是):

set ret [catch { 
    exec sh -c $cmd |& cat 
} msg] 

如果我们测试,我们会发现,我们得到$ret0,并且$msg正在正确排序:

a 
b 
c 

如何这行得通?诀窍是|&,它在管道到另一个进程时进行合并。 (我们使用cat,因为它只是传递的东西通过无干扰。)

如果您使用的Tcl 8.6(测试版),您可以使用chan pipe产生可以重定向stdoutstderr2>@ fileId form一个通道,但这对你并不有用。 (你知道8.3已经过时了吗?即使8.4不再被真正支持,8.5是生产级代码被推荐的目标。)

+0

如果你用'open'做了一个管道,你会有更多的选择,但是这样更加复杂。 – 2010-08-23 12:16:25

+0

真棒!凉!!虽然不太清楚机制,但我很高兴看到您的文章并使用此代码。谢谢! – 2010-08-24 01:04:24

+0

机制是“'&'发送stdout和stderr到管道中的下一个进程”。我使用'cat'来传递它。 – 2010-08-24 07:06:02

-1

使用source命令,而不是exec只要你想从另一个TCL脚本中调用Tcl脚本:

set ret [catch {source $cmd} msg] 
+0

谢谢ardsrk。但是很抱歉,调用是这样的:我的tcl脚本调用 - >一个.sh shell文件,它设置系统变量和调用 - > tcl测试脚本。如果我只是源代码.tcl脚本,它将无法正常工作。 – 2010-08-23 07:28:14

+0

我修改了我的问题以表明清楚。我应该。 – 2010-08-23 07:34:32

相关问题