回答:
これは、最後に実行されたコマンドの終了ステータスです。
例えば、コマンドは、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)のマンページに表示されません。
$?
最後に実行されたコマンドの終了値を返します。 echo $?
その値をコンソールに出力します。ゼロは実行が成功したことを意味し、ゼロ以外の値は失敗のさまざまな理由にマップされます。
したがって、スクリプトを作成するとき。私は次の構文を使用する傾向があります
if [ $? -eq 0 ]; then
# do something
else
# do something else
fi
比較は等しい0
か等しくないで行われます0
ます。
**コメントに基づいて更新:上記のコードブロックを比較に使用しないでください。@ tripleeeのコメントと説明を参照してください。
cmd; if [ $? -eq 0 ]; then
はすべてリファクタリングする必要がありますif cmd; then
。非常に目的のif
(およびシェル内の他のフロー制御文は)コマンドを実行し、その終了ステータスを調べることです。
if cmd;
特にcmdが別のスクリプトを参照している場合、いくつかの条件はあまり読みにくいかもしれません。
[ 1 ]
そして[ 0 ]
、どちらも真実です。[
演算子なしでは、引数が空でない文字列かどうかをチェックします。
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 ]
後で言うことができるようにする予定です。
最小限の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での単一角括弧と二重角括弧の違い
http://www.gnu.org/s/bash/manual/bash.html#Special-Parametersから
?
Expands to the exit status of the most recently executed foreground pipeline.
参照してください。Bashのマニュアルの下で3.4.2特殊パラメータ:
?-最後に実行されたフォアグラウンドパイプラインの終了ステータスに展開されます。
$?
(変数名は "just" ?
)としてリストされていないため、見つけるのは少し難しいです。もちろん終了ステータスのセクションも参照してください;-)
ハッピーコーディング。