• How to error proof Bash scripts


    execute [INVOKING-FUNCTION] [COMMAND]
    
    execute () {
        error=$($2 2>&1 >/dev/null)
    
        if [ $? -ne 0 ]; then
            echo "$1: $error"
            exit 1
        fi
    }
    
  • @es20490446e
    If I’m reading it right, it doesn’t seem to handle possible parameters of a command.
    Could you please show us an example usage?

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

  • buildApps () {
        execute "buildApps" "yaourt --sync --noconfirm $1"
    }
    
    buildApps "qtqr xiccd"
    
  • OK, it is working properly. Very nice! 🙂

    There are three things I’d like to point out, if you have any wishes to develop it further.

    • You are giving all parameters within quotes. If you wish to give them without quotes, that is also possible.
    • If you’d like to get the real error code from “execute()”, that is possible, too.
    • The name of a caller of a function is available.

    So I came up with this:

    execute() {
        local tmpfile=/tmp/errors.$$
        local errorcode
        local errormsg
    
        "[email protected]" 2>$tmpfile >/dev/null
        errorcode=$?
    
        if [ $errorcode -ne 0 ] ; then
            if [ -n "${FUNCNAME[1]}" ] ; then
                echo "[called from ${FUNCNAME[1]}]"
            fi
            echo -n "$*: "
            cat $tmpfile
            rm -f $tmpfile
            exit $errorcode
        else
            rm -f $tmpfile
        fi
    }
    

    It uses a temporary file to store the error messages (which isn’t ideal but works).
    Use it if you want, or not. I did it just for the fun of it! 🙂

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

    • Quotes makes possible to handle strings and names with spaces.
    • Exit codes needs a fixed spec.
    • Storing error messages directly into memory is short and efficient.

    Now try to improve the code for real! : P

  • @es20490446e
    Alright, let’s improve it! I made a bash test program to compare implementations (execute vs. runcheck), please run the test.
    See the difference especially in parameter handling?

    runcheck()
    {
        "[email protected]" >/dev/null
        local errorcode=$?
    
        if [ $errorcode -ne 0 ] ; then
            echo "Call stack:"
            local func
            for func in "${FUNCNAME[@]}" ; do
                echo " --> $func"
            done
            echo "Program '$1' fails, error code = $errorcode"
            return $errorcode  # changed 'exit' -> 'return' just for the test below
        fi
    }
    
    execute () {
        error=$($2 2>&1 >/dev/null)
    
        if [ $? -ne 0 ]; then
            echo "$1: $error"
            return 1   # changed 'exit' -> 'return' just for the test below
        fi
    }
    
    StartTest()
    {
        local filename="./a simple test.bash"
    
        echo "a_non_existing_command" > "$filename"
        chmod u+x "$filename"
    
        printf "Testing execute:\n"
        execute  "StartTest" "$filename"
        echo $?
    
        printf "\n\nTesting runcheck:\n"
        runcheck "$filename"
        echo $?
        rm -f "$filename"
    }
    
    StartTest
    
    
    # buildApps using runcheck:
    buildApps() {
        runcheck yaourt --sync --noconfirm "[email protected]"
    }
    # and the call would be:
    # buildApps qtqr xiccd
    

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

  • @manuel This one is cool : )

  • @es20490446e
    Thanks!
    It is quite a good idea to have a simple way to do a simple, systematic check that a command execution went OK, and immediately stop if something goes wrong.

    In fact I have sometimes done something similar for my small hobby programs, but if you think of a more professional approach, such tools are very useful.

    And while studying this, I found a nice little article about useful settings for bash scripts: http://redsymbol.net/articles/unofficial-bash-strict-mode/

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

  • @es20490446e
    I suppose those “bash strict mode” settings are meant to be used only when needed (for example in debugging), since they change the “normal” bash script behavior quite much in some aspects. So I’m not using them unless I can see real benefit in using them.

    Anyway, it is good to have various “generic” tools if/when facing problems in programs. : )

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

  • I think that the ideal is been able to choose which commands should strictly not fail, and which not. In the same script.

    That’s why I like having a function instead of using “set”.

  • @es20490446e
    That’s good for many programs.
    But for some other programs those generic tools/settings are also good.
    Developer just has to know which approach to use. One solution is seldom good for everything.

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

  • 90% of the time it works every time.

  • Could you guys explain the expression one by one so I can replicate it?

    I make things work…
    My humble wiki: https://anotherlinux.com/

  • What do you mean?

  • @manuel said in How to error proof Bash scripts:

    http://redsymbol.net/articles/unofficial-bash-strict-mode/

    This has an explanation, yours do not 🙂

    I make things work…
    My humble wiki: https://anotherlinux.com/

  • @manuel said in How to error proof Bash scripts:

    @es20490446e
    I suppose those “bash strict mode” settings are meant to be used only when needed (for example in debugging), since they change the “normal” bash script behavior quite much in some aspects. So I’m not using them unless I can see real benefit in using them.

    Anyway, it is good to have various “generic” tools if/when facing problems in programs. : )

    Amen, this in a backup script with series of backups would be a bad idea…

    @es20490446e said in How to error proof Bash scripts:

    I think that the ideal is been able to choose which commands should strictly not fail, and which not. In the same script.

    That’s why I like having a function instead of using “set”.

    Good point, you can sequence dependencies, that way if one fails the rest will not execute.

    I make things work…
    My humble wiki: https://anotherlinux.com/

  • I believe the code is quite self explanatory. Perhaps:

    error=$($2 2>&1 >/dev/null)
    Saves any error of the command in the “error” variable, without printing anything by default.

    $?
    The exit status of the command. Zero is success, anything different from that is failure.

  • Basically the function executes any command you pass.

    If the command is successful it prints nothing, if it isn’t it prints the error message preceded with the function name where it happened.

  • @izznogooood
    Which part would you like to be explained?

    Please report issues including all details! ;-)
    Show files here: cat "file" | curl -F [email protected] https://ptpb.pw/?u=1
    and show the URL.

error281 scripts6 bash6 proof1 Posts 20Views 1054
Log in to reply
Bloom Email Optin Plugin

Looks like your connection to Antergos Community Forum was lost, please wait while we try to reconnect.