0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Инструменты автоматизации и мониторинга удобны тем, что разработчик может взять готовые скрипты, при необходимости адаптировать и использовать в своём проекте. Можно заметить, что в некоторых скриптах используются коды завершения (exit codes), а в других нет. О коде завершения легко забыть, но это очень полезный инструмент. Особенно важно использовать его в скриптах командной строки.</p>
1
<p>Инструменты автоматизации и мониторинга удобны тем, что разработчик может взять готовые скрипты, при необходимости адаптировать и использовать в своём проекте. Можно заметить, что в некоторых скриптах используются коды завершения (exit codes), а в других нет. О коде завершения легко забыть, но это очень полезный инструмент. Особенно важно использовать его в скриптах командной строки.</p>
2
<h2>Содержание</h2>
2
<h2>Содержание</h2>
3
<ul><li><a>Что такое коды завершения</a></li>
3
<ul><li><a>Что такое коды завершения</a></li>
4
<li><a>Что происходит, когда коды завершения не определены</a></li>
4
<li><a>Что происходит, когда коды завершения не определены</a></li>
5
<li><a>Как использовать коды завершения в Bash-скриптах</a></li>
5
<li><a>Как использовать коды завершения в Bash-скриптах</a></li>
6
<li><a>Как использовать коды завершения в командной строке</a></li>
6
<li><a>Как использовать коды завершения в командной строке</a></li>
7
<li><a>Дополнительные коды завершения</a></li>
7
<li><a>Дополнительные коды завершения</a></li>
8
</ul><h2>Что такое коды завершения</h2>
8
</ul><h2>Что такое коды завершения</h2>
9
<p>В Linux и других Unix-подобных операционных системах программы во время завершения могут передавать значение родительскому процессу. Это значение называется кодом завершения или состоянием завершения. В POSIX по соглашению действует стандарт: программа передаёт 0 при успешном исполнении и 1 или большее число при неудачном исполнении.</p>
9
<p>В Linux и других Unix-подобных операционных системах программы во время завершения могут передавать значение родительскому процессу. Это значение называется кодом завершения или состоянием завершения. В POSIX по соглашению действует стандарт: программа передаёт 0 при успешном исполнении и 1 или большее число при неудачном исполнении.</p>
10
<p>Почему это важно? Если смотреть на коды завершения в контексте скриптов для командной строки, ответ очевиден. Любой полезный Bash-скрипт неизбежно будет использоваться в других скриптах или его обернут в однострочник Bash. Это особенно актуально при использовании инструментов автоматизации типа SaltStack или инструментов мониторинга типа Nagios. Эти программы исполняют скрипт и проверяют статус завершения, чтобы определить, было ли исполнение успешным.</p>
10
<p>Почему это важно? Если смотреть на коды завершения в контексте скриптов для командной строки, ответ очевиден. Любой полезный Bash-скрипт неизбежно будет использоваться в других скриптах или его обернут в однострочник Bash. Это особенно актуально при использовании инструментов автоматизации типа SaltStack или инструментов мониторинга типа Nagios. Эти программы исполняют скрипт и проверяют статус завершения, чтобы определить, было ли исполнение успешным.</p>
11
<p>Кроме того, даже если вы не определяете коды завершения, они всё равно есть в ваших скриптах. Но без корректного определения кодов выхода можно столкнуться с проблемами: ложными сообщениями об успешном исполнении, которые могут повлиять на работу скрипта.</p>
11
<p>Кроме того, даже если вы не определяете коды завершения, они всё равно есть в ваших скриптах. Но без корректного определения кодов выхода можно столкнуться с проблемами: ложными сообщениями об успешном исполнении, которые могут повлиять на работу скрипта.</p>
12
<h2>Что происходит, когда коды завершения не определены</h2>
12
<h2>Что происходит, когда коды завершения не определены</h2>
13
<p>В Linux любой код, запущенный в командной строке, имеет код завершения. Если код завершения не определён, Bash-скрипты используют код выхода последней запущенной команды. Чтобы лучше понять суть, обратите внимание на пример.</p>
13
<p>В Linux любой код, запущенный в командной строке, имеет код завершения. Если код завершения не определён, Bash-скрипты используют код выхода последней запущенной команды. Чтобы лучше понять суть, обратите внимание на пример.</p>
14
<p>Этот скрипт запускает команды touch и echo. Если запустить этот скрипт без прав суперпользователя, команда touch не выполнится. В этот момент мы хотели бы получить информацию об ошибке с помощью соответствующего кода завершения. Чтобы проверить код выхода, достаточно ввести в командную строку специальную переменную $?. Она печатает код возврата последней запущенной команды.</p>
14
<p>Этот скрипт запускает команды touch и echo. Если запустить этот скрипт без прав суперпользователя, команда touch не выполнится. В этот момент мы хотели бы получить информацию об ошибке с помощью соответствующего кода завершения. Чтобы проверить код выхода, достаточно ввести в командную строку специальную переменную $?. Она печатает код возврата последней запущенной команды.</p>
15
<p>Как видно, после запуска команды ./tmp.sh получаем код завершения 0. Этот код говорит об успешном выполнении команды, хотя на самом деле команда не выполнилась. Скрипт из примера выше исполняет две команды: touch и echo. Поскольку код завершения не определён, получаем код выхода последней запущенной команды. Это команда echo, которая успешно выполнилась.</p>
15
<p>Как видно, после запуска команды ./tmp.sh получаем код завершения 0. Этот код говорит об успешном выполнении команды, хотя на самом деле команда не выполнилась. Скрипт из примера выше исполняет две команды: touch и echo. Поскольку код завершения не определён, получаем код выхода последней запущенной команды. Это команда echo, которая успешно выполнилась.</p>
16
<p>Скрипт:</p>
16
<p>Скрипт:</p>
17
<p>Если убрать из скрипта команду echo, можно получить код завершения команды touch.</p>
17
<p>Если убрать из скрипта команду echo, можно получить код завершения команды touch.</p>
18
<p>Поскольку touch в данном случае - последняя запущенная команда, и она не выполнилась, получаем код возврата 1.</p>
18
<p>Поскольку touch в данном случае - последняя запущенная команда, и она не выполнилась, получаем код возврата 1.</p>
19
<h2>Как использовать коды завершения в Bash-скриптах</h2>
19
<h2>Как использовать коды завершения в Bash-скриптах</h2>
20
<p>Удаление из скрипта команды echo позволило нам получить код завершения. Что делать, если нужно сделать разные действия в случае успешного и неуспешного выполнения команды touch? Речь идёт о печати stdout в случае успеха и stderr в случае неуспеха.</p>
20
<p>Удаление из скрипта команды echo позволило нам получить код завершения. Что делать, если нужно сделать разные действия в случае успешного и неуспешного выполнения команды touch? Речь идёт о печати stdout в случае успеха и stderr в случае неуспеха.</p>
21
<h3>Проверяем коды завершения</h3>
21
<h3>Проверяем коды завершения</h3>
22
<p>Выше мы пользовались специальной переменной $?, чтобы получить код завершения скрипта. Также с помощью этой переменной можно проверить, выполнилась ли команда touch успешно.</p>
22
<p>Выше мы пользовались специальной переменной $?, чтобы получить код завершения скрипта. Также с помощью этой переменной можно проверить, выполнилась ли команда touch успешно.</p>
23
<p>После рефакторинга скрипта получаем такое поведение:</p>
23
<p>После рефакторинга скрипта получаем такое поведение:</p>
24
<ul><li>Если команда touch выполняется с кодом 0, скрипт с помощью echo сообщает об успешно созданном файле.</li>
24
<ul><li>Если команда touch выполняется с кодом 0, скрипт с помощью echo сообщает об успешно созданном файле.</li>
25
<li>Если команда touch выполняется с другим кодом, скрипт сообщает, что не смог создать файл.</li>
25
<li>Если команда touch выполняется с другим кодом, скрипт сообщает, что не смог создать файл.</li>
26
</ul><p>Любой код завершения кроме 0 значит неудачную попытку создать файл. Скрипт с помощью echo отправляет сообщение о неудаче в stderr.</p>
26
</ul><p>Любой код завершения кроме 0 значит неудачную попытку создать файл. Скрипт с помощью echo отправляет сообщение о неудаче в stderr.</p>
27
<p>Выполнение:</p>
27
<p>Выполнение:</p>
28
<h3>Создаём собственный код завершения</h3>
28
<h3>Создаём собственный код завершения</h3>
29
<p>Наш скрипт уже сообщает об ошибке, если команда touch выполняется с ошибкой. Но в случае успешного выполнения команды мы всё также получаем код 0.</p>
29
<p>Наш скрипт уже сообщает об ошибке, если команда touch выполняется с ошибкой. Но в случае успешного выполнения команды мы всё также получаем код 0.</p>
30
<p>Поскольку скрипт завершился с ошибкой, было бы не очень хорошей идеей передавать код успешного завершения в другую программу, которая использует этот скрипт. Чтобы добавить собственный код завершения, можно воспользоваться командой exit.</p>
30
<p>Поскольку скрипт завершился с ошибкой, было бы не очень хорошей идеей передавать код успешного завершения в другую программу, которая использует этот скрипт. Чтобы добавить собственный код завершения, можно воспользоваться командой exit.</p>
31
<p>Теперь в случае успешного выполнения команды touch скрипт с помощью echo сообщает об успехе и завершается с кодом 0. В противном случае скрипт печатает сообщение об ошибке при попытке создать файл и завершается с кодом 1.</p>
31
<p>Теперь в случае успешного выполнения команды touch скрипт с помощью echo сообщает об успехе и завершается с кодом 0. В противном случае скрипт печатает сообщение об ошибке при попытке создать файл и завершается с кодом 1.</p>
32
<p>Выполнение:</p>
32
<p>Выполнение:</p>
33
<h2>Как использовать коды завершения в командной строке</h2>
33
<h2>Как использовать коды завершения в командной строке</h2>
34
<p>Скрипт уже умеет сообщать пользователям и программам об успешном или неуспешном выполнении. Теперь его можно использовать с другими инструментами администрирования или однострочниками командной строки.</p>
34
<p>Скрипт уже умеет сообщать пользователям и программам об успешном или неуспешном выполнении. Теперь его можно использовать с другими инструментами администрирования или однострочниками командной строки.</p>
35
<p>Bash-однострочник:</p>
35
<p>Bash-однострочник:</p>
36
<p>В примере выше && используется для обозначения "и", а || для обозначения "или". В данном случае команда выполняет скрипт ./tmp.sh, а затем выполняет echo "bam", если код завершения 0. Если код завершения 1, выполняется следующая команда в круглых скобках. Как видно, в скобках для группировки команд снова используются && и ||.</p>
36
<p>В примере выше && используется для обозначения "и", а || для обозначения "или". В данном случае команда выполняет скрипт ./tmp.sh, а затем выполняет echo "bam", если код завершения 0. Если код завершения 1, выполняется следующая команда в круглых скобках. Как видно, в скобках для группировки команд снова используются && и ||.</p>
37
<p>Скрипт использует коды завершения, чтобы понять, была ли команда успешно выполнена. Если коды завершения используются некорректно, пользователь скрипта может получить неожиданные результаты при неудачном выполнении команды.</p>
37
<p>Скрипт использует коды завершения, чтобы понять, была ли команда успешно выполнена. Если коды завершения используются некорректно, пользователь скрипта может получить неожиданные результаты при неудачном выполнении команды.</p>
38
<h2>Дополнительные коды завершения</h2>
38
<h2>Дополнительные коды завершения</h2>
39
<p>Команда exit принимает числа от 0 до 255. В большинстве случаев можно обойтись кодами 0 и 1. Однако есть зарезервированные коды, которые обозначают конкретные ошибки. Список зарезервированных кодов можно<a>посмотреть в документации</a>.</p>
39
<p>Команда exit принимает числа от 0 до 255. В большинстве случаев можно обойтись кодами 0 и 1. Однако есть зарезервированные коды, которые обозначают конкретные ошибки. Список зарезервированных кодов можно<a>посмотреть в документации</a>.</p>
40
<p>Адаптированный перевод статьи<a>Understanding Exit Codes and how to use them in bash scripts</a>by Benjamin Cane. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.</p>
40
<p>Адаптированный перевод статьи<a>Understanding Exit Codes and how to use them in bash scripts</a>by Benjamin Cane. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.</p>