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

Linuxコマンドの基本:シェル関数の終了ステータス

シェル関数の終了ステータス

 シェル関数は通常のコマンドと同様に、終了ステータスを返します。通常、シェル関数内で最後に実行されたコマンドの終了ステータスが、そのまま関数の終了ステータスとなります。しかし、特定の条件で関数の処理を終了し、明示的に終了ステータスを返したい場合があります。そのような場合、シェルの組み込みコマンドである return を使用します。

return コマンドの使用方法

【書式】
return <終了ステータス>

  • <終了ステータス>:0〜255の整数値。0は正常終了、1以上はエラーを示します。

 return コマンドを実行すると、その時点でシェル関数の処理が終了し、呼び出し元に制御が戻ります。

例1:ユーザーの存在確認を行う関数(check_user.sh

 このスクリプトでは、指定したユーザーがシステム上に存在するかを確認します。存在しない場合は終了ステータス1を返します。

ステップ1:スクリプトの作成

user01@ubuntu:~$ nano check_user.sh

check_user.sh の内容

#!/bin/bash

check_user() {
    if id "$1" > /dev/null 2>&1; then
        echo "ユーザー '$1' は存在します。"
        return 0
    else
        echo "ユーザー '$1' は存在しません。"
        return 1
    fi
}

# 関数の呼び出し
check_user "$1"

# 終了ステータスの確認
if [ $? -eq 0 ]; then
    echo "正常終了しました。"
else
    echo "エラーが発生しました。"
fi
スクリプト全体の解説
  • check_user 関数の定義
    id "$1" コマンドでユーザーの存在を確認します。
     ・ユーザーが存在する場合は、終了ステータス0を返します。
     ・存在しない場合は、終了ステータス1を返します。
  • 関数の呼び出し
    ・スクリプトの第1引数$1を関数に渡します。
  • 終了ステータスの確認
    ・関数の終了ステータスを$?で取得し、条件分岐で結果を表示します。
if id "$1" >/dev/null 2>&1; then の解説

 「if id "$1" >/dev/null 2>&1; then」を部分ごとに解説します。

1.id "$1"

id コマンド

 id コマンドは、指定したユーザーのユーザーID(UID)、グループID(GID)、所属グループなどの情報を表示します。

例:idコマンドの出力

$ id root
uid=0(root) gid=0(root) groups=0(root)

"$1"

  • "$1" はシェルスクリプトまたは関数に渡された最初の引数を参照します。
  • 例えば、スクリプトを ./script.sh root と実行した場合、$1root になります。

2.>/dev/null 2>&1

  • >/dev/null
    ・コマンドの標準出力(stdout)を /dev/null にリダイレクトします。/dev/null は特殊なデバイスファイルで、書き込まれたデータはすべて破棄されます。
    ・これにより、id コマンドの出力が画面に表示されなくなります。
  • 2>&1
    ・コマンドの標準エラー出力(stderr)を標準出力(stdout)にリダイレクトします。
    ・既に標準出力は /dev/null にリダイレクトされているため、標準エラーも /dev/null にリダイレクトされ、表示されなくなります。
  • まとめ
    >/dev/null 2>&1 とすることで、id コマンドの出力とエラーメッセージの両方を非表示にしています。

3.if ...; then

  • 終了ステータスの評価
    ・コマンドが正常に実行されると終了ステータスとして 0 を返し、エラーが発生すると 0 以外の値を返します。
    if 文では、指定したコマンドの終了ステータスが 0 であれば真と判断し、then ブロックを実行します。
  • id "$1" の場合
    ・ユーザーが存在する場合:id コマンドは正常に実行され、終了ステータス 0 を返します。
    ・ユーザーが存在しない場合:id コマンドはエラーとなり、終了ステータス 1 を返します。

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

user01@ubuntu:~$ chmod +x check_user.sh

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

ユーザーが存在する場合

user01@ubuntu:~$ ./check_user.sh root
ユーザー 'root' は存在します。
正常終了しました。

ユーザーが存在しない場合

user01@ubuntu:~$ ./check_user.sh unknownuser
ユーザー 'unknownuser' は存在しません。
エラーが発生しました。

解説

  • 存在するユーザー名を引数に指定すると、return 0が実行され、正常終了となります。
  • 存在しないユーザー名を引数に指定すると、return 1が実行され、エラーが発生します。

例2:ファイルの読み取り権限を確認する関数(check_file_permission.sh

 このスクリプトでは、指定したファイルに対して読み取り権限があるかを確認します。読み取り権限がない場合は終了ステータス1を返します。

ステップ1:スクリプトの作成

user01@ubuntu:~$ nano check_file_permission.sh

check_file_permission.sh の内容

#!/bin/bash

check_permission() {
    if [ ! -e "$1" ]; then
        echo "ファイル '$1' は存在しません。"
        return 2
    elif [ -r "$1" ]; then
        echo "ファイル '$1' は読み取り可能です。"
        return 0
    else
        echo "ファイル '$1' は読み取り権限がありません。"
        return 1
    fi
}

# 関数の呼び出し
check_permission "$1"

# 終了ステータスの確認
case $? in
    0)
        echo "正常終了しました。"
        ;;
    1)
        echo "エラー: 読み取り権限がありません。"
        ;;
    2)
        echo "エラー: ファイルが存在しません。"
        ;;
    *)
        echo "不明なエラーが発生しました。"
        ;;
