Que hace
echo $?
significa en la programación de shell?
Que hace
echo $?
significa en la programación de shell?
Respuestas:
Este es el estado de salida del último comando ejecutado.
Por ejemplo, el comando true
siempre devuelve un estado de 0
y false
siempre devuelve un estado de 1
:
true
echo $? # echoes 0
false
echo $? # echoes 1
Del manual: (accesible llamando a man bash
en su shell)
$?
Se expande al estado de salida de la tubería de primer plano ejecutada más recientemente.
Por convención, un estado de salida 0
significa éxito, y un estado de retorno distinto de cero significa falla. Obtenga más información sobre los estados de salida en wikipedia .
Hay otras variables especiales como esta, como puede ver en este manual en línea: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
$
y ?
son dos parámetros distintos y $?
no aparece en la página de manual de bash (1).
$?
devuelve el valor de salida del último comando ejecutado. echo $?
imprime ese valor en la consola. cero implica una ejecución exitosa, mientras que los valores distintos de cero se asignan a varios motivos de falla.
Por lo tanto, al crear scripts; Tiendo a usar la siguiente sintaxis
if [ $? -eq 0 ]; then
# do something
else
# do something else
fi
La comparación se debe hacer en iguales 0
o no iguales 0
.
** Actualización basada en el comentario: Idealmente, no debe usar el bloque de código anterior para la comparación, consulte los comentarios y la explicación de @tripleee.
cmd; if [ $? -eq 0 ]; then
debería ser refactorizada if cmd; then
. El propósito mismo de if
(y las otras declaraciones de control de flujo en el shell) es ejecutar un comando y examinar su estado de salida.
if cmd;
puede no ser muy legible en algunas condiciones, especialmente cuando cmd se refiere a otro script.
[ 1 ]
y [ 0 ]
son ambos verdaderos; [
sin un operador comprueba si el argumento es una cadena no vacía.
vendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("Successful");') &> /dev/null;
. Si tuviera que poner eso en una sola línea if [ ... ]
, sería terriblemente ilegible. Planeo almacenar la salida de esa línea en una variable para poder decir if [ $drupal_installed -eq 0 ]
más tarde.
echo $? - Da el ESTADO DE SALIDA del comando ejecutado más recientemente . Este ESTADO DE SALIDA probablemente sea un número con CERO que implique Éxito y cualquier valor NO CERO que indique Falla
? - Este es un parámetro / variable especial en bash.
PS - Da el valor almacenado en la variable "?".
Algunos parámetros especiales similares en BASH son 1,2, *, # (normalmente visto en el comando echo como $ 1, $ 2, $ *, $ #, etc.,).
Tiene el último código de estado (valor de salida) de un comando.
Ejemplo de estado de salida mínimo de POSIX C
Para comprender $?
, primero debe comprender el concepto de estado de salida del proceso que define POSIX . En Linux:
cuando un proceso llama a la exit
llamada del sistema, el núcleo almacena el valor pasado a la llamada del sistema (unint
) incluso después de que el proceso falle.
La exit()
función ANSI C llama a la llamada del sistema de salida , e indirectamente cuando lo hace return
desde main
.
El proceso que llamó al proceso secundario existente (Bash), a menudo con fork
+ exec
, puede recuperar el estado de salida del elemento secundario con la wait
llamada al sistema
Considere el código Bash:
$ false
$ echo $?
1
El "equivalente" C es:
falso.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));
}
Compilar y ejecutar:
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
Salida:
$? = 1
En Bash, cuando presiona enter, se produce una bifurcación + exec + espera como arriba, y bash luego establece $?
el estado de salida del proceso bifurcado.
Nota: para comandos integrados como echo
, un proceso no necesita ser generado, y Bash solo establece$?
en 0 para simular un proceso externo.
Estándares 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 parámetros solo pueden ser referenciados; la asignación a ellos no está permitida. [...]
? Se expande al estado de salida de la canalización en primer plano ejecutada más recientemente.
ANSI C y POSIX luego recomiendan que:
0
significa que el programa fue exitoso
otros valores: el programa falló de alguna manera.
El valor exacto podría indicar el tipo de falla.
ANSI C no define el significado de ningún valor, y POSIX especifica valores mayores que 125: ¿Cuál es el significado de "POSIX"?
Bash usa el estado de salida para if
En Bash, a menudo usamos el estado de salida $?
implícitamente para controlar las if
declaraciones como en:
if true; then
:
fi
donde true
es un programa que solo devuelve 0.
Lo anterior es equivalente 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 como tal), y 1 = 1 ]
sus argumentos, vea también: Diferencia entre corchetes simples y dobles en 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.
Consulte el Manual de Bash en 3.4.2 Parámetros especiales :
? - Se expande al estado de salida de la tubería de primer plano ejecutada más recientemente.
Es un poco difícil de encontrar porque no aparece como $?
(el nombre de la variable es "solo" ?
). También vea la sección de estado de salida , por supuesto ;-)
Feliz codificación