Get error code bash

Is there a way I can do what stated in the title from the terminal commands, or will I have to look into the codes?

Exit codes indicates a failure condition when ending a program and they fall between 0 and 255. The shell and its builtins may use especially the values above 125 to indicate specific failure modes, so list of codes can vary between shells and operating systems (e.g. Bash uses the value 128+N as the exit status). See: Bash — 3.7.5 Exit Status or man bash.

In general a zero exit status indicates that a command succeeded, a non-zero exit status indicates failure.

To check which error code is returned by the command, you can print $? for the last exit code or ${PIPESTATUS[@]} which gives a list of exit status values from pipeline (in Bash) after a shell script exits.

There is no full list of all exit codes which can be found, however there has been an attempt to systematize exit status numbers in kernel source, but this is main intended for C/C++ programmers and similar standard for scripting might be appropriate.

Some list of sysexits on both Linux and BSD/OS X with preferable exit codes for programs (64-78) can be found in /usr/include/sysexits.h (or: man sysexits on BSD):

0   /* successful termination */
64  /* base value for error messages */
64  /* command line usage error */
65  /* data format error */
66  /* cannot open input */
67  /* addressee unknown */
68  /* host name unknown */
69  /* service unavailable */
70  /* internal software error */
71  /* system error (e.g., can't fork) */
72  /* critical OS file missing */
73  /* can't create (user) output file */
74  /* input/output error */
75  /* temp failure; user is invited to retry */
76  /* remote error in protocol */
77  /* permission denied */
78  /* configuration error */
/* maximum listed value */

The above list allocates previously unused exit codes from 64-78. The range of unallotted exit codes will be further restricted in the future.

However above values are mainly used in sendmail and used by pretty much nobody else, so they aren’t anything remotely close to a standard (as pointed by @Gilles).

In shell the exit status are as follow (based on Bash):

  • 1125 — Command did not complete successfully. Check the command’s man page for the meaning of the status, few examples below:

  • 1 — Catchall for general errors

    Miscellaneous errors, such as «divide by zero» and other impermissible operations.

    Example:

    $ let "var1 = 1/0"; echo $?
    -bash: let: var1 = 1/0: division by 0 (error token is "0")
    1
    
  • 2 — Misuse of shell builtins (according to Bash documentation)

    Missing keyword or command, or permission problem (and diff return code on a failed binary file comparison).

    Example:

     empty_function() {}
    
  • 6 — No such device or address

    Example:

    $ curl foo; echo $?
    curl: (6) Could not resolve host: foo
    6
    
  • 124 — command times out

  • 125 — if a command itself failssee: coreutils
  • 126 — if command is found but cannot be invoked (e.g. is not executable)

    Permission problem or command is not an executable.

    Example:

    $ /dev/null
    $ /etc/hosts; echo $?
    -bash: /etc/hosts: Permission denied
    126
    
  • 127 — if a command cannot be found, the child process created to execute it returns that status

    Possible problem with $PATH or a typo.

    Example:

    $ foo; echo $?
    -bash: foo: command not found
    127
    
  • 128 — Invalid argument to exit

    exit takes only integer args in the range 0 — 255.

    Example:

    $ exit 3.14159
    -bash: exit: 3.14159: numeric argument required
    
  • 128254 — fatal error signal «n» — command died due to receiving a signal. The signal code is added to 128 (128 + SIGNAL) to get the status (Linux: man 7 signal, BSD: man signal), few examples below:

  • 130 — command terminated due to Ctrl-C being pressed, 130-128=2 (SIGINT)

    Example:

    $ cat
    ^C
    $ echo $?
    130
    
  • 137 — if command is sent the KILL(9) signal (128+9), the exit status of command otherwise

    kill -9 $PPID of script.

  • 141SIGPIPE — write on a pipe with no reader

    Example:

    $ hexdump -n100000 /dev/urandom | tee &>/dev/null >(cat > file1.txt) >(cat > file2.txt) >(cat > file3.txt) >(cat > file4.txt) >(cat > file5.txt)
    $ find . -name '*.txt' -print0 | xargs -r0 cat | tee &>/dev/null >(head /dev/stdin > head.out) >(tail /dev/stdin > tail.out)
    xargs: cat: terminated by signal 13
    $ echo ${PIPESTATUS[@]}
    0 125 141
    
  • 143 — command terminated by signal code 15 (128+15=143)

    Example:

    $ sleep 5 && killall sleep &
    [1] 19891
    $ sleep 100; echo $?
    Terminated: 15
    143
    
  • 255* — exit status out of range.

    exit takes only integer args in the range 0 — 255.

    Example:

    $ sh -c 'exit 3.14159'; echo $?
    sh: line 0: exit: 3.14159: numeric argument required
    255
    

