O que
echo $?
significa em programação shell?
O que
echo $?
significa em programação shell?
Respostas:
Este é o status de saída do último comando executado.
Por exemplo, o comando true
sempre retorna um status de 0
e false
sempre retorna um status de 1
:
true
echo $? # echoes 0
false
echo $? # echoes 1
Do manual: (acessível chamando man bash
no seu shell)
$?
Expande para o status de saída do pipeline de primeiro plano executado mais recentemente.
Por convenção, um status de saída 0
significa sucesso e status de retorno diferente de zero significa falha. Saiba mais sobre os status de saída na wikipedia .
Existem outras variáveis especiais como essa, como você pode ver neste manual on-line: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
$
e ?
são dois parâmetros distintos e $?
não aparece na página de manual do bash (1).
$?
retorna o valor de saída do último comando executado. echo $?
imprime esse valor no console. zero implica uma execução bem-sucedida, enquanto valores diferentes de zero são mapeados para vários motivos de falha.
Portanto, ao criar scripts; Costumo usar a seguinte sintaxe
if [ $? -eq 0 ]; then
# do something
else
# do something else
fi
A comparação deve ser feita em iguais a 0
ou não 0
.
** Atualização com base no comentário: idealmente, você não deve usar o bloco de código acima para comparação, consulte os comentários e explicações do @tripleee.
cmd; if [ $? -eq 0 ]; then
deve ser refatorada para if cmd; then
. O próprio propósito de if
(e as outras instruções de controle de fluxo no shell) é para executar um comando e examinar seu estado de saída.
if cmd;
pode não ser muito legível em algumas condições, especialmente quando cmd se refere a outro script.
[ 1 ]
e [ 0 ]
são ambos verdadeiros; [
sem um operador verifica se o argumento é uma sequência não vazia.
vendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("Successful");') &> /dev/null;
. Se eu tivesse que colocar isso em uma única linha if [ ... ]
, seria terrivelmente ilegível. Eu pretendo armazenar a saída dessa linha em uma variável, para que eu possa dizer if [ $drupal_installed -eq 0 ]
mais tarde.
eco $? - Dá o EXIT STATUS do comando executado mais recentemente . Esse EXIT STATUS provavelmente seria um número com ZERO implicando Success e qualquer valor NÃO-ZERO indicando Failure
? - Este é um parâmetro / variável especial no bash.
$? - Fornece o valor armazenado na variável "?".
Alguns parâmetros especiais semelhantes no BASH são 1,2, *, # (normalmente vistos no comando echo como $ 1, $ 2, $ *, $ #, etc.).
Possui o último código de status (valor de saída) de um comando.
Exemplo mínimo de status de saída do POSIX C
Para entender $?
, você deve primeiro entender o conceito de status de saída do processo definido pelo POSIX . No Linux:
quando um processo chama a chamada do exit
sistema, o kernel armazena o valor passado para a chamada do sistema (an int
) mesmo depois que o processo morre.
A chamada de sistema exit é chamada pela exit()
função ANSI C e, indiretamente, quando você faz return
a partir main
.
o processo que chamou o processo filho de saída (Bash), geralmente com fork
+ exec
, pode recuperar o status de saída do filho com a wait
chamada do sistema
Considere o código Bash:
$ false
$ echo $?
1
OC "equivalente" é:
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));
}
Compile e execute:
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
Resultado:
$? = 1
No Bash, quando você pressiona enter, um fork + exec + wait acontece como acima, e o bash define $?
o status de saída do processo bifurcado.
Nota: para comandos internos echo
, como , um processo não precisa ser gerado, e o Bash apenas define $?
como 0 para simular um processo externo.
Normas e documentação
POSIX 7 2.5.2 "Parâmetros especiais" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :
? Expande para o status de saída decimal do pipeline mais recente (consulte Pipelines).
man bash
"Parâmetros especiais":
O shell trata vários parâmetros especialmente. Esses parâmetros podem ser referenciados apenas; a atribuição a eles não é permitida. [...]
? Expande para o status de saída do pipeline de primeiro plano executado mais recentemente.
O ANSI C e o POSIX recomendam que:
0
significa que o programa foi bem sucedido
outros valores: o programa falhou de alguma forma.
O valor exato pode indicar o tipo de falha.
O ANSI C não define o significado de quaisquer valores e o POSIX especifica valores maiores que 125: Qual é o significado de "POSIX"?
O Bash usa o status de saída para if
No Bash, geralmente usamos o status de saída $?
implicitamente para controlar if
instruções como em:
if true; then
:
fi
Onde true
é um programa que apenas retorna 0.
O acima é equivalente a:
true
result=$?
if [ $result = 0 ]; then
:
fi
E em:
if [ 1 = 1 ]; then
:
fi
[
é apenas um programa com um nome estranho (e o Bash incorporado que se comporta como ele) e 1 = 1 ]
seus argumentos, veja também: Diferença entre colchetes simples e duplos no Bash
Em http://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
?
Expands to the exit status of the most recently executed foreground pipeline.
Consulte o Manual do Bash em 3.4.2 Parâmetros especiais :
? - Expande para o status de saída do pipeline de primeiro plano executado mais recentemente.
É um pouco difícil de encontrar porque não está listado como $?
(o nome da variável é "apenas" ?
). Veja também a seção de status de saída , é claro ;-)
Feliz codificação.