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 truerenvoie toujours un état de 0et falserenvoie toujours un état de 1:
true
echo $? # echoes 0
false
echo $? # echoes 1
Depuis le manuel: (accessible en appelant man bashvotre shell)
$?S'étend au statut de sortie du pipeline de premier plan le plus récemment exécuté.
Par convention, un statut de sortie 0signifie 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é 0ou 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 ]; thendevrait ê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' exitappel 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 à returnpartir 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' waitappel 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 ifinstructions comme dans:
if true; then
:
fi
où trueest 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.