このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。

Linuxコマンドの基本:シェルスクリプトのコマンドと終了ステータス

シェルスクリプトのコマンドと終了ステータス

 シェルスクリプトを理解する上で、コマンドの終了ステータスは非常に重要な概念です。if 文はコマンドの結果を基に条件分岐を行いますが、その際にコマンドの終了ステータスを利用します。ここでは、コマンドの終了ステータスとは何か、そしてそれをどのように if 文で活用するかを詳しく解説します。

コマンドの構造と終了ステータス

まず、以下の if 文の例を見てみましょう。

if [ "$1" = "ok" ]; then
 # 処理
fi

この構造を分解すると、次のようになります。

  • コマンド[
  • 引数1"$1"
  • 引数2=
  • 引数3"ok"
  • 引数4]

if の後には コマンド があり、そのコマンドの実行結果(終了ステータス)に応じて条件分岐が行われます。

終了ステータスとは

 Linux のコマンド(lsgrep など)は、実行後に終了ステータスと呼ばれる整数値を返します。この値は、特殊なシェル変数 $? を使って取得できます。

  • 正常終了:終了ステータスは 0
  • エラー終了:終了ステータスは 0 以外の値

終了ステータスの確認例

ls コマンドの終了ステータスを確認

user01@ubuntu:~$ ls
bin   ダウンロード  ドキュメント  ミュージック
snap  テンプレート  ビデオ        公開
work  デスクトップ  ピクチャ

user01@ubuntu:~$ echo $?
0  # 終了ステータスは 0(正常終了)
  • ls コマンドが正常に実行されたため、終了ステータスは 0 です。

存在しないディレクトリを指定した場合

user01@ubuntu:~$ ls /non_exist_dir
ls: cannot access '/non_exist_dir': No such file or directory

user01@ubuntu:~$ echo $?
2  # 終了ステータスは 2(エラー終了)
  • 存在しないディレクトリを指定したため、ls コマンドはエラーとなり、終了ステータスは 2 になります。

終了ステータスを表示するシェルスクリプトの作成

ステップ1:status-disp.sh の作成

user01@ubuntu:~$ nano status-disp.sh

status-disp.sh の内容

#!/bin/bash

ls /
echo "exit status = $?"

ls /non_exist_dir
echo "exit status = $?"

解説

  • ls /:ルートディレクトリの内容を表示します。
  • echo "exit status = $?":直前のコマンドの終了ステータスを表示します。
  • ls /non_exist_dir:存在しないディレクトリを指定してエラーを発生させます。
  • 再度、終了ステータスを表示します。

ステップ2:実行権限の付与

user01@ubuntu:~$ chmod +x status-disp.sh

ステップ3:スクリプトの実行

user01@ubuntu:~$ ./status-disp.sh

出力結果

bin   boot  dev  etc  home  lib  ...
(ルートディレクトリの内容が表示される)
exit status = 0
ls: cannot access '/non_exist_dir': No such file or directory
exit status = 2

解説

  • 最初の ls / は成功しているため、終了ステータスは 0
  • 次の ls /non_exist_dir は失敗しているため、終了ステータスは 2

if 文と終了ステータスの関係

if 文では、コマンドの終了ステータスを利用して条件分岐を行います。

  • 終了ステータスが 0:条件は真と判断され、then ブロックが実行されます。
  • 終了ステータスが 0 以外:条件は偽と判断され、else ブロックが実行されます。

if 文の仕組み

if コマンド; then
 # コマンドの終了ステータスが 0(真)の場合の処理
else
 # コマンドの終了ステータスが 0 以外(偽)の場合の処理
fi

[ ] コマンドの実行と終了ステータス

 [ ] はシェルの組み込みコマンドで、条件式を評価します。条件が真の場合は終了ステータス 0 を返し、偽の場合は 0 以外の値を返します。

例:条件式をコマンドとして実行

user01@ubuntu:~$ [ "$1" = "ok" ]
user01@ubuntu:~$ echo $?
1  # 引数がないため、条件は偽となり、終了ステータスは 1
  • $1"ok" でないため、条件は偽となります。

if 文でのコマンドの活用例

if 文の条件部分には、任意のコマンドを置くことができます。その終了ステータスによって、処理を分岐させます。

例:grep コマンドを使用した条件分岐

ステップ1:found-root.sh の作成

user01@ubuntu:~$ nano found-root.sh

found-root.sh の内容

#!/bin/bash

if grep -q 'root' /etc/passwd; then
    echo 'root found'
fi

解説

  • grep -q 'root' /etc/passwd/etc/passwd ファイル内に 'root' が含まれているかを検索します。-q オプションは出力を抑制し、終了ステータスのみを利用します。
  • 条件が真(root が見つかった)場合、echo 'root found' を実行します。

ステップ2:実行権限の付与

user01@ubuntu:~$ chmod +x found-root.sh

ステップ3:スクリプトの実行

user01@ubuntu:~$ ./found-root.sh
root found

解説

  • /etc/passwdroot が含まれているため、grep コマンドの終了ステータスは 0
  • したがって、if 文の条件は真となり、echo 'root found' が実行されます。

コマンドの終了ステータスを利用するポイント

  • grep -q のようなオプション-q オプションは出力を抑制し、終了ステータスのみを利用する場合に便利です。
  • 他のコマンドでも同様test コマンドやファイル検査演算子(-e-d-f など)を使って条件を評価できます。

不要となったファイルの削除

user01@ubuntu:~$ rm status-disp.sh found-root.sh

まとめ

  • 終了ステータス:コマンドが正常に終了したかどうかを示す数値。0 が正常終了、0 以外がエラー。
  • $? シェル変数:直前に実行したコマンドの終了ステータスを格納。
  • if 文の条件:コマンドの終了ステータスを利用して、条件分岐を行う。
  • [ ] コマンド:条件式を評価し、終了ステータスを返す組み込みコマンド。
  • 任意のコマンドを条件に使用可能greptest など、終了ステータスを返すコマンドを活用して柔軟な条件分岐が可能。

 これらの知識を活用して、シェルスクリプトでより高度な制御構造を実装し、効率的なスクリプトを作成していきましょう。