Вызов внешней программы на Perl под Windows и Linux и печать того, что она делает вживую - PullRequest
0 голосов
/ 28 января 2019

Я пытаюсь вызвать внешнюю программу, то есть unrar, из Perl и разрешить вывод ее вывода на экран во время работы.

@lin1=`cd "$wholepath_dir" & $laufwerk & unrar x -v -y "$_" ` if ($^O =~ /Win/) ;       

@lin1=`cd "$wholepath_dir"; unrar x -v -y "$_" ` if (not ($^O =~ /Win/)) ;

Этот код восстанавливает some-rar-file.rar внутри каталога.Тем не менее, это не показывает никакого прогресса.Было бы хорошо, если бы он отображал вывод unrar в реальном времени, пока происходит unraring, вместо передачи результата unrar в массив.

Есть идеи, как это сделать, как для windows, так и для linux?

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Для таких интерактивных вещей, как это, IPC::Run обычно является хорошей ставкой.

use warnings;
use strict;
use IPC::Run qw/ run new_chunker /;

my @cmd = ('yourcommand', 'arg1', 'arg2');
my (@out,@err);
run \@cmd, '>', new_chunker("\n"), sub {
        my $line = shift;
        print $line;
        push @out, $line;
    }, '2>', new_chunker("\n"), sub {
        my $line = shift;
        print STDERR $line;
        push @err, $line;
    } or die $?;

Скопировано из моего поста здесь .Я также написал о теме вызова внешних команд, с примером кода, длиной здесь .

0 голосов
/ 28 января 2019

Во-первых, обратите внимание, что окружение чего-либо в кавычках не является эффективным способом защитить его от разбора оболочки, поскольку оно может содержать сами кавычки.Лучший способ - полностью избежать синтаксического анализа оболочки, используя форму списка open / system / open3 / etc, но поскольку вы используете метасимвол оболочки &, вы не можете этого сделать.Таким образом, вы можете использовать String :: ShellQuote для предоставления строки, заключенной в кавычки для соответствующей оболочки.

Использование IPC :: Open3 :

use strict;
use warnings;
use IPC::Open3;
use String::ShellQuote;

my $quoted_dir = shell_quote $wholepath_dir;
my $quoted_file = shell_quote $_;
my $cmd = $^O =~ /Win/
  ? "cd $quoted_dir & $laufwerk & unrar x -v -y $quoted_file"
  : "cd $quoted_dir; unrar x -v -y $quoted_file";

my $pid = open3 undef, my $stdout, '>&STDERR', $cmd;
my @lines;
while (my $line = readline $stdout) {
  print $line;
  push @lines, $line;
}
waitpid $pid, 0;
my $exit_code = $? >> 8;
# you can now act on the $exit_code and the @lines of STDOUT
0 голосов
/ 28 января 2019

Это должно сделать это: это позволяет оболочке обрабатывать перенаправление для STDERR.У меня нет Windows, поэтому я не знаю, какими будут соответствующие биты в cmd.exe.

#!/usr/bin/perl
use strict;
use warnings;

sub run_command(\@$) {
    my($log, $cmd) = @_;

    my($redirect_start, $redirect_end);
    if ($^O =~ /Win/) {
        # @TODO
        $redirect_start = '???';
        $redirect_end   = '???';
    } else {
        $redirect_start = '(';
        $redirect_end   = ') 2>&1';
    }
    open(my $fh, "${redirect_start}${cmd}${redirect_end} |")
        or die "ERROR: $!\n";

    while (<$fh>) {
        push(@{ $log }, $_);
        print;
    }

    close($fh)
        or die "ERROR: $!\n";
}

my @log;
run_command(@log, 'ls dummy.*');
run_command(@log, 'ls -lht dummy.txt');

print "\nLOG:\n";
print foreach (@log);

exit 0;

Пример вывода с моей машины:

$ perl dummy.pl
dummy.c
dummy.c~
...
dummy.txt
dummy.txt~
dummy.xml
-rw-rw-r--. 1 USER USER 926 Jan 25 23:33 dummy.txt

LOG:
dummy.c
dummy.c~
...
dummy.txt
dummy.txt~
dummy.xml
-rw-rw-r--. 1 USER USER 926 Jan 25 23:33 dummy.txt

ЕслиПриведенное выше решение не является удовлетворительным, я бы посоветовал изучить IPC :: Open3 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...