4

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 ]

$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 テスト スクリプトを直接ソースすることもできません。これは、2 つの間で呼び出される他のスクリプトがあり、私の tcl スクリプトがそのtcl スクリプトをソースするだけでは機能しないためです。

私はtclsh 8.3を使用しています

これがあまりにも多くを求めているかどうかはわかりません。誰かがこれを理解してくれることを願っています。ありがとう。

4

1 に答える 1

5

まず、必要なものだけを確実にテストできるテスト用の簡単なコマンドを定義しましょう。

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

catch次に、stdout ストリームと stderr ストリームのマージを処理するために、少し追加のヘルパーを使用します (ラッパーがどこにあり、ラップされたものがどこにあるかを確認できるように、わかりやすくするためにコマンドを数行に分割していますexec)。

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

それをテストすると、であり、正しい順序になっている$retことがわかります。0$msg

a
b
c

それはどのように機能しますか?トリックは|&、別のプロセスにパイプするときにマージを行うことです。(cat干渉せずに物事を通過させるために使用します。)

Tcl 8.6 (ベータ版) を使用している場合は、 を使用してchan pipeリダイレクトできるチャネルを生成できますが、これはあまり役に立ちません。(8.3 がかなり時代遅れであることをご存知ですか? 8.4 でさえ、実際にはサポートされていません。8.5 は、製品グレードのコードが対象として推奨されているものです。)stdoutstderr2>@ fileId

于 2010-08-23T12:13:55.360 に答える