Bash игнорировать ошибку

Bash, or the Bourne-Again Shell, is a powerful command-line interface (CLI) that is commonly used in Linux and Unix systems. When working with Bash, it is important to understand how to handle errors that may occur during the execution of commands. In this article, we will discuss various ways to understand and ignore errors in Bash. Bash scripting is a powerful tool for automating and simplifying various tasks in Linux and Unix systems. However, errors can occur during the execution of commands and can cause scripts to fail. In this article, we will explore the various ways to understand and handle errors in Bash. We will look at ways to check the exit status code and error messages of commands, as well as techniques for ignoring errors when necessary. By understanding and properly handling errors, you can ensure that your Bash scripts run smoothly and achieve the desired outcome.

Step-by-step approach for understanding and ignoring errors in Bash:

Step 1: Understand how errors are generated in Bash.

  • When a command is executed, it returns an exit status code.
  • A successful command will have an exit status of 0, while a failed command will have a non-zero exit status.
  • Error messages are generated when a command returns a non-zero exit status code.

Step 2: Check the exit status code of a command.

  • To check the exit status code of a command, you can use the $? variable, which holds the exit status of the last executed command.
  • For example, after executing the command ls non_existent_directory, you can check the exit status code by running echo $? The output
  • will be non-zero (e.g., 2) indicating that the command failed.

Step 3: Check the error message of a command.

  • To check the error message of a command, you can redirect the standard error output (stderr) to a file or to the standard output (stdout) using the 2> operator.
  • For example, you can redirect the stderr of the command ls non_existent_directory to a file by running ls non_existent_directory 2> error.log. Then you can view the error message by running cat error.log.

Step 4: Use the set -e command.

  • The set -e command causes the script to exit immediately if any command exits with a non-zero status. This can be useful for detecting and handling errors early on in a script.
  • For example, if you run set -e followed by ls non_existent_directory, the script will exit immediately with an error message. 

