409

Is there any way to check if there is an error in executing a command?

Example :

test1=`sed -i "/:@/c connection.url=jdbc:oracle:thin:@$ip:1521:$dataBase" $search`
valid $test1

function valid () {
  if $test -eq 1; then
    echo "OK"
    else echo "ERROR" 
  fi
}

I already tried do that but it seems it isn't working. I don't how do that.

Octavian Helm
  • 14,515
moata_u
  • 5,603

10 Answers10

574

The return value is stored in $?. 0 indicates success, others indicates error.

some_command
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

Like any other textual value, you can store it in a variable for future comparison:

some_command
retval=$?
do_something $retval
if [ $retval -ne 0 ]; then
    echo "Return code was not zero but $retval"
fi

For possible comparison operators, see man test.

Lekensteyn
  • 178,446
140

If you only need to know if the command succeeded or failed, don't bother testing $?, just test the command directly. E.g.:

if some_command; then
    printf 'some_command succeeded\n'
else
    printf 'some_command failed\n'
fi

And assigning the output to a variable doesn't change the return value (well, unless it behaves differently when stdout isn't a terminal of course).

if output=$(some_command); then
    printf 'some_command succeded, the output was «%s»\n' "$output"
fi

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals explains if in more detail.

geirha
  • 47,279
56
command && echo OK || echo Failed
David Foerster
  • 36,890
  • 56
  • 97
  • 151
27

$? should contain the exit status of the previous command, which should be zero for no error.

So, something like;

cd /nonexistant
if [ $? -ne 0 ]
then
    echo failed
else
    echo success!
fi

for most cases, it's easier to use the && construct to chain commands that need to depend on each other. So cd /nonexistant && echo success! would not echo success because the command breaks before &&. The corollary of this is ||, where cd /nonexistant || echo fail would echo fail because cd failed (this becomes useful if you use something like ||exit, which will end the script if the previous command failed).

Shaun
  • 577
8
command && echo $? || echo $?
modrobert
  • 117
6

It should be noted that if...then...fi and &&/|| type of approach deals with exit status returned by command we want to test( 0 on success ); however, some commands don't return a non-zero exit status if command failed or couldn't deal with input. This means that the usual if and &&/|| approaches won't work for those particular commands.

For instance, on Linux GNU file still exits with 0 if it received a non-existing file as argument and find couldn't locate the file user specified.

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

In such cases, one potential way we could handle the situation is by reading stderr/stdin messages, e.g. those that returned by file command, or parse output of the command like in find. For that purposes, case statement could be used.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found

( This is a repost of my own answer on related question at unix.stackexchange.com )

5

As mentioned in many other answers, a simple test of $? will do, like this

if [ $? -eq 0 ]; then something; fi

If you want to test if the command failed, you can use a shorter version in bash (but perhaps overkill) as follows:

if (($?)); then something; fi

This works by using the (( )) arithmetic mode, so if the command returned success, i.e. $? = 0 then the test evaluates to ((0)) which tests as false, otherwise it will return true.

To test for success, you could use:

if ! (($?)); then something; fi

but it's already not much shorter than the first example.

2

You can also configure bash to exit if a command fails, useful to avoid checks after every command. Place this at beginning of your script:

set -e
jcarballo
  • 318
2

For easier debugging, I make commands to only output errors with:

so [-tag] [commands]

After that $? is 0 if success, otherwise failure.

1

Prints the status of the last command

if [ $? == 0 ]; then echo passed;else echo failed; (exit 1); fi;

Section echo passed and echo failed can be modified to do whatever you want depending on the status of the last command.

Usage

echo test # supposed to pass
if [ $? == 0 ]; then echo passed;else echo failed; (exit 1); fi;

passed

blahblah # supposed to fail
if [ $? == 0 ]; then echo passed;else echo failed; (exit 1); fi;

failed

More fun using bash profile function:

function if_success() {
    if [ $? -eq 0 ]; then
        "$@"
    fi
}

echo base_echo > base_echo if_success echo awesome > awesome

blah_blah > command not found if_success echo awesome >

gndps
  • 119