According to the above table, exit codes 1 — 2, 126 — 165, and 255 have special meanings, and should therefore be avoided for user-specified exit parameters.

Please note that out of range exit values can result in unexpected exit codes (e.g. exit 3809 gives an exit code of 225, 3809 % 256 = 225).

See:

  • Appendix E. Exit Codes With Special Meanings at Advanced Bash-Scripting Guide
  • Writing Better Shell Scripts – Part 2 at Innovationsts

Инструменты автоматизации и мониторинга удобны тем, что разработчик может взять готовые скрипты, при необходимости адаптировать и использовать в своём проекте. Можно заметить, что в некоторых скриптах используются коды завершения (exit codes), а в других нет. О коде завершения легко забыть, но это очень полезный инструмент. Особенно важно использовать его в скриптах командной строки.

Что такое коды завершения

В Linux и других Unix-подобных операционных системах программы во время завершения могут передавать значение родительскому процессу. Это значение называется кодом завершения или состоянием завершения. В POSIX по соглашению действует стандарт: программа передаёт 0 при успешном исполнении и 1 или большее число при неудачном исполнении.

Почему это важно? Если смотреть на коды завершения в контексте скриптов для командной строки, ответ очевиден. Любой полезный Bash-скрипт неизбежно будет использоваться в других скриптах или его обернут в однострочник Bash. Это особенно актуально при использовании инструментов автоматизации типа SaltStack или инструментов мониторинга типа Nagios. Эти программы исполняют скрипт и проверяют статус завершения, чтобы определить, было ли исполнение успешным.

Кроме того, даже если вы не определяете коды завершения, они всё равно есть в ваших скриптах. Но без корректного определения кодов выхода можно столкнуться с проблемами: ложными сообщениями об успешном исполнении, которые могут повлиять на работу скрипта.

Что происходит, когда коды завершения не определены

В Linux любой код, запущенный в командной строке, имеет код завершения. Если код завершения не определён, Bash-скрипты используют код выхода последней запущенной команды. Чтобы лучше понять суть, обратите внимание на пример.

#!/bin/bash
touch /root/test
echo created file

Этот скрипт запускает команды touch и echo. Если запустить этот скрипт без прав суперпользователя, команда touch не выполнится. В этот момент мы хотели бы получить информацию об ошибке с помощью соответствующего кода завершения. Чтобы проверить код выхода, достаточно ввести в командную строку специальную переменную $?. Она печатает код возврата последней запущенной команды.

$ ./tmp.sh 
touch: cannot touch '/root/test': Permission denied
created file
$ echo $?
0

Как видно, после запуска команды ./tmp.sh получаем код завершения 0. Этот код говорит об успешном выполнении команды, хотя на самом деле команда не выполнилась. Скрипт из примера выше исполняет две команды: touch и echo. Поскольку код завершения не определён, получаем код выхода последней запущенной команды. Это команда echo, которая успешно выполнилась.

Скрипт:

#!/bin/bash
touch /root/test

Если убрать из скрипта команду echo, можно получить код завершения команды touch.

$ ./tmp.sh 
touch: cannot touch '/root/test': Permission denied
$ echo $?
1

Поскольку touch в данном случае — последняя запущенная команда, и она не выполнилась, получаем код возврата 1.

Как использовать коды завершения в Bash-скриптах

Удаление из скрипта команды echo позволило нам получить код завершения. Что делать, если нужно сделать разные действия в случае успешного и неуспешного выполнения команды touch? Речь идёт о печати stdout в случае успеха и stderr в случае неуспеха.

Проверяем коды завершения

Выше мы пользовались специальной переменной $?, чтобы получить код завершения скрипта. Также с помощью этой переменной можно проверить, выполнилась ли команда touch успешно.

#!/bin/bash
touch /root/test 2> /dev/null
if [ $? -eq 0 ]
then
  echo "Successfully created file"
else
  echo "Could not create file" >&2
fi

После рефакторинга скрипта получаем такое поведение:

  • Если команда touch выполняется с кодом 0, скрипт с помощью echo сообщает об успешно созданном файле.
  • Если команда touch выполняется с другим кодом, скрипт сообщает, что не смог создать файл.

Любой код завершения кроме 0 значит неудачную попытку создать файл. Скрипт с помощью echo отправляет сообщение о неудаче в stderr.

Выполнение:

$ ./tmp.sh
Could not create file

Создаём собственный код завершения

Наш скрипт уже сообщает об ошибке, если команда touch выполняется с ошибкой. Но в случае успешного выполнения команды мы всё также получаем код 0.

$ ./tmp.sh
Could not create file
$ echo $?
0