esac

解説

  • check_permission 関数の定義
    ・ファイルが存在しない場合、return 2を実行します。
    ・ファイルが読み取り可能な場合、return 0を実行します。
    ・読み取り権限がない場合、return 1を実行します。
  • 関数の呼び出し
    ・スクリプトの第1引数$1を関数に渡します。
  • 終了ステータスの確認
    ・関数の終了ステータスを$?で取得し、case文で結果に応じたメッセージを表示します。

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

user01@ubuntu:~$ chmod +x check_file_permission.sh

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

ファイルが存在し、読み取り可能な場合

user01@ubuntu:~$ ./check_file_permission.sh /etc/passwd
ファイル '/etc/passwd' は読み取り可能です。
正常終了しました。

ファイルが存在し、読み取り権限がない場合

テスト用のファイルを作成し、読み取り権限を外します。

user01@ubuntu:~$ touch no_read.txt
user01@ubuntu:~$ chmod 000 no_read.txt
user01@ubuntu:~$ ./check_file_permission.sh no_read.txt
ファイル 'no_read.txt' は読み取り権限がありません。
エラー: 読み取り権限がありません。

ファイルが存在しない場合

user01@ubuntu:~$ ./check_file_permission.sh nonexistent.txt
ファイル 'nonexistent.txt' は存在しません。
エラー: ファイルが存在しません

解説

  • ファイルの存在や権限に応じて、関数が適切な終了ステータスを返し、それに応じたメッセージが表示されます。

ここで作成したファイルの削除

user01@ubuntu:~$ rm check_user.sh check_file_permission.sh no_read.txt
rm: 書き込み保護されたファイル 通常の空ファイル 'no_read.txt' を削除しますか? y

まとめ

  • シェル関数の終了ステータスは、関数内で最後に実行されたコマンドの終了ステータスがそのまま返されます。
  • return コマンドを使用することで、任意の終了ステータスを明示的に返し、関数の処理を終了できます。
  • 関数の終了ステータスを利用することで、呼び出し元で関数の実行結果を判定し、適切なエラー処理や分岐を行うことができます。
  • ここで作成したスクリプトを通じて、シェル関数の終了ステータスの使い方とエラーハンドリングの方法を学びました。

 シェル関数の終了ステータスを適切に扱うことで、スクリプト全体の信頼性と保守性を高めることができます。これらの知識を活用して、より高度なシェルスクリプトを作成してみてください。