Vivek Goel
Vivek Goel

Reputation: 24140

Bash ignoring error for a particular command

I am using following options

set -o pipefail
set -e

In bash script to stop execution on error. I have ~100 lines of script executing and I don't want to check return code of every line in the script.

But for one particular command, I want to ignore the error. How can I do that?

Upvotes: 798

Views: 629639

Answers (13)

Konard
Konard

Reputation: 3004

To do it for multiple lines at the same time:

set +e
find "./csharp/Platform.$REPOSITORY_NAME/obj" -type f -iname "*.cs" -delete
find "./csharp/Platform.$REPOSITORY_NAME.Tests/obj" -type f -iname "*.cs" -delete
set -e

You can turn off failing on errors by set +e this will now ignore all errors after that line. Once you are done, and you want the script to fail again on any error, you can use set -e.

After applying set +e the find does not fail the whole script anymore, when files are not found. At the same time, error messages from find are still printed, but the whole script continues to execute. So it is easy to debug if that causes the problem.

This is useful for CI & CD (for example in GitHub Actions).

Upvotes: 30

Rodrigo Prazim
Rodrigo Prazim

Reputation: 858

I have a similar but not the same scenario:

#!/bin/bash
CHECK=$(unbound-checkconf 2>&1)
if [[ $CHECK == *"no errors"* ]]; then
    echo $CHECK
else
    echo "Failed!"
fi

Only add: 2>&1

Before:

[root@dns-recursive ~]# ./unbound.sh
/etc/unbound/unbound.conf:16: error: unknown keyword 'erver'
/etc/unbound/unbound.conf:16: error: stray ':'
/etc/unbound/unbound.conf:20: error: syntax error
read /etc/unbound/unbound.conf failed: 3 errors in configuration file
Failed!

After:

[root@dns-recursive ~]# ./unbound.sh
Failed!

Upvotes: 1

Almaz Gareev
Almaz Gareev

Reputation: 191

Thanks for the simple solution here from above:

<particular_script/command> || true

The following construction could be used for additional actions/troubleshooting of script steps and additional flow control options:

if <particular_script/command>
then
   echo "<particular_script/command> is fine!"
else
   echo "<particular_script/command> failed!"
   #exit 1
fi

We can brake the further actions and exit 1 if required.

Upvotes: 17

Robert.C
Robert.C

Reputation: 71

output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
echo $output
echo $exit_status

Example of using this to create a log file

log_event(){
timestamp=$(date '+%D %T') #mm/dd/yy HH:MM:SS
echo -e "($timestamp) $event" >> "$log_file"
}

output=$(*command* 2>&1) && exit_status=$? || exit_status=$?

if [ "$exit_status" = 0 ]
    then
        event="$output"
        log_event
    else
        event="ERROR $output"
        log_event
fi

Upvotes: 7

Igor Chubin
Igor Chubin

Reputation: 64563

The solution:

particular_script || true

Example:

$ cat /tmp/1.sh
particular_script()
{
    false
}

set -e

echo one
particular_script || true
echo two
particular_script
echo three

$ bash /tmp/1.sh
one
two

three will be never printed.

Also, I want to add that when pipefail is on, it is enough for shell to think that the entire pipe has non-zero exit code when one of commands in the pipe has non-zero exit code (with pipefail off it must the last one).

$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0

Upvotes: 1300

volingas
volingas

Reputation: 1173

If you want to prevent your script failing and collect the return code:

command () {
    return 1  # or 0 for success
}

set -e

command && returncode=$? || returncode=$?
echo $returncode

returncode is collected no matter whether command succeeds or fails.

Upvotes: 15

Arslan Qadeer
Arslan Qadeer

Reputation: 2239

Don't stop and also save exit status

Just in case if you want your script not to stop if a particular command fails and you also want to save error code of failed command:

set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE

Upvotes: 223

Q-life
Q-life

Reputation: 74

I kind of like this solution :

: `particular_script`

The command/script between the back ticks is executed and its output is fed to the command ":" (which is the equivalent of "true")

$ false
$ echo $?
1
$ : `false`
$ echo $?
0

edit: Fixed ugly typo

Upvotes: 0

Foto Blysk
Foto Blysk

Reputation: 344

while || true is preferred one, but you can also do

var=$(echo $(exit 1)) # it shouldn't fail

Upvotes: 1

Payman
Payman

Reputation: 2880

I have been using the snippet below when working with CLI tools and I want to know if some resource exist or not, but I don't care about the output.

if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
    echo "none exist actually exist!"
fi

Upvotes: 2

Timo
Timo

Reputation: 3404

Instead of "returning true", you can also use the "noop" or null utility (as referred in the POSIX specs) : and just "do nothing". You'll save a few letters. :)

#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."

Upvotes: 63

Lily Finley
Lily Finley

Reputation: 3007

More concisely:

! particular_script

From the POSIX specification regarding set -e (emphasis mine):

When this option is on, if a simple command fails for any of the reasons listed in Consequences of Shell Errors or returns an exit status value >0, and is not part of the compound list following a while, until, or if keyword, and is not a part of an AND or OR list, and is not a pipeline preceded by the ! reserved word, then the shell shall immediately exit.

Upvotes: 87

Lars Kotthoff
Lars Kotthoff

Reputation: 109232

Just add || true after the command where you want to ignore the error.

Upvotes: 278

Related Questions