私は次の行を使用して、機能する簡単なシステムコールを作成しています。
system ("mkdir -p Purged") or die "Failed to mkdir." ;
スクリプトを実行するとシステムコールが実行され、Purgedというディレクトリが見つかりますが、エラーメッセージが出力され、スクリプトが終了します。私の構文の何が問題になっていますか?
それは少し紛らわしいでしょうね。 --Leonardo Herrera on 池上さんの答え
はい、system
コマンドがPerlでtrueとfalseを反転し、次のような楽しいロジックを作成することは混乱を招きます。
if ( system qw($command) ) {
die qq(Aw... If failed);
}
else {
say qq(Hooray! It worked!);
}
しかし、system
コマンドがこれを行う理由は理解できます。 Unixでは、終了ステータスがゼロの場合はプログラムが機能したことを意味し、ゼロ以外のステータスではsystem
呼び出しが失敗した理由を知ることができます。たぶんあなたが呼んでいたプログラムは存在しません。たぶん、プログラムは期待通りに機能したのでしょう。たとえば、grep
が機能するが、一致する行がなかった場合、grep
は1
の終了コードを返します。 grep
が0、1、または1より大きい戻りコードを返す場合を区別することをお勧めします。 (はい、Perlプログラムでgrep
へのシステムコールを使用するのはばかげていることを私は知っていますが、それは私が考えることができる最初の例です)。
偶然の混乱を防ぐために、system
の出力を直接テストする代わりに、system
コマンドの終了ステータスを保持する変数を作成します。
my $error = system qw($command);
if ($error) {
die qq(Aw... It failed);
}
else {
say qq(Hooray! It worked!);
}
これは完全に不要であり、Perlを使用する人は、system
がPerlのtrueおよびfalseの定義を逆にすることを知っておく必要があります。 、しかし、朝にコーヒーを飲んでいなかった場合、他の誰かのコードを調べているときに、コーヒーを見逃す可能性があります。この小さなステップを実行すると、プログラムが少し論理的に見えるようになります。
system のPerldocは、システムコマンドの出力をテストして、何が起こったかを正確に確認できるコードを提供します。 (エラーが発生した場合、またはシステム割り込み信号によってsystem
呼び出しが強制終了された場合)。何が悪かったのかを理解するためにsystem
の戻り値を調べる必要があるかどうかを知るのは良いことです。
system
は、呼び出すコマンドの終了ステータスを返します。シェルでは、ゼロ終了ステータスは成功を意味します。ロジックを逆にする必要があります。
0 == system qw(mkdir -p Purged) or die "Failed to create the dir\n";
system
は成功すると_0
_を返すため、and
ではなくor
が必要です。
参照:use autodie qw( system );
言及されていないものを追加しますが、それに付属し、静かに物事を台無しにする可能性があります。
system
が 'zero-or-not'を返すと、コマンド自体がシェルまたはexecvp
によって正常に実行されたかどうかがわかります。 0
は、コマンドが実行に成功したことを意味しません。
ゼロ以外の返品の場合、詳細については$?
を解凍する必要があります。これを行う方法については、 system を参照してください。 1つは、コマンドの実際の終了コードは$? >> 8
です。これは、実行されたプログラムがその終了時に通信するように設計されたものです。
全体として、あなたはの効果のために何かをしたいと思うかもしれません
sub run_system {
my ($cmd, @other_agrs) = @_; # may do more via @other_args
my ($cmdref, $sys_ret) = (ref $cmd, 0); # LIST or scalar invocation?
if ($cmdref eq 'ARRAY') {
$sys_ret = system(@$cmd);
}
elsif (not $cmdref) {
$sys_ret = system($cmd);
}
else { Carp::carp "Invocation error, got $cmdref" }
return 1 if $sys_ret == 0;
# Still here? The rest is error handling.
Carp::carp "Trouble with 'system($cmd)': $?";
print "Got exit " . ($? >> 8) . " from $cmd\n";
return 0; # or die (but then design changes)
}
これは、コード内でsystem == 0 or do { ... };
などとして実行できますが、この方法では、エラー処理をより簡単に改善できる小さなライブラリがあり、最終的にはモジュールに切り替えて外部コマンドなどを管理することにします。 、ユーザーレベルの機能であるため、成功するとtrueが返されることは理にかなっています(system
の設計は変更していません)。
さらに、この場合、mkdir -p
は静かであることを意味し、場合によっては、それができないときに何も言わないことがあります。これはもちろん設計によるものですが、注意する必要があります。
ワンラインソリューション:
system("if printf '' > tmp.txt; then exit 1; else exit 0; fi ;") or die("unable to clobber tmp.txt");