4

我发现 tcl exec 命令首先从标准输出返回字符串,然后是标准错误。例如,我的以下“测试脚本”按此顺序生成消息:

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

然后我像这样执行脚本:

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

我从 $msg 得到的是:

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

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

有人可以让我们知道是否可以按顺序从 stdout 和 stderr 获取消息,并且:

1)请不要像这样重定向,这确实可以让它们井然有序:

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

2)我必须在我的tcl 脚本中调用那个tcl脚本,对不起

3) 我也不能直接获取 .tcl 测试脚本,因为两者之间还调用了其他脚本,如果我的 tcl 脚本只是获取tcl 脚本,它将无法工作。

我正在使用 tclsh 8.3

不确定这是否要求太多。我希望有人能解决这个问题。谢谢。

4

1 回答 1

5

首先,让我们为测试目的定义一个简单的命令,我们可以确定它会测试我们需要的内容:

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

接下来,我们使用一些额外的帮助器来处理 stdout 和 stderr 流的合并(为了清楚起见,将命令分成几行,以便我们可以看到catch包装器在哪里以及被包装在哪里exec):

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

如果我们对此进行测试,我们会发现我们得到$retbeing 0,并且$msg被正确排序:

a
b
c

它是如何工作的?诀窍是|&,它在管道到另一个进程时进行合并。(我们使用cat它是因为它只是让事物通过而不干扰。)

如果您使用的是 Tcl 8.6(测试版),您可以使用它chan pipe来生成一个可以重定向stdout并使用formstderr进入的频道,但这对您来说不是那么有用。(您知道 8.3 已经过时了吗?甚至不再真正支持 8.4;8.5 是推荐的生产级代码目标。)2>@ fileId

于 2010-08-23T12:13:55.360 回答