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 testpodría ayudarlo a encontrar la solución a su problema.trapcomando.Respuestas:
No.
Bash no tiene tantos lujos como uno puede encontrar en muchos lenguajes de programación.
No hay
try/catchen bash; sin embargo, uno puede lograr un comportamiento similar usando&&o||.Utilizando
||:si
command1falla, entonces secommand2ejecuta de la siguiente maneraDel mismo modo, usando
&&,command2se ejecutará sicommand1tiene éxitoLa aproximación más cercana de
try/catches 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 outputno falle o el bloque "catch" aún se ejecutará.if...elseconstrucción. ¿Esto implica que los comandos bash se resuelven como "verdaderos" si se ejecutan con éxito y "falsos" si fallan?set -eno 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éscatchy 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 lacatchregla 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
-Ebandera, 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
bashno cancela la ejecución en ejecución en caso de que algo detecte un estado de error (a menos que establezca el-eindicador). Los lenguajes de programación que ofrecentry/catchhacen esto para inhibir un "rescate" debido a esta situación especial (por lo tanto, típicamente se llama "excepción").En
bashcambio, 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_conditioncon uniftambié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
-een el shell, incluso puede quitar esaexitdeclaració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
-eargumento o usarset -edentro 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 +epermitir 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
-ehabilitado. 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
-ehabilitado, 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_aliasse 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/finallyen bash.Los scripts de ejemplo comienzan creando un fifo anónimo, que se utiliza para pasar mensajes de cadena desde
command exceptionothrowhacia el final deltrybloque 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 dereturnyexitcomandos y se coloca en una variable diferente. Para ingresar uncatchbloque, este estado no debe ser cero. Otros requisitos para ingresar a uncatchbloque se pasan como parámetros. Sicatchse alcanza el final de un bloque, el estado se establece en cero. Sifinallyse 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óntrycatchfinallyque contiene un controlador de excepciones no manejado.La sintaxis para el
trycatchfinallycomando se da a continuación.La
-copción agrega la pila de llamadas a los mensajes de excepción.La
-dopción habilita la salida de depuración.La
-eopción habilita las excepciones de comando.La
-hopción permite al usuario sustituir su propio controlador de excepciones de comando.La
-kopción agrega la pila de llamadas a la salida de depuración.La
-oopción reemplaza el archivo de salida predeterminado que es/dev/fd/2.La
-uopción permite al usuario sustituir su propio controlador de excepciones no manejado.La
-vopción permite al usuario la opción de transferir valores mediante el uso de la sustitución de comandos.El
fifoes el nombre de archivo fifo.La función
functionse llamatrycatchfinallycomo un subproceso.La sintaxis para el
catchcomando 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.
-esignifica[[ $value == "$string" ]](el valor debe coincidir con al menos una cadena en la lista)-nsignifica[[ $value != "$string" ]](el valor no puede coincidir con ninguna de las cadenas en la lista)-osignifica[[ $value != $pattern ]](el valor no puede coincidir con ninguno de los patrones en la lista)-psignifica[[ $value == $pattern ]](el valor tiene hacer coincidir al menos un patrón en la lista)-rsignifica[[ $value =~ $regex ]](el valor debe coincidir con al menos una expresión regular extendida en la lista)-tsignifica[[ ! $value =~ $regex ]](el valor no puede coincidir con ninguna de las expresiones regulares extendidas en la lista)El
try/catch/finallyguió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. Elmakefifoarchivo contiene el script descrito en esta respuesta . Se supone que el archivo nombrado4444kkkkkno existe, por lo que se produce una excepción. La salida del mensaje de error dells 4444kkkkkcomando se suprime automáticamente hasta dentro delcatchbloque 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
throwpuede crear otro ejemplo que use a reemplazando la funciónMyFunction3con el script que se muestra a continuación.La sintaxis para el
throwcomando 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