Поскольку скрипт завершился с ошибкой, было бы не очень хорошей идеей передавать код успешного завершения в другую программу, которая использует этот скрипт. Чтобы добавить собственный код завершения, можно воспользоваться командой exit.

#!/bin/bash
touch /root/test 2> /dev/null
if [ $? -eq 0 ]
then
  echo "Successfully created file"
  exit 0
else
  echo "Could not create file" >&2
  exit 1
fi

Теперь в случае успешного выполнения команды touch скрипт с помощью echo сообщает об успехе и завершается с кодом 0. В противном случае скрипт печатает сообщение об ошибке при попытке создать файл и завершается с кодом 1.

Выполнение:

$ ./tmp.sh
Could not create file
$ echo $?
1

Как использовать коды завершения в командной строке

Скрипт уже умеет сообщать пользователям и программам об успешном или неуспешном выполнении. Теперь его можно использовать с другими инструментами администрирования или однострочниками командной строки.

Bash-однострочник:

$ ./tmp.sh && echo "bam" || (sudo ./tmp.sh && echo "bam" || echo "fail")
Could not create file
Successfully created file
bam

В примере выше && используется для обозначения «и», а || для обозначения «или». В данном случае команда выполняет скрипт ./tmp.sh, а затем выполняет echo "bam", если код завершения 0. Если код завершения 1, выполняется следующая команда в круглых скобках. Как видно, в скобках для группировки команд снова используются && и ||.

Скрипт использует коды завершения, чтобы понять, была ли команда успешно выполнена. Если коды завершения используются некорректно, пользователь скрипта может получить неожиданные результаты при неудачном выполнении команды.

Дополнительные коды завершения

Команда exit принимает числа от 0 до 255. В большинстве случаев можно обойтись кодами 0 и 1. Однако есть зарезервированные коды, которые обозначают конкретные ошибки. Список зарезервированных кодов можно посмотреть в документации.

Адаптированный перевод статьи Understanding Exit Codes and how to use them in bash scripts by Benjamin Cane. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.

Check Exit Code in Bash

This tutorial will describe several methods for getting and displaying the exit status of a statement in Bash. We will first discuss using a simple if statement to get the exit status, after which we will discuss alternatives and shorthand notations for getting the exit status.

Check Exit Code in Bash

The exit status is essentially an integer that tells us whether or not the command succeeded. Non-intuitively, an exit status of 0 indicates success, and any non-zero value indicates failure/error.

This non-intuitive solution allows for different error codes to represent different errors. For example, if a command is not found, then the exit status of 127 will be returned.

The way to check the exit code in Bash is by using the $? command. If you wish to output the exit status, it can be done by:

# your command here
testVal=$?
echo testVal

We know that non-zero exit codes are used to report errors. If we want to check for errors in general, we can write a small script with the command in question and an if statement that checks whether the exit code is of an error (non-zero) or if the exit code indicates proper execution.

# your command here
testVal=$?
if [$testVal -ne 0]; then
    echo "There was some error"
fi
exit $testVal

A shorthand notation can be done using a test on the $? command. A minimal example of this code can be:

# your command here
test $? -eq 0 || echo "There was some error"

For a better understanding of the above statement, we can expand it.

# your command here
exitStat = $?
test $exitStat -eq 0 && echo "No error! Worked fine" || echo "There was some error";
exit $exitStat

Above, we can see the "No error! Worked fine" message in case of successful execution, and the error message in case of failure.

Important Notes and Possible Alternate Solutions

If exit codes are used to see whether or not the command is executed correctly, we have a much simpler alternative.

# define your_command here
# your_command = enter a command here
if your_command; then
    echo command returned true
else
    echo command returned an error
fi

In this case, we generally get the same output as we would using the first couple of options. Furthermore, getting specific information on the exit code or getting the specific exit code requires running $? manually.

Я новый пользователь системы Linux. Как мне получить код завершения команды?

Как получить код вывода или статус команды оболочки Linux или Unix и сохранить его в переменной оболочки?

Введение. Каждая команда оболочки Linux или Unix возвращает состояние, когда она завершается нормально или ненормально.

Например, если скрипт backup.sh не выполнен, и он возвращает код, который сообщает скрипту оболочки отправить электронное письмо админу.

Что такое код вывода в оболочке bash?

Каждая команда Linux или Unix, выполняемая скриптом оболочки или пользователем, имеет статус вывода.

Статус вывода – это целое число.

0 состояние выхода означает, что команда была успешной без каких-либо ошибок.

Ненулевое (1-255 значений) состояние выхода означает, что команда была неудачной.

Как узнать код вывода команды

Вам нужно использовать определенную переменную оболочки с именем $? чтобы получить статус вывода из ранее выполненной команды.

Выведем $? переменной используя команду echo или команду printf:

