Saltar al contenido

¿Hay un comando TRY CATCH en Bash?

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *