web-dev-qa-db-ja.com

$とは何ですか? (ドルの疑問符)シェルスクリプトの変数?

シェルスクリプトを学習しようとしていますが、他の人のコードを理解する必要があります。 $?変数ホールドとは何ですか?句読文字をブロックするため、Googleで回答を検索できません。

229
David Mulder

$?は、最後に実行されたコマンドの戻り値を見つけるために使用されます。シェルで次のことを試してください。

ls somefile
echo $?

somefileが存在する場合(ファイルかディレクトリかに関係なく)、lsコマンドによってスローされる戻り値を取得します。これは、0(デフォルトの「成功」戻り値)でなければなりません。存在しない場合は、0以外の数値を取得する必要があります。正確な数値はプログラムによって異なります。

多くのプログラムでは、対応するマニュアルページで数字とその意味を見つけることができます。これらは通常「終了ステータス」として説明され、独自のセクションを持つ場合があります。

219
pooamlairaj

これは、最後に実行された機能/プログラム/コマンドの終了ステータスです。参照する:

45
Dor

以前に実行されたプロセスの戻り値。

10.4プログラムの戻り値の取得

Bashでは、プログラムの戻り値は$?という特別な変数に格納されます。

これは、プログラムの戻り値をキャプチャする方法を示しています。ディレクトリdadaが存在しないと仮定しています。 (これはマイクによっても提案されました)

        #!/bin/bash
        cd /dada &> /dev/null
        echo rv: $?
        cd $(pwd) &> /dev/null
        echo rv: $?

詳細については、 Bash Programming Manual を参照してください。

18
user405725

最小限のPOSIX C終了ステータスの例

$?を理解するには、最初にプロセス終了ステータスの概念を理解する必要があります。

Linuxの場合:

  • プロセスがexitシステムコールを呼び出すと、カーネルはプロセスが終了した後でもシステムコールに渡された値を保存します。

    Exitシステムコールは、exit() ANSI C関数によって呼び出され、returnからmainを実行すると間接的に呼び出されます。

  • 多くの場合fork + execで終了する子プロセス(Bash)を呼び出したプロセスは、waitシステムコールで子の終了ステータスを取得できます。

Bashコードを検討してください。

$ false
$ echo $?
1

Cの「同等」は次のとおりです。

false.c:

#include <stdlib.h> /* exit */

int main() {
    exit(1);
}

bash.c:

#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main() {
    if (fork() == 0) {
        /* Call false. */
        execl("./false", "./false", (char *)NULL);
    }
    int status;
    /* Wait for a child to finish. */
    wait(&status);
    /* Status encodes multiple fields,
     * we need WEXITSTATUS to get the exit status:
     * http://stackoverflow.com/questions/3659616/returning-exit-code-from-child
     **/
    printf("$? = %d\n", WEXITSTATUS(status));
}

Bashでは、Enterキーを押すと、上記のようにfork + exec + waitが発生し、bashは$?をforkされたプロセスの終了ステータスに設定します。

注:echoなどの組み込みコマンドの場合、プロセスを生成する必要はなく、Bashは$?を0に設定するだけで外部プロセスをシミュレートします。

標準とドキュメント

POSIX 7 2.5.2 "特殊パラメーター" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02

?最新のパイプラインの10進終了ステータスに展開します(パイプラインを参照)。

man bash「特別なパラメーター」:

シェルはいくつかのパラメーターを特別に扱います。これらのパラメーターは参照のみ可能です。それらへの割り当ては許可されていません。 [...]

?最後に実行されたフォアグラウンドパイプラインの終了ステータスに展開します。

ANSI CおよびPOSIXは、次のことを推奨します。

  • 0は、プログラムが成功したことを意味します

  • 他の値:プログラムはなんとか失敗しました。

    正確な値は、障害のタイプを示している可能性があります。

    ANSI Cは値の意味を定義せず、POSIXは125より大きい値を指定します: 「POSIX」の意味は何ですか?

Bashはifの終了ステータスを使用します

Bashでは、次のように、終了ステータス$?を暗黙的に使用してifステートメントを制御します。

if true; then
  :
fi

trueは、0を返すだけのプログラムです。

上記は次と同等です:

true
result=$?
if [ $result = 0 ]; then
  :
fi

そして:

if [ 1 = 1 ]; then
  :
fi

[は奇妙な名前(およびそのように動作するBashビルトイン)を持つ単なるプログラムであり、1 = 1 ]その引数も参照してください。 単一および二重の正方形の違いBashの括弧

$?最後に実行されたコマンドの結果(終了コード)です。

9
marcelog

$?は、一連のコマンドをデイジーチェーン接続できるように、コマンドの終了ステータスです。

command1 && command2 && command3

command2command1'ssuccess (0)を生成する場合、$?が実行され、command3$?successを生成する場合、command2が実行されます

4

最後に実行されたコマンドの返されたエラーコードです。 0 =成功

4
Wulf

set -eが使用されている場合にスクリプトが終了する場合のデバッグに適しています。たとえば、コマンドの後にecho $?を置いて終了させ、返されたエラー値を確認します。

2
lukmac

最後のコマンドの終了コードが実行されました。

2
Matt