Step 5: Ignore errors when necessary.

  • To ignore errors, you can use the command || true construct. This construct allows you to execute a command, and if it returns a non-zero exit status, the command following the || operator (in this case, true) will be executed instead.
  • For example, you can run rm non_existent_file || true to remove a file that does not exist without exiting with an error.
  • Another way to ignore errors is to use the command 2> /dev/null construct, which redirects the standard error output (stderr) of a command to the null device, effectively ignoring any error messages.
  • Additionally, you can use the command 2>&1 >/dev/null construct to ignore both standard error and standard output.
  • You can also use the command || : construct which allows you to execute a command and if it returns a non-zero exit status, the command following the || operator (in this case, 🙂 will be executed instead. The: command is a no-op command that does nothing, effectively ignoring the error.

Practical Explanation for Understanding Errors

First, let’s examine how errors are generated in Bash. When a command is executed, it returns an exit status code. This code indicates whether the command was successful (exit status 0) or not (non-zero exit status). For example, the following command attempts to list the files in a directory that does not exist:

$ ls non_existent_directory
ls: cannot access 'non_existent_directory': No such file or directory

As you can see, the command generated an error message and returned a non-zero exit status code. To check the exit status code of a command, you can use the $? variable, which holds the exit status of the last executed command.

$ echo $?
2

In addition to the exit status code, you can also check the standard error output (stderr) of a command to understand errors. This can be done by redirecting the stderr to a file or to the standard output (stdout) using the 2> operator.

For example, the following script will redirect the stderr of a command to a file:

$ ls non_existent_directory 2> error.log
$ cat error.log
ls: cannot access 'non_existent_directory': No such file or directory

You can also redirect the stderr to the stdout using the 2>&1 operator, which allows you to see the error message along with the standard output of the command.

$ ls non_existent_directory 2>&1
ls: cannot access 'non_existent_directory': No such file or directory

Another useful tool for understanding errors is the set -e command, which causes the script to exit immediately if any command exits with a non-zero status. This can be useful for detecting and handling errors early on in a script.

$ set -e
$ ls non_existent_directory
# as soon as you hit enter this will exit shell and will close the terminal.

After this command script will exit from the shell if the exit code is nonzero.

Practical Explanation for Ignoring Errors

While it is important to handle errors in Bash scripts, there may be certain situations where you want to ignore errors and continue running the script. In this section, we will discuss different methods for ignoring errors in Bash and provide examples of how to implement them.

Heredoc

Heredoc is a feature in Bash that allows you to specify a string or command without having to escape special characters. This can be useful when you want to ignore errors that may occur while executing a command. The following example demonstrates how to use Heredoc to ignore errors.

#!/bin/bash

# Example of ignoring errors using Heredoc

# The `command` will fail but it will not stop execution
cat <<EOF | while read line; do
  echo $line
done
command that will fail
EOF

# Rest of the script

In this example, the command that is inside the Heredoc will fail, but the script will not stop execution. This is because the output of the command is piped to the while loop, which reads the output and ignores the error.

Pipefail

The pipe fails option in Bash can be used to change the behavior of pipelines so that the exit status of the pipeline is the value of the last (rightmost) command to exit with a non-zero status or zero if all commands exit successfully. This can be useful when you want to ignore errors that may occur while executing multiple commands in a pipeline. The following example demonstrates how to use the pipe fail option to ignore errors.

#!/bin/bash

# Example of ignoring errors using pipefail

# The `command1` will fail but it will not stop execution
set -o pipefail
command1 | command2

# Rest of the script

In this example, command1 will fail, but command2 will continue to execute, and the script will not stop execution.

Undefined Variables

By default, Bash will stop the execution of a script if an undefined variable is used. However, you can use the -u option to ignore this behavior and continue running the script even if an undefined variable is used. The following example demonstrates how to ignore undefined variables.

#!/bin/bash

# Example of ignoring undefined variables

set +u

echo $undefined_variable

# Rest of the script

In this example, the script will not stop execution when an undefined variable is used.

Compiling and Interpreting

When compiling or interpreting a script, errors may occur. However, these errors can be ignored by using the -f option when running the script. The following example demonstrates how to ignore errors when compiling or interpreting a script.

#!/bin/bash

# Example of ignoring errors when compiling or interpreting

bash -f script.sh

# Rest of the script

In this example, the script will continue to run even if there are errors during the compilation or interpretation process.

Traps

A trap is a way to execute a command or a set of commands when a specific signal is received by the script. This can be useful when you want to ignore errors and run a cleanup command instead. The following example demonstrates how to use a trap to ignore errors.

#!/bin/bash

# Example of ignoring errors using a trap

# Set a trap to run the cleanup function when an error occurs
trap cleanup ERR

# Function to run when an error occurs
cleanup() {
  echo "Cleaning up before exiting..."
}

# Command that will cause an error
command_that_will_fail

# Rest of the script

In this example, when the command_that_will_fail causes an error, the script will execute the cleanup function instead of stopping execution. This allows you to perform any necessary cleanup before exiting the script.

Examples of Bash for Error Handling:

Example 1: Error Handling Using a Conditional Condition

One way to handle errors in Bash is to use a conditional statement. The following example demonstrates how to check for a specific error and handle it accordingly.

#!/bin/bash

# Example of error handling using a conditional condition

file=example.txt

if [ ! -f $file ]; then
  echo "Error: $file does not exist"
  exit 1
fi

# Rest of the script

In this example, we check if the file “example.txt” exists using the -f option of the [ command. If the file does not exist, the script will print an error message and exit with a status code of 1. This allows the script to continue running if the file exists and exit if it does not.

Example 2: Error Handling Using the Exit Status Code

Another way to handle errors in Bash is to check the exit status code of a command. Every command in Bash returns an exit status code when it completes, with a code of 0 indicating success and any other code indicating an error. The following example demonstrates how to check the exit status code of a command and handle it accordingly.

#!/bin/bash

# Example of error handling using the exit status code

command1

if [ $? -ne 0 ]; then
  echo "Error: command1 failed"
  exit 1
fi

# Rest of the script

In this example, the script runs the command “command1” and then checks the exit status code using the special variable $?. If the exit status code is not 0, the script will print an error message and exit with a status code of 1.

Example 3: Stop the Execution on the First Error

When running a script, it can be useful to stop the execution on the first error that occurs. This can be achieved by using the set -e command, which tells Bash to exit the script if any command exits with a non-zero status code.

#!/bin/bash

# Stop execution on the first error

set -e

command1
command2
command3

# Rest of the script

In this example, if any of the commands “command1”, “command2” or “command3” fail, the script will exit immediately.

Example 4: Stop the Execution for Uninitialized Variable

Another way to stop execution on error is if an uninitialized variable is used during script execution. This can be achieved by using the set -u command, which tells Bash to exit the script if any uninitialized variable is used.

#!/bin/bash

# Stop execution for uninitialized variable

set -u

echo $uninitialized_variable

# Rest of the script

In this example, if the uninitialized_variable is not defined, the script will exit immediately.

Conclusion

In conclusion, understanding and ignoring errors in Bash is an important aspect of working with the command-line interface. By checking the exit status code of a command, its associated error message, and redirecting the stderr to a file or the stdout, you can understand what went wrong. And by using the command || true, command 2> /dev/null, command 2>&1 >/dev/null, and command || : constructs, you can ignore errors when necessary. It’s always a good practice to test these constructs in a testing environment before using them in production.

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?

Ryan Shillington's user avatar

asked Jun 27, 2012 at 17:34

Vivek Goel's user avatar

Vivek GoelVivek Goel

23k29 gold badges114 silver badges186 bronze badges

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

R. Oosterholt's user avatar

answered Jun 27, 2012 at 17:37

Igor Chubin's user avatar

Igor ChubinIgor Chubin

61.9k13 gold badges122 silver badges144 bronze badges

7

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

answered Jun 27, 2012 at 17:37

Lars Kotthoff's user avatar

Lars KotthoffLars Kotthoff

107k16 gold badges204 silver badges204 bronze badges

3

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

Ciro Santilli OurBigBook.com's user avatar

answered Aug 17, 2017 at 8:14

Arslan Qadeer's user avatar

5

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.

answered Apr 21, 2015 at 23:13

Lily Finley's user avatar

Lily FinleyLily Finley

2,8671 gold badge16 silver badges11 bronze badges

7

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.."

answered Nov 17, 2016 at 8:51

Timo's user avatar

TimoTimo

3,33530 silver badges25 bronze badges

5

I found another way to solve this:

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).

answered Feb 23, 2020 at 13:35

Konard's user avatar

KonardKonard

2,32828 silver badges21 bronze badges

3

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.

answered May 20, 2020 at 13:28

Almaz Gareev's user avatar

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.

answered Sep 10, 2019 at 10:33

volingas's user avatar

volingasvolingas

1,0339 silver badges21 bronze badges

2

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

answered Mar 25, 2020 at 3:25

Robert.C's user avatar

Robert.CRobert.C

511 silver badge1 bronze badge

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

answered Jun 23, 2018 at 22:12

Payman's user avatar

PaymanPayman

2,6401 gold badge12 silver badges18 bronze badges

1

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

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

answered Apr 25, 2019 at 15:17

Foto Blysk's user avatar

Foto BlyskFoto Blysk

3442 silver badges11 bronze badges

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

answered May 21, 2019 at 8:56

Q-life's user avatar

1

You can put 2>/dev/null behind a command to suppress errors:

ls /home/cas/thisfolderdoesntexist -> error

ls /home/cas/thisfolderdoesntexist 2>/dev/null -> no output because error is suppressed.

You can also put 2>/dev/null behind a script to run the complete script with errors suppressed:

./script.sh 2>/dev/null

What your doing is redirecting (>) errors (2) to /dev/null. Every piece of data (in this case the output of your command(s)/script) that is redirected to /dev/null will be completely ignored. See it as a trash can for data.


Edit:
2>/dev/null suppresses the output of the command, not the complete pipe. In the example that you gave, you’re supressing errors from the awk command. If the error is comming from the ls command, do the following (this will suppress errors from the ls command):

ls /bootpool 2>/dev/null | grep boot | awk 'NR==1{print $1}'

If the error is comming from the grep command:

ls /bootpool | grep boot 2>/dev/null | awk 'NR==1{print $1}'

I think you get it now.

A good thing to remember:

1 = stdout = normal output of a command

2 = stderr = error output of a command

0 = stdin = input to a command (this isn’t usefull for redirecting, more for logging)


I also improved your script (using shellcheck, you can install it or use their online tool link):

#!/bin/sh
boot=$(find /bootpool/*boot* 2>/dev/null | sed "s|/.*/||")
data=$(find /datapool/*boot* 2>/dev/null | sed "s|/.*/||")
echo "boot"
if [ "$boot" = "boot" ] 
then
        echo "boot"
        pass=$(grep rootpw /bootpool/boot/loader.conf | grep -o '".*"' | sed 's|"||g' | awk 'BEGIN { ORS = " " } { print }')

elif [ "$data" = "boot" ]
then
        pass=$(grep rootpw /datapool/boot/loader.conf | grep -o '".*"' | sed 's|"||g' | awk 'BEGIN { ORS = " " } { print }')

else
        echo "Couldn't find boot in bootpool nor datapool"
        exit
fi

if [ "$pass" = edjos ]
then
        echo "You are at default password. kindly change the password"
        oldpass=$(grep root /etc/master.passwd | awk 'NR==1 { print $1 }' | cut -d ':' -f 2 | sed 's/\$/\%/g')
        passwd
        newpass=$(grep root /etc/master.passwd | awk 'NR==1 { print $1 }' | cut -d ':' -f 2 | sed 's/\$/\%/g')
        if [ "$newpass" != "$oldpass" ]
        then              
                if [ "$boot" = "boot" ]
                then 
                        sed -i.bak '/mfsbsd.rootpw/s/edjos//' /bootpool/boot/loader.conf
                        sed -i.bak '/mfsbsd.rootpwhash/d' /bootpool/boot/loader.conf
                        echo "mfsbsd.rootpwhash=\"$newpass\""  >> /bootpool/boot/loader.conf
                        echo "Great! password updated successfully"

                elif [ "$data" = "boot" ]
                then
                        sed -i.bak '/mfsbsd.rootpw/s/edjos//' /datapool/boot/loader.conf
                        sed -i.bak '/mfsbsd.rootpwhash/d' /datapool/boot/loader.conf
                        echo "mfsbsd.rootpwhash=\"$newpass\""  >> /datapool/boot/loader.conf
                        echo "Great! password updated successfully"
                fi
        fi
else
        echo "Great! you are having authorised password"
fi
  1. You were using == but /bin/sh doesn’t make use of that. Only =. When you use /bin/bash, == will actually become usefull. But as you don’t, you need to use =.
  2. I changed the way you set the boot and data variables. The way you did it was inefficient.
  3. When both $boot and $data are empty, the script will catch it instead of letting you continue. This is handy because in your second if statement, when $oldpass and $newpass aren’t equal, it depends on either $boot or $data to contain «boot». But what if they don’t? That’s what the else is for in the first if-statement.
  4. Putting "" around variables. echo $var -> echo "$var"

I’m trying to show the number of lines, words and characters of all configuration files in /etc/*conf (with command wc).

How can I modify the command (or commandline) to not view the error messages?

quack quixote's user avatar

quack quixote

42.2k14 gold badges105 silver badges129 bronze badges

asked Mar 25, 2010 at 22:26

pedro's user avatar

1

wc /etc/*conf 2>/dev/null

answered Mar 25, 2010 at 23:33

Dennis Williamson's user avatar

Dennis WilliamsonDennis Williamson

106k19 gold badges167 silver badges187 bronze badges

i don’t have access to a shell right now, but you can try something like

cat /etc/*.conf 2> /dev/null | wc -l

That should redirect all the errors and leave the output to be passed to wc

answered Mar 25, 2010 at 22:39

Roy Rico's user avatar

Roy RicoRoy Rico

5,8787 gold badges44 silver badges57 bronze badges

1

Usually just redirect the standard output to /dev/null to ignore the output, but this is not good practice when writing shell scripts

Try use -q instead to run the shell in quite mode, which will produce less output.

This might not be relevant to the question, but just FYI.

answered May 1, 2013 at 7:10

imcoddy's user avatar

imcoddyimcoddy

2711 gold badge2 silver badges5 bronze badges

You must log in to answer this question.

Not the answer you’re looking for? Browse other questions tagged

.

Я использую следующие варианты

set -o pipefail
set -e

В скрипте bash остановить выполнение при ошибке. У меня ~ 100 строк выполнения скрипта, и я не хочу проверять код возврата каждой строки в скрипте.

Но для одной конкретной команды я хочу игнорировать ошибку. Как я могу это сделать?

4b9b3361

Ответ 1

Решение:

particular_script || true

Пример:

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

set -e

echo ein
particular_script || true
echo zwei
particular_script
echo drei

$ bash /tmp/1.sh
ein
zwei

drei никогда не будет напечатан.

Кроме того, я хочу добавить, что, когда pipefail включен,
достаточно, чтобы оболочка подумала, что весь канал имеет ненулевой код выхода
когда одна из команд в трубе имеет ненулевой код выхода (при этом pipefail он должен быть последним).

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

Ответ 2

Просто добавьте || true после команды, в которой вы хотите проигнорировать ошибку.

Ответ 3

Более кратко:

! particular_script

Из спецификации POSIX относительно set -e (выделено мной):

Если этот параметр включен, если простая команда не выполняется по любой из причин, перечисленных в Последствиях ошибок оболочки, или возвращает значение состояния выходa > 0 и не является частью составного списка через некоторое время, пока, или если ключевое слово и не является частью списка AND или OR и не является конвейером , которому предшествует! зарезервированное слово, то оболочка должна немедленно выйти.

Ответ 4

Не останавливайтесь и сохраняйте статус выхода

На всякий случай, если вы хотите, чтобы ваш сценарий не останавливался, если какая-то команда не выполнена, и вы также хотите сохранить код ошибки неудачной команды:

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

Ответ 5

Вместо «возврата true» вы также можете использовать утилиту «noop» или null (как указано в спецификации POSIX) : и просто «ничего не делать». Вы сохраните несколько писем. :)

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

Ответ 6

Я использовал приведенный ниже фрагмент при работе с инструментами CLI и хочу знать, существует какой-то ресурс или нет, но меня не волнует вывод.

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

Ответ 7

в то время как || true || true является предпочтительным, но вы также можете сделать

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

Ответ 8

Мне нравится это решение:

: 'particular_script'

Команда/скрипт между обратными галочками выполняется, и ее вывод подается на команду «:» (что эквивалентно «true»)

$ false
$ echo $?
1
$ : 'false'
$ echo $?
0

редактировать: исправлена некрасивая опечатка

Ответ 9

Если вы хотите предотвратить сбой сценария и собрать код возврата:

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

set -e

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

returncode собирается независимо от того, выполнена команда или нет.

Понравилась статья? Поделить с друзьями:
  • B8 непрерывный подсчет обнаруженных ошибок
  • Bash продолжить выполнение скрипта при ошибке
  • Bas ошибка мерседес 203
  • Baltur котел газовый ошибка e10
  • Bash подавить вывод ошибок