シェルの小ネタ: 終了ステータス

大きめのネタが続いたので、今日は息抜きに小ネタです。

exit status

みなさんは終了ステータスについてご存知ですか?
プログラミングをやっている方には、「メイン関数の戻り値」や「exit()関数に渡す引数」のことだと言ったら通りが良いでしょうか。

int main(int argc, char *argv[])
{
    ...
    if (error_happened) {
        exit(1);
    }
    ...
    return 0;
}

一般に、正常終了の時には 0 を返し、異常終了の時には 0 以外を返すという習わしになっています。(プログラミング言語では 0 を false と扱う場合が多いと思いますが、終了ステータスに限っては常に 0 が正常終了です。)

「ここに書いた数字はどこに行ってしまうんだろう」、と疑問に思っていた方もいるかとおもいますが、この値は、そのプログラムを実行したシェルに返されているのです。

true コマンドと false コマンド

ちなみに、あまり知られていませんが、POSIX環境には true と false という「何もしない」コマンドがあります。

これらは実行しても、何の仕事をせず、何の表示も出さず、すぐに終了してしまいます。ただし、終了ステータスとして それぞれ 0 と 非0 を返す、という特徴があります。

つまり、これらは「なにもせずに、常に成功(失敗)するコマンド」なわけです。

exit status の参照

ともあれ、世の中のプログラムは、自分が正常終了したかどうかを、終了ステータスとしてシェルに伝えています。

シェルで終了ステータスを参照するには、 $? という特殊変数を、プログラムを実行した直後に使います。

$ ls -l /dev/null
crw-rw-rw- 1 root root 1, 3 2010-05-12 20:29 /dev/null

$ echo $?
0

$ ls -l /dev/nullpo
ls: /dev/nullpoにアクセスできません: No such file or directory

$ echo $?
2

$ true
0

$ false
1

とはいえ、この数字を直接参照できて嬉しいシーンはあまり多くありません。じゃぁ、どういう場面で使うのかというと、プログラムを連続で実行する時です。

AND list と OR list

シェルでは、セミコロン(:)や、and記号2つ(&&)や、or記号二つ(||)を用いることで、複数のコマンドを1行で記述できます。

$ echo hello; echo $?
hello
0

セミコロンは、単にすべてのコマンドを順に実行するだけですが、 && や || の場合、前のコマンドの終了ステータスによって、後続のコマンドを実行するかどうか選択するという機能があります。 && は前のコマンドが正常終了(つまり終了ステータスが0)の時のみ、後続のコマンドを実行し、 || は前のコマンドが異常終了(つまり終了ステータスが非0)の時のみ、後続のコマンドを実行します。

$ ls -l /dev/null && echo file exists
crw-rw-rw- 1 root root 1, 3 2010-05-12 20:29 /dev/null
file exists

$ ls -l /dev/nullpo && echo file exists
ls: /dev/nullpoにアクセスできません: No such file or directory

$ true || echo ERROR

$ false || echo ERROR
ERROR

$ false && echo SUCCEEDED || echo FAILED
FAILED

便利な使い方

たとえば、拾ってきたプログラムのソースをビルドするとき、よく、このようなコマンドを打つかと思います。

$ ./configure
$ make

まずは configure して、うまくいったら make……。

もう分かりますよね。

$ ./configure && make

うーん、惜しい。 80点。 このように書く人も本当に多いんですが、もう一歩進めて次のように書くことをおすすめします

$ ./configure && make && echo DONE

make や configure は大抵非常に大量のメッセージを出力し、しかも正常終了したかどうかがわかりにくかったりしますが、このように書いておくと、正常時は最後に DONE と表示されますので、わかりやすくなります。

また、単に make などと打ってしまった場合で、出力結果が正常終了かどうかよくわからなかった時でも、おもむろに echo $? でその結果を確かめられる、という手を知っているとちょっと得をした気分になれるでしょう。


といったところで、今日はこのへんで。

……あれ、小ネタ?