¿Qué es the? (signo de interrogación dólar) variable en shell scripting?


Estoy tratando de aprender shell scripting, y necesito entender el código de otra persona. ¿Qué es la variable $? hold? No puedo buscar la respuesta en Google porque bloquean los caracteres de puntuación.

9 answers

$? se utiliza para encontrar el valor devuelto del último comando ejecutado. Prueba lo siguiente en el shell:

ls somefile
echo $?

Si somefile existe (independientemente de si se trata de un archivo o directorio), obtendrá el valor de retorno arrojado por el comando ls, que debería ser 0 (valor de retorno predeterminado de "éxito"). Si no existe, usted debe conseguir un número otro entonces 0. El número exacto depende del programa.

Para muchos programas puede encontrar los números y su significado en el correspondiente página de manual. Estos generalmente se describirán como" estado de salida " y pueden tener su propia sección.

 189
Author: pooamlairaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-29 10:35:24

Es el estado de salida de la última función/programa/comando ejecutado. Refiérase a:

 44
Author: Dor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-26 18:18:55

Un valor devuelto del proceso previamente ejecutado.

10.4 Obtener el valor devuelto de un programa

En bash, el valor de retorno de un programa se almacena en una variable especial llamado $?.

Esto ilustra cómo capturar el valor devuelto de un programa, I supongamos que el directorio dada no existe. (Esto también fue sugerido por mike)

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

Ver Bash Programming Manual para más detalles.

 18
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-26 18:09:37

$? es el resultado (código de salida) del último comando ejecutado.

 9
Author: marcelog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-26 18:09:45

Ejemplo de C mínimo

Para entender $?, primero debe entender el concepto de estado de salida del proceso.

En Linux:

  • Cuando un proceso llama a la llamada al sistema exit, el núcleo almacena el valor pasado a la llamada al sistema incluso después de que el proceso muere.

    La llamada al sistema de salida es llamada por la función ANSI C exit(), e indirectamente cuando haces return desde main.

  • El proceso que llamó al niño saliente proceso (Bash), a menudo con fork + exec, puede recuperar el estado de salida del hijo con la llamada al sistema wait

Considere el código Bash:

$ false
$ echo $?
1

La C "equivalente" es:

Falso.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));
}

En Bash, cuando se pulsa enter, ocurre una bifurcación + exec + wait como la anterior, y bash entonces establece $? al estado de salida del proceso bifurcado.

Nota: para comandos integrados como echo, no es necesario generar un proceso, y Bash solo establece $? a 0 para simular un proceso externo.

Normas y documentación

POSIX 7 2.5.2 "Parámetros especiales" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :

? Se expande al estado de salida decimal de la canalización más reciente (consulte Canalizaciones).

man bash "Parámetros Especiales":

El shell trata varios parámetros especialmente. Estos los parámetros solo pueden ser referenciados; la asignación a ellos no está permitida. [...]

? Se expande al estado de salida de la canalización de primer plano ejecutada más recientemente.

ANSI C y POSIX recomiendan entonces que:

  • 0 significa que el programa tuvo éxito

  • Otros valores: el programa falló de alguna manera.

    El valor exacto podría indicar el tipo de fallo.

    ANSI C no define el significado de ninguna vaues, y POSIX especifica valores mayores que 125: Nunca entendí realmente: ¿qué es POSIX?

Bash usa el estado de salida para if

En Bash, a menudo usamos el estado de salida $? implícitamente para controlar if declaraciones como en:

if true; then
  :
fi

Donde true es un programa que sólo devuelve 0.

Lo anterior equivale a:

true
result=$?
if [ $result = 0 ]; then
  :
fi

Y en:

if [ 1 = 1 ]; then
  :
fi

[ es solo un programa con un nombre extraño (y Bash incorporado que se comporta así), y 1 = 1 ] sus argumentos, ver también: ¿Cuál es la diferencia entre corchetes simples y dobles en Bash?

 8
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-30 15:08:16

Es el código de error devuelto del último comando ejecutado. 0 = éxito

 4
Author: Wulf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-26 18:09:35

$? es el estado de salida de un comando, de modo que puede encadenar una serie de comandos.

Ejemplo

command1 && command2 && command3

command2 se ejecutará si command1's $? los rendimientos de un success (0) y command3 ejecutará si $? de command2 producirá un success

 3
Author: Glenn John Ogapong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-14 03:13:51

Se ejecutó el código de salida del último comando.

 2
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-26 23:43:02

Es muy adecuado para la depuración en caso de que su script salga si se utiliza "set-e". Por ejemplo, poner "echo $?"después del comando que causa que salga y vea el valor de error devuelto.

 1
Author: lukmac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-04 20:04:36