Запуск команд оболочки в фоновом режиме в процедуре tcl

Я пытаюсь создать tcl proc, которому передается команда оболочки в качестве аргумента, а затем открывается временный файл и записывает отформатированную строку во временный файл, после чего выполняется команда оболочки в фоновом режиме и сохраняется вывод во временный файл также.

Запуск команды в фоновом режиме заключается в том, что процесс может быть вызван сразу после этого с переданным ему другим аргументом, записывающим в другой файл. Таким образом, выполнение сотни таких команд не должно занимать столько времени, сколько потребовалось бы их последовательному выполнению. Наконец, несколько временных файлов можно объединить в один файл.

Это псевдокод того, что я пытаюсь сделать.

proc runthis { args }  
{ 
    set date_str [ exec date {+%Y%m%d-%H%M%S} ]
    set tempFile ${date_str}.txt
    set output [ open $tempFile a+ ]
    set command [concat exec $args]
    puts $output "### Running $args ... ###"   

    << Run the command in background and store output to tempFile >>
}

Но как мне убедиться, что фон задачи выполнен правильно? Что нужно сделать, чтобы обеспечить правильное закрытие нескольких временных файлов?

Любая помощь приветствуется. Я новичок в tcl и пытаюсь понять это. Я читал об использовании потоков в tcl, но я работаю с более старой версией tcl, которая не поддерживает потоки.


person div310    schedule 16.12.2012    source источник
comment
Во-первых, открывающая фигурная скобка тела процедуры должна располагаться на той же логической строке, что и сама proc (ну, между ними могут быть заключены символы новой строки в кавычках, например, в списке аргументов или с обратной косой чертой, но это уточнение, на которое не обращает внимания большинство людей). не заморачиваюсь).   -  person Donal Fellows    schedule 17.12.2012
comment
Во-вторых, вы можете использовать clock format и clock seconds для выполнения работы exec date. Имейте в виду, что для разделения вывода из разных прогонов вам также нужен порядковый номер (конечно, если два прогона запускаются в одну и ту же секунду).   -  person Donal Fellows    schedule 17.12.2012
comment
Рассмотрите возможность использования менее неуклюжего подхода к созданию временных файлов. Эта вики-страница содержит хороший обзор опций (file tempname начиная с версии 8.6 или mkstemp(3)-эмуляция кода; как личный опыт, я считаю, что версия Стью вполне подходит для старых Tcls).   -  person kostix    schedule 18.12.2012


Ответы (1)


Как насчет:

proc runthis { args }  { 
    set date_str [clock format [clock seconds] -format {+%Y%m%d-%H%M%S}]
    set tempFile ${date_str}.txt
    set output [ open $tempFile a+ ]
    puts $output "### Running $args ... ###"   
    close $output

    exec {*}$args >> $tempFile &
}

См. http://tcl.tk/man/tcl8.5/TclCmd/exec.htm

Поскольку у вас, похоже, старый Tcl, замените

    exec {*}$args >> $tempFile &

с участием

    eval exec [linsert $args 0 exec] >> $tempFile &
person glenn jackman    schedule 17.12.2012
comment
Вам также нужен способ определить, когда конвейер закончился. К счастью, результатом фона exec является список идентификаторов процессов порожденных подпроцессов… - person Donal Fellows; 17.12.2012
comment
Я получаю эту ошибку с дополнительными символами после закрывающей скобки, когда использую команду: exec {*}$args ›› $tempFile & - person div310; 17.12.2012
comment
В этом случае, что нам нужно сделать после завершения конвейера? нам нужно что-то закрыть/промыть? Также, если exec возвращает идентификатор процесса, как мне его получить? - person div310; 17.12.2012
comment
set pid [exec ...] - Простая подстановка команд. Если вашей программе/скрипту ничего не нужно делать после завершения подпроцесса, то все в порядке. Если вы получаете дополнительные символы ошибки после закрывающей скобки, возможно, вы используете старую версию Tcl (‹8.5). Расширение слова {*} было добавлено в Tcl 8.5. - person Johannes Kuhn; 17.12.2012
comment
Эта строка: eval exec [linsert $args exec] ›› $tempFile & Выдает эту ошибку: -wrong # args: должен быть элемент индекса списка linsert ?element ...? - person div310; 19.12.2012
comment
Я объединил команду, а затем прогнал ее через eval. И это нормально работает :) - person div310; 19.12.2012
comment
В конце прогона я хочу объединить все отдельные временные файлы в один гигантский файл. Но на этом этапе, я думаю, мне нужно проверить, все ли фоновые процессы завершили выполнение, иначе я рискую получить неполные данные. Вероятно, здесь мне придется использовать идентификатор процесса порожденных подпроцессов, верно? - person div310; 19.12.2012