Кодов: 208 из 208
Операция требует привилегий, которых у процесса нет: например, сменить владельца файла, отправить сигнал процессу другого пользователя или изменить неизменяемый файл (chattr +i). В отличие от EACCES, это не решается изменением прав на файл: нужен root или соответствующая capability.
Файл или каталог не существует. Ошибка также возникает, когда в пути отсутствует промежуточный каталог, когда символическая ссылка указывает на несуществующую цель или когда не установлен интерпретатор из строки #! скрипта.
Не существует процесса, группы процессов или потока с таким идентификатором; например, при выполнении kill для PID, который уже завершился.
Сигнал прервал системный вызов до его завершения. Это не настоящая ошибка: программа должна повторить вызов или установить обработчик сигнала с SA_RESTART.
Низкоуровневая ошибка ввода-вывода, как правило при чтении с устройства или записи на него. На дисках обычно указывает на повреждённые секторы или неисправный кабель: проверьте dmesg и состояние SMART. Также возникает при записи в уже закрытый терминал.
Устройство или адрес не существует: файл устройства есть, но за ним нет оборудования, либо FIFO открыт на запись с O_NONBLOCK, когда нет ни одного читателя.
Список аргументов и переменных окружения, передаваемый в exec, слишком велик. Это классическое «Argument list too long» при использовании шаблона, который раскрывается в тысячи файлов; используйте find -exec или xargs.
Файл не имеет распознаваемого исполняемого формата: это бинарный файл для другой архитектуры, он повреждён или это скрипт без строки #!.
Файловый дескриптор недействителен, уже закрыт или открыт в режиме, который не допускает операцию, например запись в дескриптор, открытый только для чтения.
У процесса нет дочерних процессов, которые можно ожидать через wait или waitpid; часто потому, что SIGCHLD игнорируется и дочерние процессы убираются автоматически.
Ресурс временно недоступен, и стоит повторить попытку. В неблокирующих операциях это значит, что данных или места пока нет; в fork — что достигнут лимит процессов или потоков (ulimit -u или pids.max в cgroup).
То же значение:EWOULDBLOCK
Недостаточно памяти для операции или превышен лимит памяти процесса. В fork или mmap причиной может быть политика overcommit, лимит cgroup или нехватка адресного пространства.
Доступ запрещён правами на файл или на один из каталогов пути (на каждый нужно право на выполнение), ACL, SELinux или AppArmor либо монтированием с noexec. bind также возвращает эту ошибку при использовании порта ниже 1024 без привилегий.
В системный вызов передан указатель на недопустимый адрес памяти. Это указывает на ошибку в программе.
Операции нужно блочное устройство, например диск, а получен файл другого типа; например, при монтировании обычного файла без -o loop.
Устройство или ресурс занят. Типично при размонтировании файловой системы, в которой есть открытые файлы или находится терминал; lsof или fuser показывают, какие процессы её используют.
Файл, каталог или другой объект с таким именем уже существует, например при создании с O_EXCL, при использовании mkdir без -p или при создании ссылки по уже существующему пути.
Нельзя создать жёсткую ссылку или переименовать файл между разными файловыми системами. mv решает это копированием и удалением; программы, использующие rename(), должны поступать так же.
Устройство не существует или не поддерживает операцию; например, при монтировании файловой системы, модуль ядра которой не загружен.
Компонент пути, который должен быть каталогом, является файлом, или был запрошен каталог (O_DIRECTORY), а объект им не является.
Попытка выполнить файловую операцию над каталогом, например открыть его на запись.
Аргумент недопустим для вызова: значение вне диапазона, несовместимое сочетание флагов или операция, которую объект не поддерживает. Ошибка общая: конкретные случаи перечислены на man-странице вызова.
Исчерпана общесистемная таблица открытых файлов. Лимит настраивается параметром fs.file-max в sysctl.
Процесс достиг своего лимита открытых дескрипторов («Too many open files»). Увеличьте лимит через ulimit -n или LimitNOFILE в systemd и проверьте, не оставляет ли программа незакрытые файлы или сокеты.
Запрошена терминальная операция (ioctl) над тем, что не является терминалом, например когда вывод интерактивной программы перенаправлен в файл или в канал.
Исполняемый файл занят: нельзя записывать в бинарный файл, пока он выполняется, или запускать файл, который всё ещё открыт на запись. Чтобы обновить его, лучше записать новый файл и переименовать его.
Файл превышает максимальный размер, допустимый файловой системой (4 ГБ в FAT32), или лимит процесса RLIMIT_FSIZE.
На устройстве не осталось места. Если df показывает свободное место, проверьте inode с помощью df -i. inotify тоже возвращает эту ошибку при исчерпании fs.inotify.max_user_watches.
Нельзя выполнить lseek для канала, FIFO или сокета, потому что у них нет позиции.
Файловая система смонтирована только для чтения. Если она перешла в режим только для чтения, хотя никто этого не запрашивал, это сделало ядро, обнаружив ошибки: проверьте dmesg и запустите fsck.
Превышено максимальное число жёстких ссылок на файл или, в некоторых файловых системах, подкаталогов в каталоге.
Запись в канал или сокет, другой конец которого уже закрыт («Broken pipe»). Помимо ошибки, процесс получает SIGPIPE; это нормально, когда читающая сторона завершается раньше, как в cmd | head.
Аргумент математической функции вне её области определения, например квадратный корень из отрицательного числа.
Результат функции слишком велик или слишком мал для представления, или буфера не хватает для результата, как в getcwd с коротким буфером.
Предотвращена взаимоблокировка: запрошенная блокировка, например блокировка файла через fcntl или мьютекс с обнаружением ошибок, ожидала бы вечно.
То же значение:EDEADLOCK
Путь или один из его компонентов превышает максимальную длину: в Linux, как правило, 255 байт на имя и 4096 на путь.
Нет доступных блокировок. В NFS обычно означает, что служба блокировок (lockd или rpc.statd) не работает.
Системный вызов не существует в этом ядре или не реализован. Типично для бинарных файлов, собранных для более нового ядра, или для профилей seccomp в контейнерах, которые не знают о новых вызовах.
Каталог не пуст, например при использовании rmdir или при переименовании поверх существующего каталога. Чтобы удалить его вместе с содержимым, используйте rm -r.
При разрешении пути встретилось слишком много символических ссылок подряд, обычно из-за цикла, или O_NOFOLLOW был использован для символической ссылки.
В очереди сообщений System V нет сообщения запрошенного типа.
Идентификатор IPC System V (очередь, семафор или разделяемая память) был удалён, пока процесс его использовал.
Номер канала вне диапазона. Это унаследованный код, практически не используемый в Linux.
Уровень 2 не синхронизирован. Это унаследованный код System V, практически не используемый в Linux.
Уровень 3 остановлен. Это унаследованный код System V, практически не используемый в Linux.
Уровень 3 сброшен. Это унаследованный код System V, практически не используемый в Linux.
Номер ссылки вне диапазона. Это унаследованный код, практически не используемый в Linux.
Драйвер протокола не подключён. Его используют немногие подсистемы, например некоторые драйверы Bluetooth.
Нет доступной структуры CSI. Это унаследованный код, практически не используемый в Linux.
Уровень 2 остановлен. Это унаследованный код System V, практически не используемый в Linux.
Недопустимый обмен. Это унаследованный код, который некоторые драйверы и файловые системы используют в собственном значении.
Недопустимый дескриптор запроса. Это унаследованный код, который некоторые драйверы используют в собственном значении.
Обмен заполнен. Это унаследованный код, практически не используемый в Linux.
Нет «anode». Это унаследованный код, практически не используемый в Linux.
Недопустимый код запроса. Код унаследованный; некоторые драйверы используют его для неподдерживаемых команд.
Недопустимый слот. Это унаследованный код, практически не используемый в Linux.
Неверный формат файла шрифта. Это унаследованный код, практически не используемый в Linux.
Устройство не является STREAM. Относится к интерфейсу STREAMS из System V, который Linux не реализует.
Нет доступных данных. В Linux его возвращает getxattr, когда расширенный атрибут не существует; в macOS этому случаю соответствует ENOATTR.
Истёк таймер. Пришёл из STREAMS; в Linux его используют некоторые драйверы и io_uring для операций с ограничением по времени.
Закончились ресурсы STREAMS — интерфейса, который Linux не реализует.
Машина не подключена к сети. Это редко используемый унаследованный код.
Пакет не установлен. Код унаследованный; некоторые подсистемы используют его, когда отсутствует модуль, например криптографический.
Объект является удалённым. В NFS обозначает путь, экспортируемый с другого сервера.
Связь разорвана. Код унаследованный; некоторые драйверы используют его при потере соединения с устройством.
Ошибка «advertise». Это унаследованный код RFS, не используемый в Linux.
Ошибка «srmount». Это унаследованный код RFS, не используемый в Linux.
Ошибка связи при отправке. Код унаследованный; его используют некоторые сетевые и USB-драйверы.
Ошибка протокола: другая сторона или устройство ответили что-то неожиданное. Встречается с USB-устройствами и в соединениях, которые обрываются посреди обмена.
Попытка многошагового перехода (multihop). Это унаследованный код RFS.
Ошибка, специфичная для RFS. В Linux не используется.
Сообщение имеет неверный формат или повреждено. ext4, XFS и Btrfs возвращают его под псевдонимом EFSBADCRC, когда не сходится контрольная сумма метаданных.
То же значение:EFSBADCRC
Значение не помещается в целевой тип данных; например, 32-битная программа, собранная без поддержки больших файлов, открывает файл больше 2 ГБ.
Имя не уникально в сети. Это унаследованный код.
Файловый дескриптор находится в неверном состоянии. Его используют ALSA и некоторые драйверы, когда устройство не готово.
Удалённый адрес изменился. Это унаследованный код.
Нет доступа к необходимой разделяемой библиотеке. Это унаследованный код бинарных файлов a.out.
Разделяемая библиотека повреждена. Это унаследованный код бинарных файлов a.out.
Секция .lib бинарного файла a.out повреждена. Это унаследованный код.
Попытка скомпоновать слишком много разделяемых библиотек. Это унаследованный код a.out.
Разделяемую библиотеку нельзя запустить напрямую. Это унаследованный код a.out.
Последовательность байтов недопустима для кодировки символов, например текст, который не является корректным UTF-8, при преобразовании через iconv или многобайтовые функции.
Прерванный вызов нужно перезапустить. Используется внутри ядра и не должен доходить до программ.
Ошибка канала STREAMS. ALSA возвращает его, когда звуковое устройство приостановлено.
Слишком много пользователей. Его возвращает система дисковых квот, когда её таблица заполнена; встречается редко.
Операция с сокетом применена к дескриптору, который не является сокетом.
Не указан адрес назначения: данные отправлены через сокет без соединения без указания, куда.
Сообщение слишком велико для сокета, например UDP-датаграмма больше максимума или больше MTU, когда фрагментация запрещена.
Протокол не соответствует типу сокета.
Запрошенный параметр сокета или протокол недоступен, например параметр setsockopt, неизвестный ядру.
Протокол не поддерживается, например потому, что его модуль ядра не загружен.
Тип сокета не поддерживается в этом семействе адресов.
Операция не поддерживается сокетом или объектом. В Linux имеет то же значение, что и ENOTSUP, и многие файловые системы возвращают его для нереализованных функций, например fallocate или расширенных атрибутов.
Операция не поддерживается. В Linux имеет то же значение, что и EOPNOTSUPP (95); в macOS это разные коды.
Семейство протоколов не поддерживается.
Семейство адресов не поддерживается; типично при использовании IPv6 в системе или контейнере, где он отключён.
Адрес и порт уже используются: другой процесс слушает этот порт, или предыдущее соединение всё ещё находится в TIME_WAIT. Найдите процесс с помощью ss -ltnp или lsof -i :ПОРТ либо используйте SO_REUSEADDR.
Невозможно назначить запрошенный адрес: IP не принадлежит ни одному интерфейсу машины, или исчерпаны эфемерные порты для исходящих соединений.
Сетевой интерфейс отключён.
Сеть назначения недоступна, потому что к ней нет маршрута. Проверьте таблицу маршрутизации и шлюз; это также происходит при подключении по IPv6 без IPv6-связности.
Сеть сбросила соединение, например при сбое keepalive.
Соединение прервано на локальной стороне, например потому, что клиент закрыл его до того, как сервер принял его через accept.
Другая сторона резко разорвала соединение пакетом RST («Connection reset by peer»): удалённый процесс закрылся, брандмауэр или балансировщик разорвал неактивное соединение, или были отправлены данные, которых другая сторона не ожидала.
В ядре нет свободного буферного пространства для сетевой операции; обычно возникает при большом трафике или переполненных очередях сокетов.
Сокет уже подключён.
Сокет не подключён: попытка отправить или получить данные до подключения, или соединение уже закрыто. В FUSE-монтировании проявляется как «Transport endpoint is not connected», когда его процесс завершился; исправляется размонтированием через fusermount -u.
Нельзя отправлять данные после закрытия этого направления сокета вызовом shutdown.
Слишком много ссылок; в Linux — при передаче слишком большого числа вложенных дескрипторов через Unix-сокет.
Истекло время ожидания соединения, потому что узел назначения не ответил. Обычно причина — брандмауэр, молча отбрасывающий пакеты, выключенный хост или маршрут, который не доходит до цели.
Узел назначения отклонил соединение: машина отвечает, но на этом порту никто не слушает, или брандмауэр отвечает отказом. Убедитесь, что служба запущена и слушает на правильном интерфейсе, а не только на 127.0.0.1.
Хост назначения выключен.
Нет маршрута к хосту: он не отвечает на ARP в локальной сети, или маршрутизатор либо брандмауэр сообщает, что он недоступен.
С сокетом уже выполняется операция, например неблокирующий connect, который ещё не завершился.
Операция выполняется: неблокирующий connect начался и завершится позже. Это не ошибка; нужно дождаться завершения с помощью poll или select.
Идентификатор файла устарел: в NFS файл или каталог был удалён или заменён на сервере. Решается повторным открытием пути или перемонтированием.
Структура требует очистки: файловая система обнаружила повреждение (в ext4 и XFS — под псевдонимом EFSCORRUPTED). Размонтируйте её и запустите fsck или xfs_repair.
То же значение:EFSCORRUPTED
Не является именованным файлом XENIX. Это неиспользуемый унаследованный код.
Нет доступных семафоров XENIX. Это неиспользуемый унаследованный код.
Является именованным файлом XENIX. Это неиспользуемый унаследованный код.
Ошибка удалённого ввода-вывода, например от устройства I2C или удалённого диска, который не ответил.
Превышена дисковая квота пользователя или группы.
В устройстве нет носителя, например в приводе нет диска или кардридер пуст.
Неверный тип носителя.
Операция отменена, например асинхронный ввод-вывод или ожидание io_uring.
Нужного ключа нет в связке ключей ядра (keyring). Встречается в зашифрованных файловых системах, например fscrypt или eCryptfs, когда ключ не загружен.
Срок действия ключа истёк. PAM и Kerberos также используют этот код, когда истёк срок действия пароля или билета.
Ключ отозван.
Служба отклонила ключ.
Владелец робастного мьютекса завершился, не освободив его. Новый владелец должен привести защищаемое состояние в согласованный вид и вызвать pthread_mutex_consistent.
Состояние, защищаемое робастным мьютексом, невозможно восстановить, потому что предыдущий владелец завершился, а никто не пометил его как согласованное.
Операция невозможна, потому что радиомодуль Wi-Fi или Bluetooth заблокирован через RF-kill. Проверьте rfkill list, физический переключатель или клавишу режима полёта.
В странице памяти аппаратная ошибка, и ядро пометило её как отравленную.
Тип файла не подходит для операции. В macOS и BSD этот код существует давно; в Linux его добавили недавно.
Слишком много процессов. BSD определяет его для лимита процессов, хотя на практике fork возвращает EAGAIN.
Неверная структура RPC (Sun RPC, который использует NFS).
Версия RPC не совпадает (Sun RPC, который использует NFS).
Программа RPC недоступна на сервере.
Версия программы RPC не совпадает.
Процедура не существует в программе RPC.
Ошибка аутентификации, например при монтировании ресурса NFS.
Для операции нужен аутентификатор.
Устройство выключено.
Ошибка устройства, например в принтере закончилась бумага.
Исполняемый файл недействителен.
Исполняемый файл предназначен для другого типа процессора, например бинарный файл только для x86_64 на Mac с Apple Silicon без Rosetta 2 или файл для ARM на Mac с Intel.
Версия разделяемой библиотеки не совпадает.
Файл Mach-O имеет неверный формат или повреждён.
Расширенный атрибут не существует; соответствует ENODATA в Linux. Встречается с xattr, например при удалении com.apple.quarantine у файла, у которого его нет.
В MAC Framework нет политики, зарегистрированной под этим именем.
Выходная очередь сетевого интерфейса заполнена.
Недостаточно возможностей: этот код возвращают вызовы, ограниченные песочницей.
Управляющий терминал процесса закрылся или оборвался SSH-сеанс. Многие демоны, например nginx, sshd или rsyslog, воспринимают этот сигнал как команду перечитать конфигурацию; nohup, tmux и screen не дают ему завершить процессы при выходе.
Прерывание с клавиатуры по Ctrl+C. Программа может перехватить его, чтобы корректно завершиться. Код завершения 130.
Выход с клавиатуры по Ctrl+\. Завершает процесс с дампом памяти; JVM же использует его для вывода состояния потоков.
Процессор встретил недопустимую инструкцию: бинарный файл, собранный для более нового процессора (например, с AVX2 или AVX-512 на процессоре, где их нет), повреждённый код или переход на данные.
Ловушка отладки: её используют отладчики для точек останова. Если сигнал приходит без отладчика, обычно это сбой, обнаруженный самой программой, например проверки Swift в macOS.
Процесс вызвал abort(): не выполнилось утверждение (assert), не было перехвачено исключение C++ или библиотека C обнаружила повреждение кучи («double free or corruption»). Код завершения 134.
То же значение:SIGIOT
Ошибка шины: обращение к невыровненной памяти на некоторых архитектурах или к части отображённого через mmap файла, которой больше нет, потому что файл был усечён. Также возникает при заполнении /dev/shm.
Арифметическое исключение. Несмотря на название, чаще всего причина — целочисленное деление на ноль.
Немедленно завершает процесс: его нельзя перехватить, заблокировать или игнорировать. Его отправляют kill -9, OOM killer ядра при нехватке памяти, а также Docker или Kubernetes, когда контейнер превышает свой лимит памяти (OOMKilled) или не завершается вовремя после SIGTERM. Код завершения 137.
Свободный сигнал, который каждое приложение использует по-своему; например, dd выводит свой прогресс, а nginx заново открывает логи.
Нарушение сегментации («Segmentation fault»): обращение к недопустимой памяти, например разыменование нулевого указателя, выход за границы массива или переполнение стека из-за бесконечной рекурсии. Код завершения 139.
Второй свободный сигнал, который каждое приложение использует по-своему.
Запись в канал или сокет без читателя. Это нормально в cmd | head, где читающая сторона завершается раньше; серверы обычно игнорируют этот сигнал и обрабатывают ошибку EPIPE. Код завершения 141.
Истёк таймер, установленный с помощью alarm или setitimer.
Запрос на корректное завершение. Это сигнал по умолчанию для kill, systemctl stop, docker stop и Kubernetes при удалении пода; процесс должен закрыть свои соединения и завершиться. Код завершения 143.
Ошибка стека сопроцессора. В современном Linux не используется.
Дочерний процесс завершился, остановился или продолжил работу. Родитель должен забрать его через wait; иначе дочерний процесс остаётся зомби.
То же значение:SIGCLD
Возобновляет остановленный процесс, как это делают fg и bg в оболочке.
Останавливает процесс; его нельзя перехватить или игнорировать. Процесс возобновляется сигналом SIGCONT.
Остановка с терминала по Ctrl+Z. В отличие от SIGSTOP, программа может его перехватить.
Фоновый процесс попытался читать с терминала.
Фоновый процесс попытался писать в терминал при включённом stty tostop или изменить его настройки.
На сокет поступили срочные (внеполосные) данные. Go использует этот сигнал внутри для прерывания горутин.
Превышен лимит процессорного времени процесса (ulimit -t).
Превышен максимальный размер файла, разрешённый процессу (ulimit -f).
Истёк виртуальный таймер, который учитывает только процессорное время процесса.
Истёк таймер профилирования, который используют профилировщики.
Изменился размер окна терминала; полноэкранные программы используют этот сигнал, чтобы перерисоваться.
На дескрипторе, настроенном с O_ASYNC, доступен ввод-вывод. В Linux SIGPOLL — тот же сигнал.
То же значение:SIGPOLL
Сбой питания, о котором программное обеспечение ИБП сообщает системе init.
Неверный системный вызов. Сегодня обычная причина — фильтр seccomp, который его блокирует, как в контейнерах.
Ловушка эмуляции (EMT). Существует в macOS и BSD, но не в Linux на x86 и ARM.
Запрос информации по Ctrl+T в терминале macOS и BSD; многие команды в ответ показывают свой прогресс.
Команда завершилась успешно. Это единственный код, означающий успех: любое другое значение указывает на ошибку.
Общая ошибка; что она означает, решает каждая программа. Подробности обычно в том, что команда вывела в stderr. grep и diff используют его в другом смысле: «совпадений не найдено» или «файлы различаются».
Неправильное использование встроенной команды оболочки или синтаксическая ошибка в скрипте. Многие программы также используют его для недопустимых параметров, а grep — для настоящих ошибок.
Команда использована неправильно: не хватает аргументов, есть лишние или какой-то параметр неверен.
Входные данные имеют неверный формат.
Входной файл не существует или не может быть прочитан.
Указанный пользователь не существует; используется в основном почтовыми программами.
Имя хоста не существует.
Необходимая служба недоступна, или произошёл сбой, который не подходит под другие категории.
Внутренняя ошибка программы.
Ошибка операционной системы, например невозможно выполнить fork или создать канал.
Отсутствует системный файл, например /etc/passwd, или в нём есть ошибка.
Невозможно создать выходной файл.
Ошибка ввода-вывода при чтении или записи файла.
Временный сбой: стоит повторить попытку позже. Почтовые серверы используют его, чтобы оставить сообщение в очереди.
Удалённая система ответила что-то, что не соответствует протоколу.
Недостаточно прав для операции.
Ошибка в конфигурации.
Команда timeout завершила процесс, потому что было превышено указанное время.
Сбой самого docker run до запуска контейнера, например из-за неверного параметра или ошибки демона. GNU timeout тоже возвращает этот код, когда сбой произошёл в нём самом.
Файл существует, но не может быть выполнен: у него нет права на выполнение, это каталог или бинарный файл для другой архитектуры. В Docker — команда контейнера не является исполняемой.
Команда не найдена: она не установлена, её нет в PATH или в имени опечатка. В скриптах также появляется, когда отсутствует интерпретатор из строки #!; в Docker — когда команды контейнера нет в образе.
Коды больше 128 означают, что процесс был завершён сигналом, но 128 не соответствует ни одному сигналу. Git использует его для всех своих фатальных ошибок («fatal: …»), например когда репозиторий не существует или не удалась аутентификация при клонировании.
Код завершения вышел за пределы диапазона: exit -1 приходит как 255, потому что сохраняются только 8 бит. ssh тоже возвращает его, когда не удаётся подключение или аутентификация, чтобы отличить это от кода удалённой команды.
Значения для Linux приведены для x86, x86-64 и ARM; на Alpha, MIPS, SPARC и PA-RISC некоторые errno и сигналы пронумерованы иначе. Сообщения на английском — это те, что выводят strerror и strsignal в glibc, а также в macOS, если они отличаются. Коды завершения больше 128 интерпретируются как 128 плюс номер сигнала — это соглашение bash, Docker и Kubernetes.
Как это работает
Когда системный вызов в Linux завершается неудачей, он возвращает -1 и записывает в переменную errno число, которое объясняет причину: 2 — это ENOENT, файл не существует; 13 — EACCES, доступ запрещён. strerror превращает это число в текст, который виден на экране, например «No such file or directory». Python показывает его как [Errno 13], Node.js — как code: 'ECONNREFUSED', а Go, Rust или Java — тем же текстом. Номера с 1 по 34 пришли из оригинального Unix и одинаковы во всех системах; следующие каждая система пронумеровала по-своему, поэтому ECONNREFUSED — это 111 в Linux и 61 в macOS. Имя переносимо, а номер — нет.
Сигналы — это уведомления, которые ядро или другой процесс отправляют процессу: SIGINT при нажатии Ctrl+C, SIGTERM, чтобы попросить его завершиться, SIGKILL, чтобы завершить его без вопросов, SIGSEGV при обращении к недопустимой памяти. У каждого есть действие по умолчанию, и почти все можно перехватить, чтобы сделать что-то другое. Когда сигнал убивает процесс, оболочка сообщает в качестве кода завершения 128 плюс номер сигнала: 137 — это SIGKILL (9), 139 — SIGSEGV (11), а 143 — SIGTERM (15). Docker и Kubernetes используют то же соглашение.
Код завершения — это число, которое программа оставляет при завершении: 0 означает успех, а любое другое значение — ошибку. Сохраняются только 8 бит, поэтому диапазон — от 0 до 255. Соглашений немного: 126 и 127 использует оболочка, когда не может выполнить или не находит команду, коды с 64 по 78 определены в sysexits.h из BSD, а остальные каждая программа выбирает сама, как grep, который возвращает 1, когда ничего не находит.
Примеры
Last State: Terminated · Reason: OOMKilled · Exit Code: 137137 = 128 + 9 · SIGKILLКонтейнер превысил свой лимит памяти, и ядро убило его сигналом SIGKILL. Нужно увеличить лимит в resources.limits.memory или выяснить, почему процесс потребляет столько памяти; перезапуск проблему не решит.Error: connect ECONNREFUSED 127.0.0.1:5432ECONNREFUSED · Linux 111 · macOS 61 · Connection refusedNode.js не смог подключиться к PostgreSQL, потому что на порту 5432 никто не слушает. Если приложение работает в контейнере, 127.0.0.1 — это сам контейнер, а не машина: нужно использовать имя сервиса базы данных.OSError: [Errno 48] Address already in useEADDRINUSE · Linux 98 · macOS 48Число 48 выдаёт, что программа работает в macOS: в Linux та же ошибка имеет номер 98. В обоих случаях порт уже занят другим процессом; lsof -i :ПОРТ покажет каким.Сценарии использования
- Понять ошибку приложения на Python, Node.js, Go или C, которое показывает только номер или имя errno.
- Выяснить по коду завершения, почему остановился контейнер Docker или перезапускается под Kubernetes.
- Перевести номер errno из macOS в правильное имя: начиная с 35, номера не совпадают с Linux.
- Расшифровать код завершения скрипта, задания cron или CI-задачи, которые завершились с ошибкой.
- Выбрать, какой сигнал отправить через kill, и узнать, что сделает процесс, если не перехватит его.
- Написать переносимую обработку ошибок, которая сравнивает по имени, а не по номеру.
Часто задаваемые вопросы
Что означает exit code 137?
Что процесс был завершён сигналом 9, SIGKILL (128 + 9). Чаще всего причина в памяти: контейнер превысил свой лимит, и Kubernetes сообщает об этом как OOMKilled, или OOM killer ядра выбрал этот процесс, что остаётся в dmesg как «Out of memory: Killed process». Это также происходит при docker kill или когда процесс не завершается в отведённое время после SIGTERM: 10 секунд в docker stop и 30 в Kubernetes.
Чем отличаются SIGTERM и SIGKILL?
SIGTERM просит процесс завершиться, и процесс может перехватить его, чтобы закрыть соединения, сохранить данные и выйти. SIGKILL означает, что ядро завершает процесс немедленно и процесс ничего не может сделать. Правильно отправить SIGTERM, подождать несколько секунд и прибегать к SIGKILL, только если процесс всё ещё жив, — именно так поступают systemd, docker stop и Kubernetes.
Почему у того же errno другой номер в macOS?
Потому что POSIX определяет имена, но не номера. Номера с 1 по 34 все системы унаследовали от оригинального Unix; дальше BSD, от которой происходит macOS, и System V, за которой следовал Linux, нумеровали их независимо. Поэтому всегда лучше сравнивать по имени — через errno.ECONNREFUSED в Python, err.code в Node.js или константу в C, — а не по номеру.
Чем отличаются EACCES и EPERM?
EACCES («Permission denied») означает, что этого не позволяют права на файл или на какой-либо каталог пути либо мешает ACL или SELinux: решается через chmod, chown или соответствующую политику. EPERM («Operation not permitted») означает, что сама операция требует привилегий независимо от прав доступа, например сменить владельца файла или убить процесс другого пользователя: нужен root, capability или снятие атрибута, например атрибута неизменяемости.
Как посмотреть код завершения команды или контейнера?
В bash и zsh echo $? показывает код последней команды; в PowerShell — $LASTEXITCODE. В Docker docker ps -a показывает его в столбце STATUS, например «Exited (137)». В Kubernetes kubectl describe pod показывает его в «Last State: Terminated» вместе с причиной, например OOMKilled или Error.