Que fait
echo $?
signifie en programmation shell?
Que fait
echo $?
signifie en programmation shell?
Réponses:
Il s'agit de l'état de sortie de la dernière commande exécutée.
Par exemple, la commande true
renvoie toujours un état de 0
et false
renvoie toujours un état de 1
:
true
echo $? # echoes 0
false
echo $? # echoes 1
Depuis le manuel: (accessible en appelant man bash
votre shell)
$?
S'étend au statut de sortie du pipeline de premier plan le plus récemment exécuté.
Par convention, un statut de sortie 0
signifie succès et un statut de retour différent de zéro signifie échec. En savoir plus sur les statuts de sortie sur wikipedia .
Il existe d'autres variables spéciales comme celle-ci, comme vous pouvez le voir dans ce manuel en ligne: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
$
et ?
sont deux paramètres distincts et $?
n'apparaissent pas dans la page de manuel bash (1).
$?
renvoie la valeur de sortie de la dernière commande exécutée. echo $?
imprime cette valeur sur la console. zéro implique une exécution réussie tandis que les valeurs non nulles sont mappées à diverses raisons d'échec.
Par conséquent, lors de la création de scripts; J'ai tendance à utiliser la syntaxe suivante
if [ $? -eq 0 ]; then
# do something
else
# do something else
fi
La comparaison doit être faite sur un pied d'égalité 0
ou non 0
.
** Mise à jour Basé sur le commentaire: Idéalement, vous ne devriez pas utiliser le bloc de code ci-dessus pour la comparaison, reportez-vous aux commentaires et explications @tripleee.
cmd; if [ $? -eq 0 ]; then
devrait être refactorisé if cmd; then
. Le but même de if
(et des autres instructions de contrôle de flux dans le shell) est d'exécuter une commande et d'examiner son état de sortie.
if cmd;
certaines conditions peuvent ne pas être très lisibles, en particulier lorsque cmd fait référence à un autre script.
[ 1 ]
et [ 0 ]
sont tous les deux vrais; [
sans opérateur vérifie si l'argument est une chaîne non vide.
vendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("Successful");') &> /dev/null;
. Si je devais mettre cela sur une seule ligne, if [ ... ]
ce serait terriblement illisible. Je prévois de stocker la sortie de cette ligne dans une variable afin que je puisse le dire if [ $drupal_installed -eq 0 ]
plus tard.
echo $? - Donne le STATUT DE SORTIE de la dernière commande exécutée . Ce STATUT DE SORTIE serait très probablement un nombre avec ZERO indiquant le succès et toute valeur NON-ZERO indiquant l' échec
? - Ceci est un paramètre / variable spécial dans bash.
$? - Il donne la valeur stockée dans la variable "?".
Certains paramètres spéciaux similaires dans BASH sont 1,2, *, # (normalement vu dans la commande echo comme $ 1, $ 2, $ *, $ #, etc.,).
Il a le dernier code d'état (valeur de sortie) d'une commande.
Exemple d'état de sortie POSIX C minimal
Pour comprendre $?
, vous devez d'abord comprendre le concept de statut de sortie de processus qui est défini par POSIX . Sous Linux:
lorsqu'un processus appelle l' exit
appel système, le noyau stocke la valeur passée à l'appel système (unint
) même après la mort du processus.
L'appel système de sortie est appelé par la exit()
fonction ANSI C et indirectement lorsque vous le faites à return
partir de main
.
le processus qui a appelé le processus enfant sortant (Bash), souvent avec fork
+ exec
, peut récupérer le statut de sortie de l'enfant avec l' wait
appel système
Considérez le code Bash:
$ false
$ echo $?
1
L '«équivalent» C est:
faux.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));
}
Compilez et exécutez:
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
Production:
$? = 1
Dans Bash, lorsque vous appuyez sur Entrée, un fork + exec + wait se produit comme ci-dessus, et bash définit ensuite $?
l'état de sortie du processus forké.
Remarque: pour les commandes intégrées comme echo
, un processus n'a pas besoin d'être généré, et Bash se règle simplement $?
sur 0 pour simuler un processus externe.
Normes et documentation
POSIX 7 2.5.2 "Paramètres spéciaux" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :
? S'étend à l'état de sortie décimal du pipeline le plus récent (voir Pipelines).
man bash
"Paramètres spéciaux":
Le shell traite plusieurs paramètres spécialement. Ces paramètres ne peuvent être référencés que; leur attribution n'est pas autorisée. [...]
? S'étend au statut de sortie du pipeline de premier plan le plus récemment exécuté.
ANSI C et POSIX recommandent alors que:
0
signifie que le programme a réussi
autres valeurs: le programme a échoué d'une manière ou d'une autre.
La valeur exacte peut indiquer le type de panne.
ANSI C ne définit pas la signification des vaues, et POSIX spécifie des valeurs supérieures à 125: Quelle est la signification de "POSIX"?
Bash utilise l'état de sortie pour if
Dans Bash, nous utilisons souvent le statut de sortie $?
implicitement pour contrôler les if
instructions comme dans:
if true; then
:
fi
où true
est un programme qui renvoie simplement 0.
Ce qui précède est équivalent à:
true
result=$?
if [ $result = 0 ]; then
:
fi
Et en:
if [ 1 = 1 ]; then
:
fi
[
est juste un programme avec un nom étrange (et intégré à Bash qui se comporte comme lui), et 1 = 1 ]
ses arguments, voir aussi: Différence entre les crochets simples et doubles dans Bash
De http://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
?
Expands to the exit status of the most recently executed foreground pipeline.
Voir le manuel Bash sous 3.4.2 Paramètres spéciaux :
? - S'étend à l'état de sortie du pipeline de premier plan le plus récemment exécuté.
C'est un peu difficile à trouver car il n'est pas répertorié comme $?
(le nom de la variable est "juste" ?
). Voir aussi la section sur l' état de sortie , bien sûr ;-)
Bon codage.