Как мне выполнить внешний скрипт при захвате как кода вывода, так и кода выхода в Perl? - PullRequest
7 голосов
/ 05 февраля 2010

Я пытаюсь проверить наличие тега SVN из скрипта Perl. Поэтому я пытаюсь вызвать svn info $url, прочитать код завершения и подавить стандартный вывод и стандартные потоки ошибок. Тем не менее, я изо всех сил пытаюсь сделать это элегантно (возможно, есть лучшие способы спросить SVN о теге, но здесь дело не в этом):

my $output = `svn info $url/tags/$tag`;

Подавляет вывод при помещении его в $output. Код выхода потерян.

my $output = `svn info $url/tags/$tag 2>&1`;

Это подавляет STDERR и STDOUT и помещает их в $output. Код выхода снова потерян.

my $exitcode = system("svn", "info", "$url/tags/$tag");

Это ловит код выхода, но фактический вывод и поток ошибок видны пользователю.

open( STDERR, q{>}, "/dev/null" );
open my $fh, q{>}, "/dev/null";
select($fh);
if (system("svn", "info", "$url/tags/$tag") != 0) {
   select(STDOUT);
   print ("Tag doesn't exist!");
   do_something_with_exit();
}
select(STDOUT);
print "Exit code: $exitcode";

Это убивает STDOUT и STDERR и ловит код выхода, но это уродливо, потому что мне придется помнить, чтобы переключить STDOUT обратно в исходное состояние.

Итак, есть ли более элегантное решение?

Ответы [ 4 ]

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

Попробуйте использовать $? .e.g.

my $output = `svn info $url/tags/$tag`;
my $extcode = $?>>8;
3 голосов
/ 05 февраля 2010

Что произойдет, когда вы попробуете это с IPC :: System :: Simple ? Этот модуль обрабатывает большинство деталей таких проблем:

 use IPC::System::Simple qw(capturex $EXITVAL);

 my $output = capturex( "some_command", @args );
 my $exit   = $EXITVAL;
1 голос
/ 05 февраля 2010
 my $output = `svn info $url/tags/$tag 2>&1`;

Это подавляет как STDERR, так и STDOUT и помещает их обоих в $ output. Код выхода снова потерян

Вы уверены, что код выхода утерян? Когда я пытаюсь это сделать, я получаю код выхода в $?.

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

Модуль IPC :: Run3 дает очень детальный контроль над входом и выходом.

use IPC::Run3;
run3 \@cmd, \$in, \$out, \$err;

Вы можете передать одну и ту же переменную \$out и \$err, и она будет делать то, что вы ожидаете, объединяя оба потока. Ввод не требуется, поэтому вы можете передать либо undef ("наследовать от родительского процесса"), либо \undef ("закрытый дескриптор файла".)

IPC::Run3::run3() возвращает true или false в зависимости от кода выхода и оставляет фактический код завершения дочернего процесса в $? согласно perlvar.

В вашем случае вы бы запустили

use IPC::Run3

my @cmd = ('svn', 'info', "$url/tags/$tag");
my $out;
my $rv = run3(\@cmd, \undef, \$out, \$out);
if ($rv) {
    # process $out
}
else {
    die "error: $@";
}
...