Linux service status exit code

What are exit codes in Linux?

Many candidates are rejected or down-leveled in technical interviews due to poor performance in behavioral or cultural fit interviews. Ace your interviews with this free course, where you will practice confidently tackling behavioral interview questions.

Overview

In Linux, an exit code indicates the response from the command or a script after execution. It ranges from 0 to 255. The exit codes help us determine whether a process ran:

  1. Successfully.
  2. Failed due to an error.
  3. Or another state that gives us an indication of an unexpected result.

Note: Exit codes are also known as return codes.

We can get the process’s exit code once the command or script execution is complete using $? .

Example

root@educative:/# echo "Hello There!"
Hello There!
root@educative:/# echo $?
0
root@educative:/# cat demofile.txt
cat: demofile.txt: No such file or directory
root@educative:/# echo $?
1

Note: The terminal is attached to the end of the shot. Please copy the commands from above and paste them into the terminal to try them.

Explanation

  1. We ran the command echo “Hello There!” and it printed Hello There! on the following line. Then we ran the command echo $? and it provided output as 0 , which indicates that the command ran successfully.
  2. We ran the command cat demofile.txt , and it gave us an error cat: demofile.txt: No such file or directory , and the return code is 1 , indicating a failure.

Reserved exit codes

Linux has some reserved exit codes with a special meaning. Here’s the list of exit codes:

Exit codes are usually used in the shell script to check the status and take actions accordingly. We run multiple commands in a shell script to check for an everyday use case and see if the command runs successfully. Here’s an example:

Источник

Getting the exit code of a failed systemd service

How to get the exit-code of a failed systemd service ? service some_service status prints the following :

 Active: failed (Result: exit-code) 

But what is that exit-code ? And are those exit-codes standard or do they have different meanings for different services?

1 Answer 1

systemctl status does have what you’re looking for:

$ systemctl status openproject-web-1.service ● openproject-web-1.service Loaded: loaded (/etc/systemd/system/openproject-web-1.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Mon 2020-05-25 08:17:17 CEST; 1 day 4h ago Process: 969 ExecStart=/usr/bin/openproject run web (code=exited, status=203/EXEC) Main PID: 969 (code=exited, status=203/EXEC) 

You see here under Main PID: you have (code=exited, status=203/EXEC) . That 203 is the exit code.

Читайте также:  Открыть блокнот в линукс

The exit codes are up to the specific application, but there are conventions. 0 is successful exit, 1-255 is abnormal exit, 256+ is out of range. The posix standard has a few special cases. But you’ll want to look at the documentation of the application for anything more than that.

. the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred

As JdePB describes below, systemd may set some exit codes itself in the range of 200 to 242. In the example above we have exit code 203 which means the actual execution failed (maybe the file was not found or was not marked as executable).

Источник

Script handling systemd service’s return code

I’m writing a systemd service which can be started or stopped using systemctl commands. However this program can also return with several return codes and I would like to handle those return codes. For example if the service was stopped with systemctl stop it should do nothing. But if it wasn’t killed by systemctl and returned by itself I want to run a post script on which I could get the return code and do actions depending on its value. Modified after @NarūnasK answer
When having systemd version >= v232 it’s okay with @NarūnasK answer However when not having the good systemd version how could it be done ? I though about doing something like

ExecStart=/bin/sh -c ' -C /etc/; [ $? -eq 1 ] && < >' 

1 Answer 1

Additional commands that are executed after the service is stopped. This includes cases where the commands configured in ExecStop= were used, where the service does not have any ExecStop= defined, or where the service exited unexpectedly. This argument takes multiple command lines, following the same scheme as described for ExecStart=. Use of these settings is optional. Specifier and environment variable substitution is supported. Note that – unlike ExecStop= – commands specified with this setting are invoked when a service failed to start up correctly and is shut down again.

It is recommended to use this setting for clean-up operations that shall be executed even when the service failed to start up correctly. Commands configured with this setting need to be able to operate even if the service failed starting up half-way and left incompletely initialized data around. As the service’s processes have been terminated already when the commands specified with this setting are executed they should not attempt to communicate with them.

Note that all commands that are configured with this setting are invoked with the result code of the service, as well as the main process’ exit code and status, set in the $SERVICE_RESULT, $EXIT_CODE and $EXIT_STATUS environment variables, see systemd.exec(5) for details.

In your script you can read $EXIT_CODE or $EXIT_STATUS environment variables and take appropriate action.

Читайте также:  Семейство ос linux особенности отличия от ос windows

You can use the following workaround with systemd < 232 .

#! /bin/bash -- sleep 5 ## Non standard exit code exit 255 
#! /bin/bash -- CODE="$" echo CODE: $CODE echo SERVICE_RESULT: $SERVICE_RESULT echo EXIT_CODE: $EXIT_CODE echo EXIT_STATUS: $EXIT_STATUS 
# systemctl cat sample_script.service # /etc/systemd/system/sample_script.service [Unit] Description=My service After=network.target rsyslog.service [Service] Type=simple Restart=never ExecStart=/bin/bash -c '/tmp/sample_script || /tmp/exit_handler $?' ExecStopPost=/tmp/exit_handler [Install] WantedBy=multi-user.target 

Status of the sample_script.service:

# systemctl status sample_script.service ● sample_script.service - My service Loaded: loaded (/etc/systemd/system/sample_script.service; enabled) Active: inactive (dead) since Thu 2017-12-14 12:29:16 GMT; 7s ago Process: 16511 ExecStopPost=/tmp/exit_handler (code=exited, status=0/SUCCESS) Process: 16505 ExecStart=/bin/bash -c /tmp/sample_script || /tmp/exit_handler $? (code=exited, status=0/SUCCESS) Main PID: 16505 (code=exited, status=0/SUCCESS) Dec 14 12:29:11 build-local systemd[1]: Started My service. Dec 14 12:29:16 build-local bash[16505]: CODE: 255 Dec 14 12:29:16 build-local bash[16505]: SERVICE_RESULT: Dec 14 12:29:16 build-local bash[16505]: EXIT_CODE: Dec 14 12:29:16 build-local bash[16505]: EXIT_STATUS: Dec 14 12:29:16 build-local exit_handler[16511]: CODE: N/A Dec 14 12:29:16 build-local exit_handler[16511]: SERVICE_RESULT: Dec 14 12:29:16 build-local exit_handler[16511]: EXIT_CODE: Dec 14 12:29:16 build-local exit_handler[16511]: EXIT_STATUS: 

You can see that exit_handler has been called twice. At first from bash where it has the exit code supplied to it and then as ExecStopPost= script, where positional argument of exit code was not supplied therefore it printed N/A.

Источник

Работа с linux. Exit codes.

Привет. Сегодня ещё один важный момент про работу с Linux — обработка кодов завершения процессов. У меня на данный момент стоит Ubuntu 18, все написанное дальше тестировалось на этой системе. Нюансы могут отличаться, но суть должна остаться неизменной. Код завершения (exit code) — число от 0 до 255, возвращаемое при завершении процесса в родительский процесс. Это число может быть интерпретировано программой и распознано как успех или провал.

Как правило, 0 код — успех, все остальные сигнализируют о разных причинах провала.

Как их отслеживать?

Получить код завершения предыдущего процесса можно с помощью команды `$?`

Читайте также:  Linux log ip address

1 — стандартный код для общих ошибок.

В данном случае ошибка — cat: /some_file.txt: Нет такого файла или каталога.

Коды завершения и конвейеры (pipelines)

У нас есть два оператора, позволяющие взаимодействовать с кодами завершения в конвейере — это `&&` и `||`

В теории `&&` можно было бы реализовать с помощью проверки условий if например так:

Или использовать `if [ $? -ne 0 ]; then` для `||`, но для конвейера такое решение не годится.

`&&`действует как логические И. Оператор запускает следующую команду, если код завершения предыдущей 0.

`||` действует как логическое ИЛИ. Оператор запускает следующую команду, если предыдущая вернула код отличный от 0.

Хоть решение с if не подойдет для какого-нибудь сложного конвейера, с несколькими уровнями вложений, его удобно использовать для файлов-скриптов.

Коды завершения и .sh файлы

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

Поэтому обычно && || используются в составе .sh скриптов для улучшения читаемости и сокращения связанных команд. Рассмотрим пару вариантов, которые я использовал в работе.

Нюанс в том, что .sh скрипт движется дальше и командой $? вы получите только код завершения последней команды. Поэтому если команда, которая может вернуть ошибку где-то в середине, то код затеряется и дальше его видно не будет. Если такой скрипт участвует в конвейере, то следующая команда получит ложный сигнал.

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

Если у вас есть несколько команд и важна правильность выполнения всего скрипта, но при этом нужно, чтобы скрипт проходил полностью (например в конце расположен код, удаляющий созданные вначале файлы вне зависимости от результатов тестов) можно поставить счетчик и возвращать 1 в случае, если он больше 0 уже после чистки.

Второй вариант — если нужно сразу прерывать скрипт при провале. Напишем небольшую проверочную функцию и будем запускать её после важных скриптов (так можно дополнительно кастомизировать сообщение). Получится что-то вроде обработчика исключений.

Чтобы её применить нужно указать `check $? ‘exception text’` после исполняемой команды. Первым аргументом вы передаете код завершения предыдущего процесса, а вторым ваш текст ошибки. Важно, что мы выходим с тем же кодом ошибки, который был передан от последнего проверяемого процесса. Отредактируем наш скрипт:

На этом все, надеюсь вы так же оцените удобство работы с командной строкой и этот инструмент вам поможет перейти на новый уровень)

Источник

Оцените статью
Adblock
detector