web-dev-qa-db-fra.com

Quel est le $? (point d'interrogation dollar) variable dans les scripts Shell?

J'essaie d'apprendre les scripts Shell et j'ai besoin de comprendre le code de quelqu'un d'autre. Quelle est la valeur de la variable $?? Je ne peux pas rechercher la réponse sur Google car ils bloquent les caractères de ponctuation.

236
David Mulder

$? est utilisé pour trouver la valeur de retour de la dernière commande exécutée. Essayez ce qui suit dans le shell:

ls somefile
echo $?

Si somefile existe (que ce soit un fichier ou un répertoire), vous obtiendrez la valeur renvoyée par la commande ls, qui devrait être 0 (valeur renvoyée par défaut "success") . S'il n'existe pas, vous devriez obtenir un nombre autre que 0. Le nombre exact dépend du programme.

Pour de nombreux programmes, vous pouvez trouver les numéros et leur signification dans la page de manuel correspondante. Celles-ci seront généralement décrites comme "statut de sortie" et peuvent avoir leur propre section.

227
pooamlairaj

C'est l'état de sortie de la dernière fonction/programme/commande exécutée. Faire référence à:

45
Dor

Une valeur de retour du processus précédemment exécuté.

10.4 Obtenir la valeur de retour d'un programme

Dans bash, la valeur de retour d'un programme est stockée dans une variable spéciale appelée $ ?.

Ceci illustre comment capturer la valeur de retour d'un programme, je suppose que le répertoire dada n'existe pas. (Cela a également été suggéré par Mike)

        #!/bin/bash
        cd /dada &> /dev/null
        echo rv: $?
        cd $(pwd) &> /dev/null
        echo rv: $?

Voir Manuel de programmation Bash pour plus de détails.

18
user405725

Exemple d'état de sortie minimal pour POSIX C

Pour comprendre $?, vous devez d'abord comprendre le concept d'état de sortie du processus.

Sous Linux:

  • lorsqu'un processus appelle l'appel système exit, le noyau stocke la valeur transmise à l'appel système même après la mort du processus.

    L'appel système de sortie est appelé par la fonction exit() ANSI C, et indirectement lorsque vous effectuez return à partir de main.

  • le processus qui a appelé le processus enfant sortant (Bash), souvent avec fork + exec, peut récupérer l'état de sortie de l'enfant avec l'appel système wait

Considérons le code Bash:

$ false
$ echo $?
1

Le "équivalent" C est:

false.c:

#include <stdlib.h> /* exit */

int main() {
    exit(1);
}

bash.c:

#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main() {
    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));
}

Dans Bash, lorsque vous appuyez sur entrée, un fork + exec + wait se passe comme ci-dessus, puis bash définit ensuite $? sur le statut de sortie du processus fork.

Remarque: pour les commandes intégrées telles que echo, il n'est pas nécessaire de générer un processus et Bash configure simplement $? à 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 :

? Développe le statut de sortie décimal du pipeline le plus récent (voir Pipelines).

man bash "Paramètres spéciaux":

Le shell traite spécialement plusieurs paramètres. Ces paramètres ne peuvent être référencés que; leur assignation n'est pas autorisée. [...]

? Développe le statut de sortie du pipeline de premier plan exécuté le plus récemment.

ANSI C et POSIX recommandent alors que:

  • 0 signifie que le programme a réussi

  • autres valeurs: le programme a échoué en quelque sorte.

    La valeur exacte pourrait indiquer le type d'échec.

    ANSI C ne définit pas la signification des valeurs, et POSIX spécifie des valeurs supérieures à 125: Quelle est la signification de "POSIX"?

Bash utilise le statut de sortie pour if

Dans Bash, nous utilisons souvent le statut de sortie $? implicitement pour contrôler les instructions if comme dans:

if true; then
  :
fi

true est un programme qui ne retourne que 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 Bash intégré qui se comporte de la sorte), et 1 = 1 ] ses arguments, voir aussi: Différence entre les crochets simples et doubles dans Bash

$? est le résultat (code de sortie) de la dernière commande exécutée.

9
marcelog

$? est le statut de sortie d'une commande, de sorte que vous pouvez chaîner une série de commandes.

Exemple

command1 && command2 && command3

command2 s'exécutera si command1's$? donne un success (0) et command3 s'exécutera si $? de command2 donnera un success

4

C'est le code d'erreur renvoyé de la dernière commande exécutée. 0 = succès

4
Wulf

Il convient bien au débogage dans le cas où votre script se termine si set -e est utilisé. Par exemple, mettez echo $? après la commande qui provoque sa fermeture et consultez la valeur d'erreur renvoyée.

2
lukmac

Le code de sortie de la dernière commande a été exécuté.

2
Matt