scripts script programas pasar parametros operaciones manejo español ejemplos cadenas aritmeticas bash scripting exit exit-code

bash - programas - shell script linux español



En un script de Bash, ¿cómo puedo salir del script completo si se produce una determinada condición? (7)

A menudo incluyo una función llamada run () para manejar los errores. Todas las llamadas que quiero hacer se pasan a esta función, por lo que la secuencia de comandos completa se cierra cuando se produce un error. La ventaja de esto sobre la solución set -e es que la secuencia de comandos no se cierra silenciosamente cuando falla una línea, y puede decirle cuál es el problema. En el siguiente ejemplo, la tercera línea no se ejecuta porque la secuencia de comandos sale en la llamada a falso.

function run() { cmd_output=$(eval $1) return_value=$? if [ $return_value != 0 ]; then echo "Command $1 failed" exit -1 else echo "output: $cmd_output" echo "Command succeeded." fi return $return_value } run "date" run "false" run "date"

Estoy escribiendo un script en Bash para probar un código. Sin embargo, parece una tontería ejecutar las pruebas si la compilación del código falla en primer lugar, en cuyo caso simplemente abortaré las pruebas.

¿Hay alguna manera de que pueda hacer esto sin ajustar todo el script dentro de un bucle while y usando cortes? ¿Algo así como un dun dun dun goto?


En lugar de construir, puede aprovechar la evaluación de cortocircuito :

#!/usr/bin/env bash echo $[1+1] echo $[2/0] # division by 0 but execution of script proceeds echo $[3+1] (echo $[4/0]) || exit $? # script halted with code 1 returned from `echo` echo $[5+1]

Tenga en cuenta el par de paréntesis que es necesario debido a la prioridad del operador de alternancia. $? es una variable especial establecida para salir del código del comando llamado más recientemente.



Si invoca el script con source , puede usar return <x> donde <x> será el estado de salida del script (use un valor distinto de cero para error o false). Esto también funcionará como se esperaba, cuando source la secuencia de comandos, pero si invoca una secuencia de comandos ejecutable (es decir, directamente con su nombre de archivo), la declaración de retorno dará lugar a una queja (mensaje de error "return: solo se puede ''devolver'' desde un Función o script de origen ").

Si se usa exit <x> su lugar, cuando el script se invoca con source , resultará en salir del shell que inició el script, pero un script ejecutable se ejecutará directamente bien.

Para manejar cualquiera de los casos en el mismo script, puede usar

return <x> 2> /dev/null || exit <x>

Esto manejará cualquier invocación que sea adecuada.

Nota: <x> se supone que es solo un número.


Tengo la misma pregunta pero no puedo hacerla porque sería un duplicado.

La respuesta aceptada, utilizando exit, no funciona cuando el script es un poco más complicado. Si usa un proceso en segundo plano para verificar la condición, exit solo sale de ese proceso, ya que se ejecuta en un sub-shell. Para matar el script, debes matarlo explícitamente (al menos esa es la única manera que conozco).

Aquí hay un pequeño guión sobre cómo hacerlo:

#!/bin/bash boom() { while true; do sleep 1.2; echo boom; done } f() { echo Hello N=0 while ((N++ <10)) do sleep 1 echo $N # ((N > 5)) && exit 4 # does not work ((N > 5)) && { kill -9 $$; exit 5; } # works done } boom & f & while true; do sleep 0.5; echo beep; done

Esta es una respuesta mejor, pero aún incompleta. Realmente no sé cómo deshacerme de la parte de auge .


Un chico malo de SysOps una vez me enseñó la técnica de la garra de tres dedos:

yell() { echo "$0: $*" >&2; } die() { yell "$*"; exit 111; } try() { "$@" || die "cannot $*"; }

Estas funciones son * NIX OS y shell con sabor robusto. Póngalos al comienzo de su script (bash o de otra manera), try() su declaración y su código.

Explicación

(basado en el comentario de ).

  • yell : imprime el nombre del script y todos los argumentos a stderr :
    • $0 es la ruta al script;
    • $* son todos los argumentos.
    • >&2 significa > redireccionar stdout a & pipe 2 . la pipa 1 sería stdout sí.
  • die hace lo mismo que yell , pero sale con un estado de salida distinto a 0 , que significa "falla".
  • try usar el || (booleano OR ), que solo evalúa el lado derecho si el izquierdo no falló.
    • $@ es todos los argumentos otra vez, pero different .

Espero que lo explique todo.


Utilice set -e

#!/bin/bash set -e /bin/command-that-fails /bin/command-that-fails2

La secuencia de comandos terminará después de la primera línea que falla (devuelve un código de salida distinto de cero). En este caso, el comando-that-fail2 no se ejecutará.

Si tuviera que verificar el estado de retorno de cada comando único, su script se vería así:

#!/bin/bash # I''m assuming you''re using make cd /project-dir make if [[ $? -ne 0 ]] ; then exit 1 fi cd /project-dir2 make if [[ $? -ne 0 ]] ; then exit 1 fi

Con set -e se vería como:

#!/bin/bash set -e cd /project-dir make cd /project-dir2 make

Cualquier comando que falle causará que todo el script falle y devolverá un estado de salida que puede verificar con $? . Si tu script es muy largo o estás creando muchas cosas, se pondrá muy feo si agregas controles de estado de retorno en todas partes.