date
echo $?

0
date-foo-bar

printf '%dn' $?
127 

Из приведенных выше выводов ясно, что код вывода 0 означает, что команда date была успешной.

Кроме того, код вывода – 127 (не ноль), так как команда nonexistant не была успешной.

Bash как получить код завершения команды – Как использовать коды вывода в скриптах оболочки

Итак, как вы сохранить статус вывода команды в переменной оболочки?

Просто назначьте $? в переменную оболочки. Синтаксис:

command
status=$?
## run date command ##
cmd="date"
$cmd
## get status ##
status=$?
## take some decision ## 
[ $status -eq 0 ] && echo "$cmd command was successful" || echo "$cmd failed"

Как мне установить код вывода для моих собственных скриптов оболочки?

Команда exit вызывает обычное завершение скриптов оболочки.

Вывод из оболочки со статусом N. Синтаксис:

#!/bin/bash
/path/to/some/command
[ $? -eq 0 ]  || exit 1

Пример скрипта оболочки для получения кода завершения команды

#!/bin/bash
#
# Sample shell script to demo exit code usage #
#
set -e
 
## find ip in the file ##
grep -q 192.168.2.254 /etc/resolv.conf
 
## Did we found IP address? Use exit status of the grep command ##
if [ $? -eq 0 ]
then
  echo "Success: I found IP address in file."
  exit 0
else
  echo "Failure: I did not found IP address in file. Script failed" >&2
  exit 1
fi

Заключение

На этой странице показано, как использовать коды вывода в системах на основе Linux или Unix и как получить статус вывода / код команды.

Scripting is one of the key tools for a sysadmin to manage a set of day-to-day activities such as running backups, adding users/groups, installing/updating packages, etc. While writing a script, error handling is one of the crucial things to manage.

This article shows some basic/intermediate techniques of dealing with error handling in Bash scripting. I discuss how to obtain the error codes, get verbose output while executing the script, deal with the debug function, and standard error redirection. Using these techniques, sysadmins can make their daily work easy.

[ Readers also liked: Bash command line exit codes demystified ]

Exit status

In Bash scripting, $? prints the exit status. If it returns zero, it means there is no error. If it is non-zero, then you can conclude the earlier task has some issue.

A basic example is as follows:

$ cat myscript.sh
           #!/bin/bash
           mkdir learning
           echo $?

If you run the above script once, it will print 0 because the directory does not exist, therefore the script will create it. Naturally, you will get a non-zero value if you run the script a second time, as seen below:

$ sh myscript.sh
mkdir: cannot create directory 'learning': File exists
1

Best practices

It is always recommended to enable the debug mode by adding the -e option to your shell script as below:

$ cat test3.sh
!/bin/bash
set -x
echo "hello World"
mkdiir testing
 ./test3.sh
+ echo 'hello World'
hello World
+ mkdiir testing
./test3.sh: line 4: mkdiir: command not found

You can write a debug function as below, which helps to call it anytime, using the example below:

$ cat debug.sh
#!/bin/bash
_DEBUG="on"
function DEBUG()
{
 [ "$_DEBUG" == "on" ] && $@
}
DEBUG echo 'Testing Debudding'
DEBUG set -x
a=2
b=3
c=$(( $a + $b ))
DEBUG set +x
echo "$a + $b = $c"

Which prints:

$ ./debug.sh
Testing Debudding
+ a=2
+ b=3
+ c=5
+ DEBUG set +x
+ '[' on == on ']'
+ set +x
2 + 3 = 5

Standard error redirection

You can redirect all the system errors to a custom file using standard errors, which can be denoted by the number 2. Execute it in normal Bash commands, as demonstrated below:

$ mkdir users 2> errors.txt
$ cat errors.txt
mkdir: cannot create directory ‘users’: File exists

Most of the time, it is difficult to find the exact line number in scripts. To print the line number with the error, use the PS4 option (supported with Bash 4.1 or later). Example below:

$ cat test3.sh
#!/bin/bash
PS4='LINENO:'

set -x
echo "hello World"
mkdiir testing

You can easily see the line number while reading the errors:

$ /test3.sh
5: echo 'hello World'
hello World
6: mkdiir testing
./test3.sh: line 6: mkdiir: command not found

[ Get this free ebook: Managing your Kubernetes clusters for dummies. ]

Wrap up

Managing errors is a key skill for administrators when writing scripts. These tips should help make your life easier when troubleshooting Bash scripts or even general commands.

Понравилась статья? Поделить с друзьями:
  • Get error 500 internal server error
  • Go microsoft com fwlink linkid 528892 как исправить
  • Go microsoft com fwlink linkid 225039 как исправить
  • Go get unknown revision error
  • Go func return error