Если вы используете Tcl 8.6, вы можете захватить вывод с помощью:
lassign [chan pipe] reader writer
set pid [exec make >@$writer &]
close $writer
Не забудьте прочитать из $reader
или подпроцесс будет простаивать. Имейте в виду, что при использовании таким образом выход будет доставлен полностью буферизованным, хотя это более важно при выполнении интерактивной работы. Если вы хотите, чтобы выход был эхом и стандартным, вам нужно сделать так, чтобы ваш сценарий сделал это. Вот простой обработчик для чтения.
while {[gets $reader line] >= 0} {
lappend log $line
puts $line
}
close $reader
Перед Tcl 8.6, лучше всего было бы создать команду подпроцесс трубопровода:
set reader [open |make]
Если вам нужен PID, то это может стать немного более сложным:
set reader [open |[list /bin/sh -c {echo $$; exec make}]]
set pid [gets $reader]
Да, это довольно уродливо ...
[EDIT]: Вы используете Tk в Tcl 8.5 (так что вам нужна форма конвейера open |…
), и поэтому вы хотите сохранить цикл событий. Хорошо. Это точно, для fileevent
, но вам нужно думать асинхронно.
# This code assumes that you've opened the pipeline already
fileevent $reader readable [list ReadALine $reader]
proc ReadALine {channel} {
if {[gets $channel line] >= 0} {
HandleLine $line
} else {
# No line could be read; must be at the end
close $channel
}
}
proc HandleLine {line} {
global log
lappend log $line; # Or insert it into the GUI or whatever
puts $line
}
Этот пример делает не использование неблокирующего ввода/вывода. Это может вызвать проблему, но, вероятно, этого не произойдет. Если это не вызывает проблем, используйте:
fconfigure $reader -blocking 0
fileevent $reader readable [list ReadALine $reader]
proc ReadALine {channel} {
if {[gets $channel line] >= 0} {
HandleLine $line
} elseif {[eof $channel]} {
close $channel
}
}
proc HandleLine {line} {
global log
lappend log $line
puts $line
}
Более сложные и разнообразные варианты возможны, но они только действительно необходимо, когда вы имеете дело с ненадежными каналами (например, розетки публичных серверов).
Если вы использовали 8.6, вы могли бы использовать сопрограммы, чтобы этот код выглядел более похожим на прямолинейный код, который я использовал ранее, но это функция, которая строго 8.6 (и более поздняя, когда мы будем делать более поздние версии) только в том случае, если они зависят от без стека.
позвольте мне перефразировать мой вопрос, я использую 8.5 ... Моя операция делает много журналов на stdout и также отображает gui .. Можно ли передать это на переменную? и без «&» мои журналы и графический интерфейс не отображаются в exec? –
С Tcl 8.5 вы все равно можете использовать первое решение Donal, если у вас также есть расширение TclX (или его можно установить), но вместо команды [tclX pipe] (http://wiki.tcl.tk/2033) для 'chan pipe ', который встроен в Tcl 8.6. –
@ AxT_8041 Проверьте мою расширенную версию ответа. Это должно покрыть все, что вам нужно. –