【发布时间】:2011-11-07 01:29:26
【问题描述】:
是什么
echo $?
在shell编程中是什么意思?
【问题讨论】:
-
上一个命令的退出状态
标签: shell scripting special-characters
是什么
echo $?
在shell编程中是什么意思?
【问题讨论】:
标签: shell scripting special-characters
这是最后执行命令的退出状态。
例如命令true总是返回0的状态,false总是返回1的状态:
true
echo $? # echoes 0
false
echo $? # echoes 1
来自手册:(可通过在您的 shell 中调用 man bash 访问)
$?扩展到最近执行的前台管道的退出状态。
按照惯例,退出状态0 表示成功,非零返回状态表示失败。了解更多关于退出状态on wikipedia。
还有其他类似的特殊变量,您可以在此在线手册中看到: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 cmets 和解释。
【讨论】:
cmd; if [ $? -eq 0 ]; then 的东西都应该重构为if cmd; then。 if(以及 shell 中的其他流控制语句)的真正目的是运行命令并检查其退出状态。
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 ]。
echo $? - 给出最近执行的命令的退出状态。这个 EXIT STATUS 很可能是一个数字,零表示 成功,任何非零值表示 失败
? - 这是 bash 中的一个特殊参数/变量。
$? - 它给出了存储在变量“?”中的值。
BASH 中一些类似的特殊参数有 1,2,*,# (通常在 echo 命令中看到为 $1 ,$2 , $* , $# 等)。
【讨论】:
它具有命令的最后状态码(退出值)。
【讨论】:
最小的 POSIX C 退出状态示例
要了解$?,您必须首先了解定义by POSIX 的进程退出状态的概念。在 Linux 中:
当进程调用exit 系统调用时,即使在进程终止后,内核也会存储传递给系统调用的值(int)。
退出系统调用由exit() ANSI C 函数调用,并且当您从main 执行return 时间接调用。
调用退出子进程(Bash)的进程,通常使用fork + exec,可以通过wait 系统调用检索子进程的退出状态
考虑一下 Bash 代码:
$ false
$ echo $?
1
C 的“等价物”是:
假.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 将 $? 设置为分叉进程的退出状态。
注意:对于像 echo 这样的内置命令,不需要生成进程,Bash 只需将 $? 设置为 0 以模拟外部进程。
标准和文档
POSIX 7 2.5.2“特殊参数”http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02:
?扩展到最近管道的十进制退出状态(请参阅管道)。
man bash“特殊参数”:
shell 专门处理几个参数。这些参数只能被引用;不允许分配给他们。 [...]
?扩展到最近执行的前台管道的退出状态。
ANSI C 和 POSIX 建议:
0 表示程序成功
其他值:程序以某种方式失败。
确切的值可以指示失败的类型。
ANSI C 没有定义任何值的含义,POSIX 指定大于 125 的值:What is the meaning of "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 ] 它的参数,另请参阅:Difference between single and double square brackets in Bash
来自http://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
?
Expands to the exit status of the most recently executed foreground pipeline.
【讨论】:
参见3.4.2 Special Parameters下的The Bash Manual:
? - 扩展到最近执行的前台管道的退出状态。
有点难找,因为它没有被列为$?(变量名是“just”?)。当然,另请参阅exit status 部分;-)
编码愉快。
【讨论】:
输出最后执行的unix命令的结果
0 implies true
1 implies false
【讨论】: