MasterYodaの昼下がり

日々の備忘録的なアレ

system関数の戻り値

昔のメモを見返してたらperlのsystem関数で実行した外部コマンドのリターンコードをうまく取得できずにハマったことが書いてあるのを見つけた。新卒2年目でperlって何?美味しいの??状態であったのが思い出される。 

ハマったポイントは、リターンコードを取得してそのまま利用してたら256とか返ってきて「エッ」ってなった点。当時はsshでコマンド投げて、コマンドの実行ステータスを取ろうとしてsshのリターンコードに256ってあったっけとか思いながらmanページを小一時間眺めてた。

system関数について
参考情報:perldocの日本語訳サイトから
http://perldoc.jp/func/system

上記の説明にも、
返り値は、wait が返すプログラムの exit 状態です。実際の exit 値を得るには 右に 8 ビットシフトしてください
とある。

このことがどういうことか理解するには以下を参照すると良い
http://perldoc.jp/variable/%24%3F

perldocの説明によると、system関数の戻り値は
伝統的な Unix の wait() システムコールが返した 16 ビットのステータス
とある。

Unixのwaitシステムコールが返すステータスは、子プロセスの終了時の情報がまとめられた16ビットの情報として返される。
また上位8ビットが子プロセスが設定した終了ステータスを示すことになっている。

その為、system関数で実行した外部コマンドの戻り値を取得するには、system関数の戻り値を8ビット右シフトしなければならない。

残りの8ビットは、
そのプロセスを止めたシグナルの番号($? & 127)
コアダンプがあるかどうか($? & 128)
を示す。

サンプルコード

#!/usr/bin/perl

sub main {

$re = system("~/tmp/perl_test/return1_test.sh");
$bit_shift_re = $re >> 8; # 8ビット右シフト
print $re . "\n";
print $bit_shift_re . "\n";

}

&main($ARGV);

サンプルコード中で実行しているシェルはexit 1しているだけのテスト用のもの

実行結果

$ ./test.pl 
256
1
$