user6934519
user6934519

Reputation:

Using Set -e , how to make exception for one command

Using set -e in the shell script can let the process exit immediately if one of the commands exits with a non-zero status

However, if I want to exclude one command, so that if that specific command exits with non-zero value, the process continues.

Upvotes: 3

Views: 1279

Answers (3)

user19264607
user19264607

Reputation: 59

( set +e; command; ) do not work

( set +e; command; true ) is the solution

Example:

#!/usr/bin/bash
set -e
( set +e ; killall DUMMY_PROCESS_ABC )
echo happy end

This will work:

#!/usr/bin/bash
set -e
echo $( set +e ; killall DUMMY_PROCESS_ABC )
echo happy end

this also work:

#!/usr/bin/bash
set -e
(set +e ; killall DUMMY_PROCESS_ABC ; true)
echo happy end

Upvotes: 0

William Pursell
William Pursell

Reputation: 212414

First rule, don't use set -e. Second rule, see rule 1. The implementation of set -e has strange behavior in edge cases, and has changed through various versions of shells. It is safest not to use it. However, you can suppress it simply by making your command part of a compound command. That is, instead of

cmd_which_may_fail

you can simply do:

cmd_which_may_fail || true

Now, if cmd_which_may_fail does fail, the script will not exit.

Note that is is sometimes tempting (and you will often see code that does this) to do something like cmd_which_may_fail || echo 'command failed!' >&2, but you really should not do that. Instead, allow cmd_which_may_fail to emit a reasonable error message (most common commands do, and if you have a command that doesn't emit good error messages you might want to reconsider using it at all), since that process will have context and can write a useful error message. Command failed is generally considered a useless error message.

Upvotes: 3

KamilCuk
KamilCuk

Reputation: 141493

I usually do

command ||:

the return status of : is zero. If command returns nonzero status, then : is executed, which returns zero status. If command returns a zero status, then : is not executed. In both cases - the return status is zero, ie. success.

I've seen:

command |:

Well... it's one character shorter, but binding stdout to : process seems like a waste of cpu time for me. The return status of the pipe is the return status of the last executed command, and it's :. But this can fail when set -o pipefail, so I wouldn't recommend it.

You can run a command in a subshell:

( set +e; command; )

this allows for more flexibility, but you need to add ( before the command and is far more typing.

Upvotes: 2

Related Questions