Este equipo redactor ha pasado mucho tiempo buscando la respuesta a tu interrogante, te dejamos la solución de modo que deseamos resultarte de gran apoyo.
Solución:
¿Hay un comando TRY CATCH en Bash?
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 command2
se ejecuta de la siguiente manera
command1 || command2
Del mismo modo, usando &&
, command2
se ejecutará si command1
es exitoso
La aproximación más cercana de try/catch
es como sigue
# try
command1 &&
#save your output
|| # catch
# save log for exception
También bash contiene algunos mecanismos de manejo de errores, así como
set -e
detiene su secuencia de comandos si falla cualquier comando simple.
Y también por qué no if...else
. Es tu mejor amigo.
Según algunas respuestas que encontré aquí, me hice un pequeño archivo de ayuda para mis proyectos:
Trycatch.sh
#!/bin/bash
function try()
[[ $- = *e* ]]; SAVED_OPT_E=$?
set +e
function throw()
exit $1
function catch()
export ex_code=$?
(( $SAVED_OPT_E )) && set +e
return $ex_code
function throwErrors()
set -e
function ignoreErrors()
set +e
Aquí hay un ejemplo de cómo se ve en uso:
#!/bin/bash
export AnException=100
export AnotherException=101
# start with a try
try
( # open a subshell !!!
echo "do something"
[ someErrorCondition ] && throw $AnException
echo "do something more"
executeCommandThatMightFail || throw $AnotherException
throwErrors # automaticatly end the try block, if command-result is non-null
echo "now on to something completely different"
executeCommandThatMightFail
echo "it's a wonder we came so far"
executeCommandThatFailsForSure || true # ignore a single failing command
ignoreErrors # ignore failures of commands until further notice
executeCommand1ThatFailsForSure
local result = $(executeCommand2ThatFailsForSure)
[ result != "expected error" ] && throw $AnException # ok, if it's not an expected error, we want to bail out!
executeCommand3ThatFailsForSure
echo "finished"
)
# directly after closing the subshell you need to connect a group to the catch using ||
catch ||
# now you can handle
case $ex_code in
$AnException)
echo "AnException was thrown"
;;
$AnotherException)
echo "AnotherException was thrown"
;;
*)
echo "An unexpected exception was thrown"
throw $ex_code # you can rethrow the "exception" causing the script to exit if not caught
;;
esac
Desarrollé una implementación de prueba y captura casi impecable en bash, que te permite escribir código como:
try
echo 'Hello'
false
echo 'This will not be displayed'
catch
echo "Error in $__EXCEPTION_SOURCE__ at line: $__EXCEPTION_LINE__!"
¡Incluso puedes anidar los bloques de prueba y captura dentro de ellos mismos!
try
echo 'Hello'
try
echo 'Nested Hello'
false
echo 'This will not execute'
catch
echo "Nested Caught (@ $__EXCEPTION_LINE__)"
false
echo 'This will not execute too'
catch
echo "Error in $__EXCEPTION_SOURCE__ at line: $__EXCEPTION_LINE__!"
El código es parte de mi plantilla/marco de bash. Extiende aún más la idea de probar y atrapar con cosas como el manejo de errores con seguimiento y excepciones (además de algunas otras características interesantes).
Aquí está el código que es responsable solo de probar y atrapar:
set -o pipefail
shopt -s expand_aliases
declare -ig __oo__insideTryCatch=0
# if try-catch is nested, then set +e before so the parent handler doesn't catch us
alias try="[[ $__oo__insideTryCatch -gt 0 ]] && set +e;
__oo__insideTryCatch+=1; ( set -e;
trap "Exception.Capture $LINENO; " ERR;"
alias catch=" ); Exception.Extract $? || "
Exception.Capture()
local script="$BASH_SOURCE[1]#./"
if [[ ! -f /tmp/stored_exception_source ]]; then
echo "$script" > /tmp/stored_exception_source
fi
if [[ ! -f /tmp/stored_exception_line ]]; then
echo "$1" > /tmp/stored_exception_line
fi
return 0
Exception.Extract()
if [[ $__oo__insideTryCatch -gt 1 ]]
then
set -e
fi
__oo__insideTryCatch+=-1
__EXCEPTION_CATCH__=( $(Exception.GetLastException) )
local retVal=$1
if [[ $retVal -gt 0 ]]
then
# BACKWARDS COMPATIBILE WAY:
# export __EXCEPTION_SOURCE__="$__EXCEPTION_CATCH__[($#__EXCEPTION_CATCH__[@]-1)]"
# export __EXCEPTION_LINE__="$__EXCEPTION_CATCH__[($#__EXCEPTION_CATCH__[@]-2)]"
export __EXCEPTION_SOURCE__="$__EXCEPTION_CATCH__[-1]"
export __EXCEPTION_LINE__="$__EXCEPTION_CATCH__[-2]"
export __EXCEPTION__="$__EXCEPTION_CATCH__[@]:0:($#__EXCEPTION_CATCH__[@] - 2)"
return 1 # so that we may continue with a "catch"
fi
Exception.GetLastException()
if [[ -f /tmp/stored_exception ]] && [[ -f /tmp/stored_exception_line ]] && [[ -f /tmp/stored_exception_source ]]
then
cat /tmp/stored_exception
cat /tmp/stored_exception_line
cat /tmp/stored_exception_source
else
echo -e " n$BASH_LINENO[1]n$BASH_SOURCE[2]#./"
fi
rm -f /tmp/stored_exception /tmp/stored_exception_line /tmp/stored_exception_source
return 0
Siéntase libre de usar, bifurcar y contribuir: está en GitHub.