$の意味?(ドル疑問符)シェルスクリプト


回答:


212

これは、最後に実行されたコマンドの終了ステータスです。

例えば、コマンドは、true常にのステータスを返す0と、falseいつものステータスを返します1

true
echo $? # echoes 0
false
echo $? # echoes 1

マニュアルから:(呼び出すことによってアクセス可能 man bashシェルでで)

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

慣例により、終了ステータス0は成功を意味し、ゼロ以外の戻りステータスは失敗を意味します。終了ステータスの詳細 、ウィキペディアを

このオンラインマニュアルで確認できるように、このような特別な変数は他にもあります。https//www.gnu.org/s/bash/manual/bash.html#Special-Parameters


音符$?二つの別個のパラメータであり、$?bashの(1)のマンページに表示されません。
Josh Habdas

19

$? 最後に実行されたコマンドの終了値を返します。 echo $?その値をコンソールに出力します。ゼロは実行が成功したことを意味し、ゼロ以外の値は失敗のさまざまな理由にマップされます。

したがって、スクリプトを作成するとき。私は次の構文を使用する傾向があります

if [ $? -eq 0 ]; then
 # do something
else
 # do something else
fi

比較は等しい0か等しくないで行われます0ます。

**コメントに基づいて更新:上記のコードブロックを比較に使用しないでください。@ tripleeeのコメントと説明を参照してください。


15
いいえ、これはアンチパターンです。のようなものcmd; if [ $? -eq 0 ]; thenはすべてリファクタリングする必要がありますif cmd; then。非常に目的if(およびシェル内の他のフロー制御文は)コマンドを実行し、その終了ステータスを調べることです。
tripleee 2018年

if cmd;特にcmdが別のスクリプトを参照している場合、いくつかの条件はあまり読みにくいかもしれません。
Saurabh Ariyan

1
これは今ではさらに間違っています。[ 1 ]そして[ 0 ]、どちらも真実です。[演算子なしでは、引数が空でない文字列かどうかをチェックします。
tripleee

2
やるよvendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("Successful");') &> /dev/null;。それを一行に入れなければならないとしたら、if [ ... ]それはひどく読めないでしょう。その行の出力を変数に格納して、if [ $drupal_installed -eq 0 ]後で言うことができるようにする予定です。
サードパーティ、

1
@thirdenderこれに対する適切な解決策は、複雑なテストをシェル関数にカプセル化することです。
tripleee

12

エコー$?- 最後に実行されたコマンドの終了ステータスを示します。この終了ステータスは、ほとんどの場合、成功を意味するゼロと、失敗を示すゼロ以外の値を持つ数値になります。

-これはbashの特別なパラメーター/変数の1つです。

$?-変数「?」に格納されている値を提供します。

BASHのいくつかの同様の特別なパラメーターは、1,2、*、#です(通常、echoコマンドでは、$ 1、$ 2、$ *、$#などとして表示されます)。



5

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

理解するには$?、まずPOSIXで定義さているプロセスの終了ステータスの概念を理解する必要があります。Linuxの場合:

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

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

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

Bashコードを考えてみましょう:

$ false
$ echo $?
1

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

false.c

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

int main(void) {
    exit(1);
}

bash.c

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

int main(void) {
    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));
}

コンパイルして実行:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o bash bash.c
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o false false.c
./bash

出力:

$? = 1

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での単一角括弧と二重角括弧の違い




2

最後に実行されたunixコマンドの結果を出力します

0 implies true
1 implies false
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.