HTML Diff
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>В примере выше &amp;&amp; используется для обозначения "и", а || для обозначения "или". В данном случае команда выполняет скрипт ./tmp.sh, а затем выполняет echo "bam", если код завершения 0. Если код завершения 1, выполняется следующая команда в круглых скобках. Как видно, в скобках для группировки команд снова используются &amp;&amp; и ||.</p>
36 <p>В примере выше &amp;&amp; используется для обозначения "и", а || для обозначения "или". В данном случае команда выполняет скрипт ./tmp.sh, а затем выполняет echo "bam", если код завершения 0. Если код завершения 1, выполняется следующая команда в круглых скобках. Как видно, в скобках для группировки команд снова используются &amp;&amp; и ||.</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>