2010-08-23 1 views
4

Я обнаружил, что команда tcl exec возвращает строку из stdout сначала, а затем 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 se есть другие сценарии, называемые между ними, и это не будет работать, если мой tcl-скрипт просто будет источником , что tcl script.

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

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

+1

См. Http://wiki.tcl.tk/stderr для получения дополнительных сведений. –

ответ

5

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

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 form, но это не так полезно для вас. (Вы знаете, что 8.3 довольно устаревший? Даже 8.4 больше не поддерживается, а 8.5 - это то, что рекомендуется для целевого класса.)

+0

У вас будет больше вариантов, если вы создали конвейер с 'open', но сложнее сшить. –

+0

awesome !! круто!! хотя и не очень ясный механизм, я так рад видеть ваше сообщение и использовать этот код. Спасибо! –

+0

Механизм «' | & 'отправляет как stdout, так и stderr в следующий процесс в конвейере». Я использую 'cat', чтобы просто передать его. –

-1

Используйте source команду вместо exec, как вы хотите, чтобы вызвать TCL скрипт из другого TCL сценария:

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

Спасибо ardsrk. Но извините, что вызов выглядит так: мой скрипт tcl вызывает -> файл оболочки .sh, который устанавливает системные вары и вызовы -> тестовый скрипт tcl. Если я просто отправлю сценарий .tcl, это не сработает. –

+0

Я изменил свой вопрос, чтобы сделать четкое заявление. Мне следует иметь. –