6

I am trying to execute the script whenever the command fails. We all know that if the command is failed $? value will not be equal to 0.It gives the value 127 if command fails.

The script is ready but I am unable to catch the command fail events.

For example, if I try a command which is not present then it has to take that input and pass it to the script. I have figured all the logic except catching the failed events. How can I do this?
Example

$-> code 

code is not the command here so it fails in execution automatically run the following command with taking code as input to the cd command.

cd code     
1

What could be done is to use functions. They run as subshells, so you can catch errors of one subshell via redirection, and send it to other function to deal with it. The script bellow handles only failure of one command.

#!/bin/bash
err_handling()
{
    # grab command from output
    cmd=$(awk -F ':' '{print $1}'  < /dev/stdin)
    # re-run with some proper argument
    $cmd /dev/sda1

}

main()
{
    # let main stop on error
    # so note , last line won't run !!!
    set -e
    # This will fail with df: asdf: No such file or directory
    # err_handling function will grab the command name 
    # and rerun it
    df asdf
    echo "Last line"
}

# Run main with redirecting stderr to stdout
# and original stdout to /dev/null. That way
# only stderr goes via pipe
main  2>&1 >/dev/null | err_handling 

You could handle multiple commands, if you tell awk to filter output. For instance, this reads all stderr form main, and for each err line, extracts command. case...esac is used to handle specific cases of errors

#!/bin/bash
err_handling()
{
    while read line
    do
        # grab command from output
        cmd=$(awk -F ':' '{print $1}'  <<< "$line" )
        # re-run with some proper argument
        case $line in
            # do something with cmd depending on error
            *not\ found*) echo "$cmd wasn't found" ;;
            *No\ such\ file*) echo "$cmd didn't find your file" ;;
        esac

    done

}

main()
{
    # let main stop on error
    # so note , last line won't run if set -x is set !!!
    # set -x 
    # This will fail with df: asdf: No such file or directory
    # err_handling function will grab the command name 
    # and rerun it
    df asdf
    asdf
}

# Run main with redirecting stderr to stdout
# and original stdout to /dev/null. That way
# only stderr goes via pipe
main  2>&1 >/dev/null | err_handling 

Note, as i mention in the comments - some commands don't use stderr, for instance file command. In such case, you'd need to redirect its stdin and handle it via pipe or otherwise

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.