Estoy escribiendo un script de shell y necesito verificar que se haya instalado una aplicación de terminal. Quiero usar un comando TRY / CATCH para hacer esto a menos que haya una forma más ordenada.
bash
shell
error-handling
Lee Probert
fuente
fuente
help test
podría ayudarlo a encontrar la solución a su problema.trap
comando.Respuestas:
No.
Bash no tiene tantos lujos como uno puede encontrar en muchos lenguajes de programación.
No hay
try/catch
en bash; sin embargo, uno puede lograr un comportamiento similar usando&&
o||
.Utilizando
||
:si
command1
falla, entonces secommand2
ejecuta de la siguiente maneraDel mismo modo, usando
&&
,command2
se ejecutará sicommand1
tiene éxitoLa aproximación más cercana de
try/catch
es la siguienteTambién bash contiene algunos mecanismos de manejo de errores, también
detiene su script si falla un comando simple.
Y también por qué no
if...else
. Es tu mejor amigofuente
#save your output
no falle o el bloque "catch" aún se ejecutará.if...else
construcción. ¿Esto implica que los comandos bash se resuelven como "verdaderos" si se ejecutan con éxito y "falsos" si fallan?set -e
no es necesariamente la mejor manera de hacer las cosas; Aquí hay algunos argumentos en contra / argumentos especiales: mywiki.wooledge.org/BashFAQ/105En base a algunas respuestas que encontré aquí, hice un pequeño archivo auxiliar para buscar mis proyectos:
trycatch.sh
Aquí hay un ejemplo de cómo se ve en uso:
fuente
||
despuéscatch
y antes del{}
bloque? Hubiera pensado que sería un&&
if False or run_if_failed()
significa que el cortocircuito O intentó la primera declaración que no devolvió verdadero y ahora está pasando a la siguiente declaración.&&
no funcionaría porque la primera declaración (try
) arrojó falso, lo que significa que lacatch
regla de tautología no necesita la declaraciónfalse&any equals false
. Solo un circuito no corto Y / O ejecutaría ambos.Desarrollé una implementación de prueba y captura casi perfecta en bash, que le permite escribir código como:
¡Incluso puedes anidar los bloques try-catch dentro de ellos!
El código es parte de mi bash boilerplate / framework . Extiende aún más la idea de probar y atrapar con cosas como el manejo de errores con retroceso y excepciones (además de algunas otras características interesantes).
Aquí está el código que es responsable solo de try & catch:
Siéntase libre de usar, bifurcar y contribuir: está en GitHub .
fuente
my_output=$(try { code...; } catch { code...; })
Puedes usar
trap
:try { block A } catch { block B } finally { block C }
se traduce en:
fuente
-E
bandera, creo, por lo que la trampa se propaga a funcionesHay tantas soluciones similares que probablemente funcionen. A continuación se muestra una forma simple y funcional de lograr try / catch, con explicación en los comentarios.
fuente
bash
no cancela la ejecución en ejecución en caso de que algo detecte un estado de error (a menos que establezca el-e
indicador). Los lenguajes de programación que ofrecentry/catch
hacen esto para inhibir un "rescate" debido a esta situación especial (por lo tanto, típicamente se llama "excepción").En
bash
cambio, solo el comando en cuestión saldrá con un código de salida mayor que 0, lo que indica ese estado de error. Puede verificar eso, por supuesto, pero dado que no hay rescate automático de nada, un intento / captura no tiene sentido. Simplemente le falta ese contexto.Sin embargo, puede simular un rescate utilizando subcapas que pueden terminar en un punto que usted decida:
En lugar de eso
some_condition
con unif
también puede probar un comando, y en caso de que falle (tiene un código de salida mayor que 0), rescate:Desafortunadamente, al usar esta técnica, está restringido a 255 códigos de salida diferentes (1..255) y no se pueden usar objetos de excepción decentes.
Si necesita más información para transmitir junto con su excepción simulada, puede usar la salida estándar de las subcapas, pero eso es un poco complicado y tal vez otra pregunta ;-)
Usando el indicador mencionado anteriormente
-e
en el shell, incluso puede quitar esaexit
declaración explícita :fuente
Como todos dicen, bash no tiene una sintaxis adecuada de prueba / captura compatible con el idioma. Puede iniciar bash con el
-e
argumento o usarset -e
dentro del script para abortar todo el proceso de bash si algún comando tiene un código de salida distinto de cero. (También puedeset +e
permitir temporalmente los comandos fallidos).Por lo tanto, una técnica para simular un bloque try / catch es iniciar un subproceso para hacer el trabajo con
-e
habilitado. Luego, en el proceso principal, verifique el código de retorno del subproceso.Bash admite cadenas heredoc, por lo que no tiene que escribir dos archivos separados para manejar esto. En el siguiente ejemplo, el TRY heredoc se ejecutará en una instancia de bash separada, con
-e
habilitado, por lo que el subproceso se bloqueará si algún comando devuelve un código de salida distinto de cero. Luego, nuevamente en el proceso principal, podemos verificar el código de retorno para manejar un bloque catch.No es un bloque de prueba / captura compatible con el idioma adecuado, pero puede rascarse una picazón similar para usted.
fuente
Tu puedes hacer:
fuente
Y tiene trampas http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html que no es lo mismo, pero otra técnica que puede utilizar para este propósito
fuente
Una cosa muy simple que uso:
fuente
||
está adentro()
, se ejecutaría en un subshell y saldría, sin que el shell principal salga. Utilice la{ }
agrupación en su lugar.A continuación se muestra una copia completa del script simplificado utilizado en mi otra respuesta . Más allá de la comprobación adicional de errores, hay un alias que permite al usuario cambiar el nombre de un alias existente. La sintaxis se da a continuación. Si
new_alias
se omite el parámetro, se elimina el alias.El guión completo se da a continuación.
fuente
A continuación se muestra un ejemplo de un script que se implementa
try/catch/finally
en bash.Los scripts de ejemplo comienzan creando un fifo anónimo, que se utiliza para pasar mensajes de cadena desde
command exception
othrow
hacia el final deltry
bloque más cercano . Aquí los mensajes se eliminan del fifo y se colocan en una variable de matriz. El estado se devuelve a través dereturn
yexit
comandos y se coloca en una variable diferente. Para ingresar uncatch
bloque, este estado no debe ser cero. Otros requisitos para ingresar a uncatch
bloque se pasan como parámetros. Sicatch
se alcanza el final de un bloque, el estado se establece en cero. Sifinally
se alcanza el final del bloque y el estado sigue siendo distinto de cero, se ejecuta un lanzamiento implícito que contiene los mensajes y el estado. El script requiere la llamada de la funcióntrycatchfinally
que contiene un controlador de excepciones no manejado.La sintaxis para el
trycatchfinally
comando se da a continuación.La
-c
opción agrega la pila de llamadas a los mensajes de excepción.La
-d
opción habilita la salida de depuración.La
-e
opción habilita las excepciones de comando.La
-h
opción permite al usuario sustituir su propio controlador de excepciones de comando.La
-k
opción agrega la pila de llamadas a la salida de depuración.La
-o
opción reemplaza el archivo de salida predeterminado que es/dev/fd/2
.La
-u
opción permite al usuario sustituir su propio controlador de excepciones no manejado.La
-v
opción permite al usuario la opción de transferir valores mediante el uso de la sustitución de comandos.El
fifo
es el nombre de archivo fifo.La función
function
se llamatrycatchfinally
como un subproceso.La sintaxis para el
catch
comando se da a continuación.Las opciones se definen a continuación. El valor de la primera lista es el estado. Los valores subsiguientes son los mensajes. Si hay más mensajes que listas, los mensajes restantes se ignoran.
-e
significa[[ $value == "$string" ]]
(el valor debe coincidir con al menos una cadena en la lista)-n
significa[[ $value != "$string" ]]
(el valor no puede coincidir con ninguna de las cadenas en la lista)-o
significa[[ $value != $pattern ]]
(el valor no puede coincidir con ninguno de los patrones en la lista)-p
significa[[ $value == $pattern ]]
(el valor tiene hacer coincidir al menos un patrón en la lista)-r
significa[[ $value =~ $regex ]]
(el valor debe coincidir con al menos una expresión regular extendida en la lista)-t
significa[[ ! $value =~ $regex ]]
(el valor no puede coincidir con ninguna de las expresiones regulares extendidas en la lista)El
try/catch/finally
guión se da a continuación. Para simplificar el script para esta respuesta, se eliminó la mayor parte de la comprobación de errores. Esto redujo el tamaño en un 64%. Puede encontrar una copia completa de este script en mi otra respuesta .A continuación se muestra un ejemplo, que supone que la secuencia de comandos anterior se almacena en el archivo denominado
simple
. Elmakefifo
archivo contiene el script descrito en esta respuesta . Se supone que el archivo nombrado4444kkkkk
no existe, por lo que se produce una excepción. La salida del mensaje de error dells 4444kkkkk
comando se suprime automáticamente hasta dentro delcatch
bloque apropiado .El script anterior se probó usando
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. El resultado, al ejecutar este script, se muestra a continuación.Se
throw
puede crear otro ejemplo que use a reemplazando la funciónMyFunction3
con el script que se muestra a continuación.La sintaxis para el
throw
comando se da a continuación. Si no hay parámetros presentes, se utilizan en su lugar el estado y los mensajes almacenados en las variables.El resultado, al ejecutar el script modificado, se muestra a continuación.
fuente