31

Perl で system() を使用してシェル コマンドを実行する必要があります。例えば、

system('ls')

システム コールはSTDOUTに出力されますが、Perl コードで将来の処理を実行できるように、出力を変数にキャプチャしたいと考えています。

4

4 に答える 4

45

それがバックティックの目的です。からperldoc perlfaq8:

でコマンドの出力を取得できないのはなぜsystem()ですか?

system()とバッククォート (``)の目的を混同しています。system() コマンドを実行し、終了ステータス情報を返します (16 ビット値として: 下位 7 ビットは、プロセスが停止した場合のシグナルであり、上位 8 ビットは実際の終了値です)。バッククォート (``) はコマンドを実行し、STDOUT に送信したものを返します。

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

詳細については、を参照perldoc perlopしてください。

于 2012-07-17T01:48:00.880 に答える
20

IPC::Runこの種のタスクの私のお気に入りのモジュールです。非常に強力で柔軟性があり、小さなケースでは自明なほど単純です。

use IPC::Run 'run';

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

# Now $stdout contains output
于 2012-07-17T11:14:18.647 に答える
2

の出力を見たかったので、バッククォートの代わりに 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 ...")

于 2015-02-24T12:22:14.247 に答える