捕获的Perl系统的输出()(Capture the output of Perl system&#

2019-06-26 08:00发布

我需要运行与系统()在Perl shell命令。 例如,

system('ls')

系统调用将打印到标准输出,但我想输出捕捉到一个变量,这样我可以做进一步处理我的Perl代码。

Answer 1:

这就是反引号是。 从perldoc perlfaq8

为什么我不能得到一个命令与输出system()

你混淆的目的system()和反引号(``)。 system()运行一个命令,并返回退出状况信息(作为16位值:低7位是该处理从,如果任何死的信号,并将该高8位是实际退出值)。 反引号(``)运行命令,并返回它发送到标准输出。

 my $exit_status = system("mail-users"); my $output_string = `ls`; 

perldoc perlop更多的细节。



Answer 2:

IPC::Run是我最喜欢这样的任务模块。 非常强大和灵活,也为小的情况下平凡简单。

use IPC::Run 'run';

run [ "command", "arguments", "here" ], ">", \my $stdout;

# Now $stdout contains output


Answer 3:

只需使用类似bash的例子:

    $variable=`some_command some args`;

就这样。 请注意,你不会在输出看到任何印刷到标准输出,因为这会被重定向到变量。 这个例子是不可用于与用户进行交互,除非你已经准备好答案命令。 对,你可以使用类似这样使用shell命令的堆栈:

    $variable=`cat answers.txt|some_command some args`;

answers.txt文件中,你应该准备回答所有的some_command正常工作。

我知道这是不是最佳编程方式:)但是这是如何实现的目标,特别是对于bash程序员最简单的方法。

当然,如果输出较大(与子目录LS),你不应该让所有的输出一次。 通过同样的方式读取命令,当你阅读regullar文件:

open CMD,'-|','your_command some args' or die $@;
my $line;
while (defined($line=<CMD>)) {
    print $line; #or push @table,$line or do whatewer what you want processing line by line
}
close CMD;

为无需额外的bash呼叫处理长命令输出附加扩展的解决方案:

my @CommandCall=qw(find / -type d); #some example single command
my $commandSTDOUT; #file handler
my $pid=open($commandSTDOUT),'-|'); #there will be implict fork!
if ($pid) {
    #parent side
    my $singleLine;
    while(defined($singleline=<$commandSTDOUT>)) {
        chomp $line; #typically we don't need EOL
        do_some_processing_with($line);
    };
    close $commandSTDOUT; #in this place $? will be set for capture
    $exitcode=$? >> 8;
    do_something_with_exit_code($exitcode);
} else {
    #child side, there you really calls a command
    open STDERR, '>>&', 'STDOUT'; #redirect stderr to stdout if needed, it works only for child, remember about fork
    exec(@CommandCall); #at this point child code is overloaded by external command with parameters
    die "Cannot call @CommandCall"; #error procedure if call will fail
}

如果你使用的程序一样,你将捕获所有的过程输出,并且可以通过线做的一切加工生产线。 祝好运 :)



Answer 4:

我想跑系统(),而不是反引号的,因为我想看到的输出rsync --progress 。 不过,我也想在情况取决于返回值出现错误捕获输出。 (这是一个备份脚本)。 这是我现在使用的是什么:

use File::Temp qw(tempfile);
use Term::ANSIColor qw(colored colorstrip);



sub mysystem {
    my $cmd = shift; #"rsync -avz --progress -h $fullfile $copyfile";
    my ($fh, $filename) = tempfile();
    # http://stackoverflow.com/a/6872163/2923406
    # I want to have rsync progress output on the terminal AND capture it in case of error.
    # Need to use pipefail because 'tee' would be the last cmd otherwise and hence $? would be wrong.
    my @cmd = ("bash", "-c", "set -o pipefail && $cmd 2>&1 | tee $filename");
    my $ret = system(@cmd);
    my $outerr = join('', <$fh>);
    if ($ret != 0) {
        logit(colored("ERROR: Could not execute command: $cmd", "red"));
        logit(colored("ERROR: stdout+stderr = $outerr", "red"));
        logit(colored("ERROR: \$? = $?, \$! = $!", "red"));
    }
    close $fh;
    unlink($filename);
    return $ret;
}

# and logit() is sth like:
sub logit {
    my $s = shift;
    my ($logsec,$logmin,$loghour,$logmday,$logmon,$logyear,$logwday,$logyday,$logisdst)=localtime(time);
    $logyear += 1900;
    my $logtimestamp = sprintf("%4d-%02d-%02d %02d:%02d:%02d",$logyear,$logmon+1,$logmday,$loghour,$logmin,$logsec);
    my $msg = "$logtimestamp $s\n";
    print $msg;
    open LOG, ">>$LOGFILE";
    print LOG colorstrip($msg);
    close LOG;
}

编辑:使用unlink ,而不是system("rm ...")



Answer 5:

我用如下操作:

print(system("ls"));


文章来源: Capture the output of Perl system()
标签: perl shell