23

In a sort of try/catch form I want to execute a bash that doesn't stop if an error occurs.

The specific bash is:

#!/bin/sh

invoke-rc.d tomcat stop

rm -fr /var/webapps/
cp -R $WEBAPP /var/webapps/
invoke-rc.d tomcat start

I want to exec "invoke-rc.d tomcat stop" and even if Tomcat is not running, continue to execute the other bash commands.

4
  • 6
    Isn't that bash's default behavior? I could have sworn it was (you need to take explicit action to terminate a script if some command fails...) Commented Jul 2, 2009 at 15:35
  • If you execute this script and tomcat is not running the script will stop execution since the first command return error. I want the script to continue. Commented Jul 2, 2009 at 15:38
  • @Alex: it is default but there is probablt something that overrides the default setting. Commented Jul 2, 2009 at 16:23
  • 3
    I'm with Alex - bash is misbehaving, or has been configured to (mis)behave by exiting on an error. Use: 'set +e' to counteract the effect of 'set -e' (which means terminate on error). And sort out what it is in your environment setup that makes bash misbehave - all sorts of scripts will fail unexpectedly if your shell bails on the first error. Commented Jul 2, 2009 at 16:54

5 Answers 5

32

Try:

invoke-rc.d tomcat stop > /dev/null 2>&1 || true

A little background:

user@tower: # true
user@tower: # echo $?
0
user@tower: # false
user@tower: # echo $?
1

user@tower: # which true
/bin/true
user@tower: # which false
/bin/false

The real solution is looking at the tomcat init script to see how it knows if tomcat is running :) That way, you don't pester it needlessly.

See this post on the other suggestion to unset / set +e. While it would solve your immediate problem, you may find that you need the recently unset behavior in your own script, especially since you are copying files.

This is one of the biggest reasons why true and false were made, other than making Makefiles behave as expected in a variety of build environments.

Also, set +e is not entirely portable, i.e. some versions of Solaris (and even Dash) .. but I doubt that this is a concern for you.

Sign up to request clarification or add additional context in comments.

6 Comments

I removed the paths of your code and the root user because somebody might think you need to be su. Hope you don't mind ;)
@victor hugo - Thanks. I edited this post a few times and failed to notice that I left the paths in tact :) I must be slightly brain dead today.
i actually don't understand the part 2>&1 || true. I understand > /dev/null means the error gets redirected there but I neither understand the syntax nor the meaning of the other part. Can you maybe explain?
@Toskan > /dev/null Redirects stdout to /dev/null. 2>&1 redirects stderr to stdout, effectively sending both stdout and stderr to the null device. || true ensures that the command exits with a zero status, even if it failed. It's like saying if this does not work, run /bin/true and return that value instead. It's a logical OR. E.g. [ -d /etc ] || echo "your system is broken" (if /etc is not a directory, echo something).
Is redirecting the output to /dev/null optional? I have a bash script that calls a database client to drop some indexes, import a lot of data, and then restore the indexes. I'd like those indexes to be put back if the import fails, but I'd like to see the output and know the import failed, too. Can printing to stderr cause my script to exit after I called set -e, or can I just omit the redirect?
|
29

Disable the "exit immediately" option with set +e, run your command, then optionally re-enable it with set -e:

set +e
invoke-rc.d tomcat stop
set -e  # optional

See section 4.3.1 of the Bash manual for an explanation of the set builtin and all of its various options (of which there are many).

Comments

4

Use bash's set command to temporarily disable exit-on-nonzero behaviour.

set +e
invoke-rc.d tomcat stop
set -e

2 Comments

You should write a little explanation of your script. Just click 'edit'. BTW Welcome to SO
set {args} is not always portable. However, if you do: set +e || { code to cope with a brain dead shell } Its just fine for anything worth its salt in POSIX conformity. Universally, its much easier (and much more portable) to just use true / false.
1

If invoke-rc.d tomcat stop is the only thing you want to protect against failing, maybe invoke-rc.d tomcat stop || true may do it? That should never have a non-zero exit status.

Comments

-4

Try redirecting the standard error to a file ...something like 2> myerror.

2 Comments

If seen something like command > /dev/null. Is it something like that? This will make the output of the command go to a file. But does also catch the error?
This does not recover from the error, it merely hides the cause.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.