Коды возврата и обработка ошибок команд
Учимся понимать, успешно ли отработала команда, и реагировать на сбои.
Код возврата (exit code) — это число от 0 до 255, которое команда оставляет после себя:
0означает успех, любое другое — конкретную ошибку.
Переменная $? хранит результат
Сразу после команды её код возврата лежит в специальной переменной $?.
ls /etc > /dev/null
echo "Код: $?"
ls /not-exist 2> /dev/null
echo "Код: $?"Вывод:
Код: 0 Код: 2
Первая команда успешна (0), вторая не нашла путь и вернула 2. Каждая программа сама определяет, какие коды что значат, но 0 всегда успех.
exit завершает скрипт с кодом
Скрипт тоже возвращает код — через exit N. По нему вызывающая система (например, CI или cron) понимает, всё ли хорошо.
#!/usr/bin/env bash
if [ ! -f "$1" ]; then
echo "Файл не найден" >&2
exit 1
fi
echo "Файл на месте"
exit 0Обратите внимание на >&2 — сообщение об ошибке мы отправляем в stderr, как и положено.
Цепочки && и ||
Операторы && и || выполняют следующую команду в зависимости от успеха предыдущей.
| Запись | Когда выполнится вторая команда |
A && B | если A успешна (код 0) |
A || B | если A неуспешна (код не 0) |
mkdir -p /tmp/build && echo "папка готова"
cd /no-such-dir || echo "не смог перейти"Вывод:
папка готова не смог перейти
Это компактный способ написать «сделай Б, только если А удалась» или «иначе предупреди».
Как работает под капотом
Когда процесс завершается, операционная система сохраняет его код выхода, и Bash кладёт его в $?. Конвейер A | B по умолчанию возвращает код только последней команды (B) — об этом важно помнить при обработке ошибок. Операторы && и || используют «ленивое» вычисление: A && B не запустит B, если A уже провалилась, потому что результат и так известен.
Частые ошибки
- Проверять $? слишком поздно.
$?хранит код ПОСЛЕДНЕЙ команды; дажеechoмежду проверкой и командой перезапишет его. Проверяйте сразу. - Возвращать exit 0 при ошибке. Тогда CI или cron решат, что всё хорошо. Возвращайте ненулевой код при сбое.
- Путать && и ||.
&&— «при успехе»,||— «при неудаче».
Итог
- Код возврата:
0— успех, иначе — ошибка; он лежит в$?сразу после команды. exit Nзавершает скрипт с кодом, по которому судят об успехе извне.A && Bзапускает B при успехе A,A || B— при неудаче A.