DevOps и серверы
Коды ошибок и сигналы Unix
errno, сигналы и коды выхода в одном месте — с правилом «128 плюс номер», из-за которого 137 означает нехватку памяти.
Разбор кода
Что означает число
Код выхода
Убит SIGKILL
128 + 9. В Docker и Kubernetes это почти всегда OOM-killer: контейнеру не хватило памяти.
Одно и то же число значит разное в разных местах, поэтому показаны все подходящие трактовки.
Показано 66 из 66 строк.
Коды выхода
В оболочке код последней команды лежит в $?. Всё, что больше 128, — почти всегда сигнал.
0
Успех. Единственный код, который в скриптах означает «всё хорошо».
1
Общая ошибка. Универсальный «что-то пошло не так». Большинство программ ограничивается им.
2
Неверное использование. У встроенных команд оболочки — синтаксическая ошибка или неверный ключ.
126
Команда не исполняема. Файл есть, но нет бита x, либо это каталог.
127
Команда не найдена. Нет в PATH. В контейнерах ещё и «нет sh в образе» либо не тот шебанг.
128
Неверный аргумент exit. exit с числом вне диапазона 0–255.
130
Прервано с Ctrl-C. 128 + 2 (SIGINT).
137
Убит SIGKILL. 128 + 9. В Docker и Kubernetes это почти всегда OOM-killer: контейнеру не хватило памяти.
139
Обращение к чужой памяти. 128 + 11 (SIGSEGV).
141
Обрыв канала. 128 + 13 (SIGPIPE). Типично для «cmd | head».
143
Завершён SIGTERM. 128 + 15. Штатная остановка: docker stop, systemctl stop, вытеснение пода.
255
Код вне диапазона. Часто это exit(-1): в 8 бит он превращается в 255. У ssh — ошибка самого ssh.
Сигналы
Значения приведены для Linux x86-64: на других архитектурах номера части сигналов отличаются.
SIGHUP (1)
Обрыв терминала. Демоны используют его как «перечитай конфиг». Чтобы процесс пережил выход из ssh — nohup или systemd-unit.
SIGINT (2)
Прерывание с клавиатуры (Ctrl-C). Программа может перехватить и завершиться аккуратно.
SIGQUIT (3)
Выход с дампом (Ctrl-\). У JVM и Go печатает стеки всех потоков — удобно при зависании.
SIGILL (4)
Недопустимая инструкция. Бинарник собран под другой процессор.
SIGABRT (6)
Аварийное завершение. Программа сама вызвала abort(): проваленный assert, необработанное исключение в C++.
SIGFPE (8)
Ошибка арифметики. Деление на ноль в целых числах.
SIGKILL (9)
Немедленное убийство. Перехватить нельзя. В контейнерах чаще всего приходит от OOM-killer или как «время вышло» после SIGTERM.
SIGSEGV (11)
Обращение к чужой памяти. Разыменование нулевого указателя, переполнение стека при бесконечной рекурсии.
SIGPIPE (13)
Запись в закрытый канал. Именно поэтому «cmd | head» иногда завершается кодом 141.
SIGALRM (14)
Сигнал таймера.
SIGTERM (15)
Вежливая просьба завершиться. Сигнал по умолчанию у kill, docker stop и systemctl stop. Приложение должно закрыть соединения и выйти.
SIGCHLD (17)
Дочерний процесс завершился. Игнорируется по умолчанию; необработанный — источник зомби-процессов.
SIGCONT (18)
Продолжить выполнение. Пара к SIGSTOP; в оболочке это fg и bg.
SIGSTOP (19)
Приостановить процесс. Перехватить нельзя, как и SIGKILL.
SIGTSTP (20)
Приостановка с клавиатуры (Ctrl-Z).
SIGXCPU (24)
Превышен лимит процессорного времени. ulimit -t.
SIGXFSZ (25)
Превышен предел размера файла. ulimit -f.
SIGSYS (31)
Недопустимый системный вызов. Часто это seccomp-фильтр в контейнере.
errno
Номер errno — это не код выхода: программа обычно превращает его в сообщение и выходит с 1.
EPERM (1)
Операция не разрешена. Прав не хватает, но дело не в правах файла: обычно нужен root или соответствующая capability.
ENOENT (2)
Нет такого файла или каталога. Самая частая ошибка вообще. Проверьте не только файл, но и каждый каталог пути и битые симлинки.
ESRCH (3)
Нет такого процесса. PID уже завершился.
EINTR (4)
Вызов прерван сигналом. Не ошибка: вызов надо повторить. В коде это забывают и получают случайные сбои.
EIO (5)
Ошибка ввода-вывода. Часто физическая: диск, шлейф, сеть у сетевой ФС. Смотрите dmesg.
E2BIG (7)
Слишком длинный список аргументов. Классика: rm * в каталоге с сотней тысяч файлов. Спасает find … -delete или xargs.
ENOEXEC (8)
Ошибка формата исполняемого файла. Не тот формат или архитектура; иногда — отсутствующий шебанг.
EBADF (9)
Неверный файловый дескриптор. Работа с уже закрытым файлом или сокетом.
EAGAIN / EWOULDBLOCK (11)
Ресурс временно недоступен. Неблокирующая операция не готова — повторить позже. Иногда упирается в лимит потоков.
ENOMEM (12)
Не хватает памяти. Кончилась память или сработал лимит cgroup/ulimit.
EACCES (13)
Доступ запрещён. Именно права: биты доступа, владелец, ACL, SELinux. У каталога нужен ещё и бит x.
EBUSY (16)
Устройство или ресурс занят. Размонтировать не даёт открытый файл — ищите через lsof.
EEXIST (17)
Файл уже существует. Создание с O_EXCL или mkdir по существующему пути.
EXDEV (18)
Ссылка через устройство. rename между разными файловыми системами не работает — нужно копирование.
ENOTDIR (20)
Не каталог. В середине пути оказался обычный файл.
EISDIR (21)
Это каталог. Попытка открыть каталог на запись как файл.
EINVAL (22)
Недопустимый аргумент. Самая бессодержательная ошибка: смотрите strace, чтобы увидеть, какой именно вызов и с чем.
ENFILE (23)
Переполнена системная таблица файлов. Лимит на всю систему: fs.file-max.
EMFILE (24)
Слишком много открытых файлов. Лимит процесса: ulimit -n или LimitNOFILE в unit-файле. Часто это утечка дескрипторов.
EFBIG (27)
Файл слишком велик. Предел файловой системы или ulimit -f.
ENOSPC (28)
На устройстве не осталось места. Проверьте не только df -h, но и df -i: свободные inode кончаются раньше места.
EROFS (30)
Файловая система только для чтения. Ядро перевело ФС в read-only после ошибки диска — типичный симптом умирающего накопителя.
EMLINK (31)
Слишком много ссылок. Предел числа жёстких ссылок на файл.
EPIPE (32)
Обрыв канала. Пишем в закрытый сокет или в конвейер, чей читатель уже вышел (head закрывает поток).
ENAMETOOLONG (36)
Слишком длинное имя файла. Обычно 255 байт на компонент; кириллица занимает по два байта на символ.
ENOTEMPTY (39)
Каталог не пуст. rmdir работает только с пустым каталогом.
ELOOP (40)
Слишком много уровней символических ссылок. Симлинк ссылается сам на себя по кругу.
ETIME (62)
Истекло время таймера.
EADDRINUSE (98)
Адрес уже используется. Порт занят. Найти виновника: ss -tulpn или lsof -i :порт. После падения помогает SO_REUSEADDR.
EADDRNOTAVAIL (99)
Невозможно назначить адрес. Пытаетесь слушать IP, которого нет на интерфейсах.
ENETUNREACH (101)
Сеть недоступна. Нет маршрута: ip r.
ECONNRESET (104)
Соединение сброшено другой стороной. Собеседник закрыл сокет резко (RST). Часто это таймаут балансировщика или перезапуск бэкенда.
ETIMEDOUT (110)
Истекло время ожидания. Пакеты уходят в никуда — обычно файрвол молча их дропает.
ECONNREFUSED (111)
В соединении отказано. Порт закрыт: сервис не запущен или слушает только localhost.
EHOSTUNREACH (113)
Хост недоступен.
EDQUOT (122)
Превышена дисковая квота.