tcl exec сначала читает stdout, затем stderr? - PullRequest
4 голосов
/ 23 августа 2010

Я обнаружил, что команда 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 скрипт в my tcl-скрипт, извините

3) Также я не могу напрямую создать тестовый скрипт .tcl, потому что между ними есть другие скрипты, и он не будет работать, если мой tcl-скрипт будет просто источником that tcl script.

Я использую tclsh 8.3

Не уверен, что это слишком много.Я надеюсь, что кто-то может понять это.Спасибо.

Ответы [ 2 ]

5 голосов
/ 23 августа 2010

Прежде всего, давайте определим простую команду для целей тестирования, которая, как мы можем быть уверены, протестирует именно то, что нам нужно:

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

Далее мы используем небольшой дополнительный помощник для обработки слияния потоков stdout и stderr (для ясности разделим команду на несколько строк, чтобы мы могли видеть, где находится обертка catch и где обернутый exec есть):

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

Если мы проверим это, мы обнаружим, что $ret будет 0, а $msg будет правильно упорядоченным:

a
b
c

Как это работает? Уловка |&, которая выполняет слияние при передаче по трубопроводу в другой процесс. (Мы используем cat, потому что он просто пропускает вещи без вмешательства.)

Если вы используете Tcl 8.6 (в бета-версии), вы можете использовать chan pipe для создания канала, на который вы можете перенаправить stdout и stderr в 2>@ fileId форма , но это не так полезно для вас. (Вы знаете, что 8.3 довольно устарел? Даже 8.4 больше не поддерживается; 8.5 - это код производственного уровня, который рекомендуется использовать.)

0 голосов
/ 23 августа 2010

Используйте команду source вместо exec, так как вы хотите вызвать tcl-скрипт из другого tcl-скрипта:

set ret [catch {source $cmd} msg]
...