Perl で system() を使用してシェル コマンドを実行する必要があります。例えば、
system('ls')
システム コールはSTDOUTに出力されますが、Perl コードで将来の処理を実行できるように、出力を変数にキャプチャしたいと考えています。
それがバックティックの目的です。からperldoc perlfaq8
:
でコマンドの出力を取得できないのはなぜ
system()
ですか?
system()
とバッククォート (``)の目的を混同しています。system()
コマンドを実行し、終了ステータス情報を返します (16 ビット値として: 下位 7 ビットは、プロセスが停止した場合のシグナルであり、上位 8 ビットは実際の終了値です)。バッククォート (``) はコマンドを実行し、STDOUT に送信したものを返します。my $exit_status = system("mail-users"); my $output_string = `ls`;
詳細については、を参照perldoc perlop
してください。
IPC::Run
この種のタスクの私のお気に入りのモジュールです。非常に強力で柔軟性があり、小さなケースでは自明なほど単純です。
use IPC::Run 'run';
run [ "command", "arguments", "here" ], ">", \my $stdout;
# Now $stdout contains output
の出力を見たかったので、バッククォートの代わりに system() を実行したかったのです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 ...")