open CMD,'-|','your_command some args' or die $@;
my $line;
while (defined($line=<CMD>)) {
print $line; # Or push @table,$line or do whatever 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 an implicit 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 the child code is overloaded by an external command with parameters
die "Cannot call @CommandCall"; # Error procedure if the call will fail
}
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 something 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;
}
4条答案
按热度按时间qyzbxkaa1#
这就是反勾号的作用。从
perldoc perlfaq8
:为什么我无法获得
system()
命令的输出?您混淆了
system()
和反勾号("')的用途。system()
运行一个命令并返回退出状态信息(作为一个16位值:低7位是进程终止的信号(如果有的话),高8位是实际的退出值)。有关详细信息,请参阅
perldoc perlop
。dba5bblo2#
IPC::Run
是我最喜欢的模块。非常强大和灵活,也非常简单的小案件。bsxbgnwa3#
简单地使用类似于Bash的例子:
注意,您不会在输出中看到任何到STDOUT的输出,因为它被重定向到一个变量。
这个例子不适用于与用户交互的命令,除非你已经准备好了答案。为此,你可以使用一堆shell命令:
在 answers.txt 文件中,您应该准备好some_command的所有答案,以便正常工作。
我知道这不是最好的编程方法:)但这是实现目标的最简单方法,特别是对于Bash程序员。
当然,如果输出较大(
ls
带子目录),你不应该一次得到所有的输出。一个额外的扩展解决方案,用于处理长命令输出,而无需额外的Bash调用:
如果您使用这样的过程,您将捕获所有过程输出,并且可以逐行执行所有处理操作。祝您好运:)
t98cgbkg4#
我想运行system()而不是backticks,因为我想看到
rsync --progress
的输出。但是,我还想捕获输出,以防根据返回值出现错误。(这是用于备份脚本的)。这就是我现在使用的代码: