Захват вывода командной строки на win32, который еще не был сброшен - PullRequest
1 голос
/ 05 февраля 2010

(Контекст: я пытаюсь отслеживать длительный процесс из сценария Perl CGI. Он выполняет резервное копирование базы данных MSSQL, а затем 7-архивирует ее. Пока что часть резервного копирования (используя WITH STATS=1) выводит в файл, который я могу просмотреть в браузере, обновляя его каждые несколько секунд, и он работает.)

Я пытаюсь использовать утилиту командной строки 7zip, но записываю индикатор выполнения в файл. К сожалению, в отличие от резервных копий SQL, где каждый раз, когда выполняется еще один процент, он выводит еще одну строку, 7zip перематывает свои выходные данные перед выводом новых данных о ходе выполнения , так что это выглядит лучше, если вы просто используете его обычно на командная строка. Причина, по которой это вызывает сожаление, заключается в том, что обычные перенаправления с использованием >, 1> и 2> создают только пустой файл, и в нем никогда не появляется никакого вывода, за исключением >, который не выводится до тех пор, пока не выполнится задание. готово, что не очень полезно для индикатора выполнения.

Как я могу захватить этот вид вывода, либо добавив каждое изменение в% каким-либо образом к лог-файлу (чтобы я мог использовать свой существующий метод мониторинга лог-файла), просто используя хитрость командной строки (без Perl), либо использование некоторого кода Perl для захвата его непосредственно после вызова system()?

Ответы [ 3 ]

1 голос
/ 05 февраля 2010

Если вам нужно захватить вывод все сразу, то это код, который вы хотите:

$var=`echo cmd`;

Если вы хотите читать вывод построчно, тогда вам нужен этот код:

#! perl -slw
use strict;
use threads qw[ yield async ];
use threads::shared;

my( $cmd, $file ) = @ARGV;
my $done : shared = 0;
my @lines : shared;

async {
    my $pid = open my $CMD, "$cmd |" or die "$cmd : $!";
    open my $fh, '>', $file or die "$file : $!";
    while( <$CMD> ) {
        chomp;
        print $fh $_;         ## output to the file
        push @lines, $_;    ## and push it to a shared array
    }
    $done = 1;
}->detach;

my $n = 0;
while( !$done ) {
    if( @lines ) {            ## lines to be processed
        print pop @lines;   ## process them
    }
    else {
        ## Else nothing to do but wait.
        yield;
    }
}

Другой вариант - использование процесса создания Windows. Я знаю, что процесс создания Windows C / C ++ позволит вам перенаправить все стандартный вывод. Perl имеет доступ к тому же API-вызову: См. Win32 :: Process .

0 голосов
/ 10 февраля 2010

Это не ответ о том, как захватить результат, который перематывается, но это был полезный способ добиться этого, который я в итоге использовал.

Для восстановления:

  1. используйте 7za l, чтобы перечислить файлы в zip-файле и их размеры
  2. вилка 7za e с использованием open my $command
  3. отслеживайте каждый файл в том виде, в котором он указан с -s $filename, и сравнивайте его со списком
  4. когда все выходные файлы имеют полный размер, все готово

Для резервных копий:

  1. создать где-нибудь уникальный каталог
  2. вилка 7za a -w
  3. найдите файл .tmp в каталоге
  4. отслеживать его размер
  5. когда файл .tmp больше не существует, все готово

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

0 голосов
/ 05 февраля 2010

Вы можете попробовать открыть трубу , чтобы прочитать вывод 7zip.

...