208 de 208 códigos
A operação requer privilégios que o processo não tem, como mudar o dono de um arquivo, enviar um sinal a um processo de outro usuário ou modificar um arquivo imutável (chattr +i). Diferente de EACCES, não se resolve mudando as permissões do arquivo: é preciso ser root ou ter a capability correspondente.
O arquivo ou diretório não existe. Também aparece quando falta um diretório intermediário do caminho, quando um link simbólico aponta para um destino que não existe ou quando o interpretador da linha #! de um script não está instalado.
Não existe nenhum processo, grupo de processos ou thread com esse identificador; por exemplo, ao executar kill sobre um PID que já terminou.
Um sinal interrompeu a chamada de sistema antes que ela terminasse. Não é um erro de verdade: o programa deve repetir a chamada ou instalar o manipulador do sinal com SA_RESTART.
Erro de entrada/saída de baixo nível, em geral ao ler ou gravar no dispositivo. Em discos, costuma indicar setores danificados ou um cabo com defeito: verifique o dmesg e o status SMART. Também aparece ao escrever em um terminal que já foi fechado.
O dispositivo ou o endereço não existe: o arquivo de dispositivo está lá, mas não há hardware por trás, ou um FIFO foi aberto para escrita com O_NONBLOCK sem nenhum leitor.
A lista de argumentos e variáveis de ambiente passada para exec é grande demais. É o clássico “Argument list too long” ao usar um curinga que se expande para milhares de arquivos; use find -exec ou xargs.
O arquivo não tem um formato executável reconhecido: é um binário de outra arquitetura, está danificado ou é um script sem linha #!.
O descritor de arquivo não é válido, já foi fechado ou foi aberto em um modo que não permite a operação, como escrever em um descritor aberto somente para leitura.
O processo não tem filhos pelos quais esperar com wait ou waitpid, muitas vezes porque SIGCHLD é ignorado e os filhos são recolhidos automaticamente.
O recurso não está disponível no momento e convém tentar de novo. Em operações não bloqueantes, significa que ainda não há dados ou espaço; no fork, que foi atingido o limite de processos ou threads (ulimit -u ou pids.max do cgroup).
Mesmo valor:EWOULDBLOCK
Não há memória suficiente para a operação ou foi excedido um limite de memória do processo. No fork ou no mmap, pode ser causado pela política de overcommit, pelo limite do cgroup ou pela falta de espaço de endereçamento.
Permissão negada pelas permissões do arquivo ou de um diretório do caminho (é preciso permissão de execução em cada um), por uma ACL, pelo SELinux ou AppArmor, ou por uma montagem com noexec. O bind também o retorna ao usar uma porta menor que 1024 sem privilégios.
Foi passado a uma chamada de sistema um ponteiro para um endereço de memória inválido. Indica um bug no programa.
A operação precisa de um dispositivo de blocos, como um disco, e recebeu outro tipo de arquivo; por exemplo, ao montar um arquivo comum sem -o loop.
O dispositivo ou o recurso está em uso. É típico ao desmontar um sistema de arquivos que tem arquivos abertos ou um terminal posicionado nele; lsof ou fuser mostram quais processos o usam.
Já existe um arquivo, um diretório ou outro objeto com esse nome, por exemplo ao criar com O_EXCL, ao usar mkdir sem -p ou ao criar um link cujo destino já existe.
Não é possível criar um link físico nem renomear um arquivo entre sistemas de arquivos diferentes. O mv resolve isso copiando e apagando; os programas que usam rename() devem fazer o mesmo.
O dispositivo não existe ou não suporta a operação; por exemplo, ao montar um tipo de sistema de arquivos cujo módulo do kernel não está carregado.
Um componente do caminho que deveria ser um diretório é um arquivo, ou foi pedido um diretório (O_DIRECTORY) e não é.
Foi tentada uma operação de arquivo sobre um diretório, como abri-lo para escrita.
Um argumento não é válido para a chamada: um valor fora do intervalo, uma combinação de opções incompatível ou uma operação que o objeto não suporta. É genérico: a página man da chamada lista os casos concretos.
A tabela de arquivos abertos de todo o sistema se esgotou. O limite é ajustado com fs.file-max no sysctl.
O processo atingiu seu limite de descritores abertos (“Too many open files”). Aumente o limite com ulimit -n ou com LimitNOFILE no systemd, e verifique se o programa não deixa arquivos ou sockets sem fechar.
Foi pedida uma operação de terminal (ioctl) sobre algo que não é um terminal, por exemplo quando a saída de um programa interativo é redirecionada para um arquivo ou um pipe.
O executável está em uso: não é possível escrever em um binário enquanto ele é executado, nem executar um que continua aberto para escrita. Para atualizá-lo, convém escrever um arquivo novo e renomeá-lo.
O arquivo excede o tamanho máximo suportado pelo sistema de arquivos (4 GB no FAT32) ou o limite RLIMIT_FSIZE do processo.
Não há espaço livre no dispositivo. Se o df mostrar espaço livre, verifique os inodes com df -i. O inotify também o retorna ao esgotar fs.inotify.max_user_watches.
Não é possível fazer lseek em um pipe, um FIFO ou um socket, porque eles não têm posição.
O sistema de arquivos está montado como somente leitura. Se passou a somente leitura sem que ninguém pedisse, foi o kernel ao detectar erros: verifique o dmesg e execute o fsck.
Foi excedido o número máximo de links físicos para um arquivo, ou o de subdiretórios de um diretório em alguns sistemas de arquivos.
Houve uma escrita em um pipe ou socket cuja outra ponta já foi fechada (“Broken pipe”). Além do erro, o processo recebe SIGPIPE; é normal quando o leitor termina antes, como em cmd | head.
O argumento de uma função matemática está fora do seu domínio, como a raiz quadrada de um número negativo.
O resultado de uma função é grande ou pequeno demais para ser representado, ou um buffer não é suficiente para o resultado, como no getcwd com um buffer curto.
Um deadlock foi evitado: o lock pedido, como um bloqueio de arquivo com fcntl ou um mutex com detecção de erros, ficaria esperando para sempre.
Mesmo valor:EDEADLOCK
O caminho ou um de seus componentes excede o comprimento máximo: no Linux, em geral, 255 bytes por nome e 4096 por caminho.
Não há locks disponíveis. No NFS, costuma indicar que o serviço de bloqueio (lockd ou rpc.statd) não está funcionando.
A chamada de sistema não existe neste kernel ou não está implementada. É típico de binários compilados para um kernel mais novo, ou de perfis seccomp de contêineres que não conhecem chamadas recentes.
O diretório não está vazio, por exemplo ao usar rmdir ou ao renomear sobre um diretório existente. Para apagá-lo com seu conteúdo, use rm -r.
Há links simbólicos encadeados demais ao resolver o caminho, normalmente por causa de um ciclo, ou foi usado O_NOFOLLOW sobre um link simbólico.
Não há nenhuma mensagem do tipo pedido na fila de mensagens do System V.
O identificador de IPC do System V (fila, semáforo ou memória compartilhada) foi removido enquanto o processo o usava.
Número de canal fora do intervalo. É um código legado sem uso prático no Linux.
Nível 2 não sincronizado. É um código legado do System V sem uso prático no Linux.
Nível 3 parado. É um código legado do System V sem uso prático no Linux.
Nível 3 reiniciado. É um código legado do System V sem uso prático no Linux.
Número de link fora do intervalo. É um código legado sem uso prático no Linux.
O driver do protocolo não está conectado. Poucos subsistemas o usam, como alguns drivers de Bluetooth.
Não há nenhuma estrutura CSI disponível. É um código legado sem uso prático no Linux.
Nível 2 parado. É um código legado do System V sem uso prático no Linux.
Troca inválida. É um código legado que alguns drivers e sistemas de arquivos reutilizam com um sentido próprio.
Descritor de requisição inválido. É um código legado que alguns drivers reutilizam com um sentido próprio.
Troca cheia. É um código legado sem uso prático no Linux.
Não há nenhum “anode”. É um código legado sem uso prático no Linux.
Código de requisição inválido. É legado; alguns drivers o usam para comandos que não suportam.
Slot inválido. É um código legado sem uso prático no Linux.
Formato de arquivo de fonte incorreto. É um código legado sem uso prático no Linux.
O dispositivo não é um STREAM. Pertence à interface STREAMS do System V, que o Linux não implementa.
Não há dados disponíveis. No Linux, o getxattr o retorna quando o atributo estendido não existe; no macOS, esse caso é ENOATTR.
Um temporizador expirou. Vem do STREAMS; no Linux, alguns drivers e o io_uring o usam para operações com tempo limite.
Não restam recursos de STREAMS, uma interface que o Linux não implementa.
A máquina não está na rede. É um código legado pouco usado.
O pacote não está instalado. É legado; alguns subsistemas o usam quando falta um módulo, por exemplo um criptográfico.
O objeto é remoto. No NFS, indica um caminho exportado a partir de outro servidor.
O link foi cortado. É legado; alguns drivers o usam quando a conexão com o dispositivo é perdida.
Erro de “advertise”. É um código legado do RFS sem uso no Linux.
Erro de “srmount”. É um código legado do RFS sem uso no Linux.
Erro de comunicação ao enviar. É legado; alguns drivers de rede e USB o usam.
Erro de protocolo: a outra ponta ou o dispositivo respondeu algo inesperado. Aparece com dispositivos USB e em conexões que caem no meio de uma troca.
Foi tentado um salto múltiplo (multihop). É um código legado do RFS.
Erro específico do RFS. Sem uso no Linux.
A mensagem está malformada ou corrompida. O ext4, o XFS e o Btrfs o retornam, com o alias EFSBADCRC, quando a soma de verificação dos metadados falha.
Mesmo valor:EFSBADCRC
O valor não cabe no tipo de dados de destino; por exemplo, um programa de 32 bits compilado sem suporte a arquivos grandes que abre um arquivo de mais de 2 GB.
O nome não é único na rede. É um código legado.
O descritor de arquivo está em um estado incorreto. O ALSA e alguns drivers o usam quando o dispositivo não está preparado.
O endereço remoto mudou. É um código legado.
Não é possível acessar uma biblioteca compartilhada necessária. É um código legado dos binários a.out.
A biblioteca compartilhada está danificada. É um código legado dos binários a.out.
A seção .lib do binário a.out está danificada. É um código legado.
Houve uma tentativa de vincular bibliotecas compartilhadas demais. É um código legado do a.out.
Uma biblioteca compartilhada não pode ser executada diretamente. É um código legado do a.out.
A sequência de bytes não é válida para a codificação de caracteres, como um texto que não é UTF-8 válido ao convertê-lo com iconv ou com as funções multibyte.
A chamada interrompida deve ser reiniciada. É de uso interno do kernel e não deveria chegar aos programas.
Erro de pipe do STREAMS. O ALSA o retorna quando o dispositivo de áudio está suspenso.
Há usuários demais. O sistema de cotas de disco o retorna quando sua tabela fica cheia, o que é pouco comum.
Foi usada uma operação de socket sobre um descritor que não é um socket.
Falta o endereço de destino: algo foi enviado por um socket sem conexão sem indicar para onde.
A mensagem é grande demais para o socket, como um datagrama UDP maior que o máximo ou que a MTU quando a fragmentação não é permitida.
O protocolo não corresponde ao tipo de socket.
A opção de socket ou o protocolo pedido não está disponível, por exemplo uma opção do setsockopt que o kernel não conhece.
O protocolo não é suportado, por exemplo porque seu módulo do kernel não está carregado.
O tipo de socket não é suportado nessa família de endereços.
A operação não é suportada pelo socket ou pelo objeto. No Linux, tem o mesmo valor que ENOTSUP, e muitos sistemas de arquivos o retornam para funções que não implementam, como fallocate ou os atributos estendidos.
A operação não é suportada. No Linux, tem o mesmo valor que EOPNOTSUPP (95); no macOS, são códigos diferentes.
A família de protocolos não é suportada.
A família de endereços não é suportada; é típico ao usar IPv6 em um sistema ou contêiner que o tem desabilitado.
O endereço e a porta já estão em uso: outro processo escuta nessa porta, ou a conexão anterior continua em TIME_WAIT. Encontre o processo com ss -ltnp ou lsof -i :PORTA, ou use SO_REUSEADDR.
Não é possível atribuir o endereço pedido: o IP não pertence a nenhuma interface da máquina, ou as portas efêmeras para conexões de saída se esgotaram.
A interface de rede está inativa.
A rede de destino é inalcançável porque não há nenhuma rota para ela. Verifique a tabela de rotas e o gateway; também acontece ao conectar por IPv6 sem conectividade IPv6.
A rede reiniciou a conexão, por exemplo quando um keepalive falha.
A conexão foi abortada do lado local, por exemplo porque o cliente a fechou antes que o servidor a aceitasse com accept.
A outra ponta cortou a conexão abruptamente com um RST (“Connection reset by peer”): o processo remoto foi encerrado, um firewall ou um balanceador de carga cortou a conexão inativa, ou foram enviados dados que o outro lado não esperava.
Não há espaço de buffer disponível no kernel para a operação de rede; costuma aparecer com muito tráfego ou com as filas dos sockets cheias.
O socket já está conectado.
O socket não está conectado: tentou-se enviar ou receber antes de conectar, ou a conexão já foi fechada. Em uma montagem FUSE, aparece como “Transport endpoint is not connected” quando seu processo morreu; resolve-se desmontando com fusermount -u.
Não é possível enviar depois de fechar esse sentido do socket com shutdown.
Há referências demais; no Linux, ao passar descritores aninhados demais por um socket Unix.
O tempo de espera da conexão se esgotou porque o destino não respondeu. Costuma ser causado por um firewall que descarta os pacotes silenciosamente, por um host desligado ou por uma rota que não chega ao destino.
O destino recusou a conexão: a máquina responde, mas ninguém escuta nessa porta ou um firewall responde com uma rejeição. Verifique se o serviço está rodando e escutando na interface correta, não apenas em 127.0.0.1.
O host de destino está fora do ar.
Não há rota para o host: ele não responde a ARP na rede local, ou um roteador ou firewall informa que ele é inalcançável.
Já há uma operação em andamento no socket, como um connect não bloqueante que ainda não terminou.
A operação está em andamento: um connect não bloqueante começou e terminará mais tarde. Não é um erro; é preciso esperar com poll ou select.
O identificador de arquivo ficou obsoleto: no NFS, o arquivo ou o diretório foi apagado ou substituído no servidor. Resolve-se abrindo o caminho novamente ou remontando.
A estrutura precisa de limpeza: o sistema de arquivos detectou corrupção (no ext4 e no XFS, com o alias EFSCORRUPTED). Desmonte-o e execute fsck ou xfs_repair.
Mesmo valor:EFSCORRUPTED
Não é um arquivo nomeado do XENIX. É um código legado sem uso.
Não há semáforos do XENIX disponíveis. É um código legado sem uso.
É um arquivo nomeado do XENIX. É um código legado sem uso.
Erro de E/S remota, por exemplo de um dispositivo I2C ou de um disco remoto que não respondeu.
A cota de disco do usuário ou do grupo foi excedida.
Não há nenhuma mídia no dispositivo, como uma unidade óptica sem disco ou um leitor de cartões vazio.
O tipo de mídia não é o correto.
A operação foi cancelada, por exemplo uma E/S assíncrona ou uma espera do io_uring.
A chave necessária não está no keyring do kernel. Aparece com sistemas de arquivos criptografados, como fscrypt ou eCryptfs, quando a chave não foi carregada.
A chave expirou. O PAM e o Kerberos também o usam quando a senha ou o ticket expirou.
A chave foi revogada.
O serviço rejeitou a chave.
O dono de um mutex robusto morreu sem liberá-lo. O novo dono deve deixar consistente o estado protegido e chamar pthread_mutex_consistent.
O estado protegido por um mutex robusto não pode ser recuperado, porque o dono anterior morreu e ninguém o marcou como consistente.
A operação não é possível porque o rádio Wi-Fi ou Bluetooth está bloqueado pelo RF-kill. Verifique rfkill list, a chave física ou a tecla de modo avião.
A página de memória tem um erro de hardware e o kernel a marcou como envenenada.
O tipo de arquivo não é adequado para a operação. No macOS e no BSD existe há muito tempo; no Linux, foi adicionado recentemente.
Há processos demais. O BSD o define para o limite de processos, embora na prática o fork retorne EAGAIN.
A estrutura de RPC está incorreta (Sun RPC, usado pelo NFS).
A versão de RPC não corresponde (Sun RPC, usado pelo NFS).
O programa RPC não está disponível no servidor.
A versão do programa RPC não corresponde.
O procedimento não existe no programa RPC.
Erro de autenticação, por exemplo ao montar um compartilhamento NFS.
É necessário um autenticador para a operação.
O dispositivo está desligado.
Erro do dispositivo, por exemplo uma impressora sem papel.
O executável não é válido.
O executável é para outro tipo de CPU, como um binário somente x86_64 em um Mac com Apple Silicon sem o Rosetta 2, ou um ARM em um Mac com Intel.
A versão da biblioteca compartilhada não corresponde.
O arquivo Mach-O está malformado ou danificado.
O atributo estendido não existe; equivale ao ENODATA do Linux. Aparece com xattr, por exemplo ao remover com.apple.quarantine de um arquivo que não o tem.
Não há nenhuma política registrada com esse nome no MAC Framework.
A fila de saída da interface de rede está cheia.
As capacidades não são suficientes: é retornado pelas chamadas restringidas por um sandbox.
O terminal que controlava o processo foi fechado ou a sessão SSH caiu. Muitos daemons, como nginx, sshd ou rsyslog, o usam como pedido para reler a configuração; nohup, tmux e screen evitam que ele encerre os processos ao sair.
Interrupção pelo teclado com Ctrl+C. O programa pode capturá-lo para terminar de forma ordenada. Código de saída 130.
Saída pelo teclado com Ctrl+\. Encerra o processo com despejo de memória; a JVM, por outro lado, o usa para imprimir o estado das threads.
O processador encontrou uma instrução ilegal: um binário compilado para uma CPU mais nova (por exemplo, com AVX2 ou AVX-512 em um processador que não os tem), código danificado ou um salto para dados.
Trap de depuração: os depuradores o usam para os breakpoints. Se chegar sem um depurador, costuma ser uma falha detectada pelo próprio programa, como as verificações do Swift no macOS.
O processo chamou abort(): uma asserção que falhou, uma exceção de C++ não capturada ou uma corrupção do heap detectada pela biblioteca C (“double free or corruption”). Código de saída 134.
Mesmo valor:SIGIOT
Erro de barramento: um acesso a memória desalinhada em algumas arquiteturas, ou a uma parte de um arquivo mapeado com mmap que já não existe porque o arquivo foi truncado. Também acontece quando /dev/shm fica cheio.
Exceção aritmética. Apesar do nome, a causa mais comum é uma divisão inteira por zero.
Encerra o processo imediatamente: não pode ser capturado, bloqueado nem ignorado. É enviado por kill -9, pelo OOM killer do kernel quando a memória se esgota, e pelo Docker ou Kubernetes quando um contêiner excede seu limite de memória (OOMKilled) ou não termina a tempo depois de SIGTERM. Código de saída 137.
Sinal livre para que cada aplicação lhe dê seu próprio uso; por exemplo, o dd informa seu progresso e o nginx reabre os logs.
Violação de segmento (“Segmentation fault”): um acesso a memória inválida, como desreferenciar um ponteiro nulo, sair dos limites de um array ou estourar a pilha com uma recursão infinita. Código de saída 139.
Segundo sinal livre para que cada aplicação lhe dê seu próprio uso.
Escrita em um pipe ou socket sem leitor. É normal em cmd | head, onde o leitor termina antes; os servidores costumam ignorá-lo e tratar o erro EPIPE. Código de saída 141.
O temporizador programado com alarm ou setitimer expirou.
Pedido de encerramento ordenado. É o sinal padrão do kill, do systemctl stop, do docker stop e do Kubernetes ao excluir um pod; o processo deveria fechar suas conexões e sair. Código de saída 143.
Falha de pilha do coprocessador. Não é usado no Linux atual.
Um processo filho terminou, foi suspenso ou foi retomado. O pai deve recolhê-lo com wait; se não o fizer, o filho fica como zumbi.
Mesmo valor:SIGCLD
Retoma um processo suspenso, como fazem fg e bg no shell.
Suspende o processo; não pode ser capturado nem ignorado. O processo é retomado com SIGCONT.
Suspensão a partir do terminal com Ctrl+Z. Diferente de SIGSTOP, o programa pode capturá-lo.
Um processo em segundo plano tentou ler do terminal.
Um processo em segundo plano tentou escrever no terminal com stty tostop ativo, ou alterar a configuração do terminal.
Chegaram dados urgentes (fora de banda) a um socket. O Go o usa internamente para interromper goroutines.
O limite de tempo de CPU do processo foi excedido (ulimit -t).
O tamanho máximo de arquivo permitido ao processo foi excedido (ulimit -f).
O temporizador virtual, que conta apenas o tempo de CPU do processo, expirou.
O temporizador de profiling, usado pelos profilers, expirou.
O tamanho da janela do terminal mudou; os programas de tela cheia o usam para se redesenhar.
Há E/S disponível em um descritor configurado com O_ASYNC. No Linux, SIGPOLL é o mesmo sinal.
Mesmo valor:SIGPOLL
Falha de energia, que um software de nobreak (UPS) informa ao sistema init.
Chamada de sistema incorreta. Hoje a causa habitual é um filtro seccomp que a bloqueia, como nos contêineres.
Trap de emulação (EMT). Existe no macOS e no BSD, mas não no Linux em x86 nem em ARM.
Pedido de informação com Ctrl+T no terminal do macOS e do BSD; muitos comandos respondem mostrando seu progresso.
O comando terminou com sucesso. É o único código que significa sucesso: qualquer outro valor indica um erro.
Erro geral; cada programa decide o que significa. O detalhe costuma estar no que o comando escreveu no stderr. grep e diff o usam com outro sentido: “não encontrou correspondências” ou “os arquivos são diferentes”.
Uso incorreto de um comando interno do shell ou erro de sintaxe no script. Muitos programas também o usam para opções inválidas, e o grep para erros reais.
O comando foi usado incorretamente: faltam argumentos, sobram argumentos ou alguma opção está incorreta.
Os dados de entrada têm um formato incorreto.
Um arquivo de entrada não existe ou não pode ser lido.
O usuário indicado não existe; é usado sobretudo pelos programas de e-mail.
O nome do host não existe.
Um serviço necessário não está disponível, ou falhou algo que não se encaixa em outra categoria.
Erro interno do programa.
Erro do sistema operacional, como não conseguir fazer fork ou criar um pipe.
Falta um arquivo do sistema, como /etc/passwd, ou ele tem um erro.
Não é possível criar um arquivo de saída.
Erro de entrada/saída ao ler ou gravar um arquivo.
Falha temporária: convém tentar novamente mais tarde. Os servidores de e-mail o usam para deixar a mensagem na fila.
O sistema remoto respondeu algo que não respeita o protocolo.
Permissões insuficientes para a operação.
Há um erro na configuração.
O comando timeout o encerrou porque ele excedeu o tempo indicado.
O próprio docker run falhou antes de executar o contêiner, por exemplo por uma opção incorreta ou um erro do daemon. O GNU timeout também o retorna quando quem falha é ele.
O arquivo existe, mas não pode ser executado: falta a permissão de execução, é um diretório ou é um binário de outra arquitetura. No Docker, o comando do contêiner não é executável.
O comando não foi encontrado: não está instalado, não está no PATH ou o nome está escrito errado. Em scripts, também aparece quando falta o interpretador da linha #!; no Docker, quando o comando do contêiner não existe na imagem.
Os códigos maiores que 128 indicam que um sinal encerrou o processo, mas 128 não corresponde a nenhum. O Git o usa para todos os seus erros fatais (“fatal: …”), como um repositório que não existe ou uma falha de autenticação ao clonar.
O código de saída ficou fora do intervalo: exit -1 chega como 255, porque só são conservados 8 bits. O ssh também o retorna quando a conexão ou a autenticação falha, para diferenciá-lo do código do comando remoto.
Os valores do Linux são os de x86, x86-64 e ARM; Alpha, MIPS, SPARC e PA-RISC numeram alguns errno e sinais de forma diferente. As mensagens em inglês são as que strerror e strsignal mostram na glibc, e no macOS quando são diferentes. Os códigos de saída maiores que 128 são interpretados como 128 mais o número do sinal, que é a convenção do bash, do Docker e do Kubernetes.
Como funciona
Quando uma chamada de sistema falha no Linux, ela retorna -1 e deixa na variável errno um número que diz o motivo: 2 é ENOENT, o arquivo não existe; 13 é EACCES, permissão negada. O strerror converte esse número no texto que aparece na tela, como “No such file or directory”. O Python o mostra como [Errno 13], o Node.js como code: 'ECONNREFUSED', e Go, Rust ou Java com o mesmo texto. Os números de 1 a 34 vêm do Unix original e são iguais em todos os sistemas; os seguintes foram numerados por cada sistema à sua maneira, por isso ECONNREFUSED é 111 no Linux e 61 no macOS. O nome é portável; o número, não.
Os sinais são avisos que o kernel ou outro processo enviam a um processo: SIGINT quando se pressiona Ctrl+C, SIGTERM para pedir que ele termine, SIGKILL para encerrá-lo sem perguntar, SIGSEGV quando ele acessa memória inválida. Cada um tem uma ação padrão, e quase todos podem ser capturados para fazer outra coisa. Quando um sinal mata um processo, o shell informa como código de saída 128 mais o número do sinal: 137 é SIGKILL (9), 139 é SIGSEGV (11) e 143 é SIGTERM (15). O Docker e o Kubernetes usam a mesma convenção.
O código de saída é o número que um programa deixa ao terminar: 0 significa sucesso e qualquer outro valor, erro. Só são conservados 8 bits, então ele vai de 0 a 255. Há poucas convenções: 126 e 127 são usados pelo shell quando não consegue executar ou não encontra o comando, de 64 a 78 são definidos pelo sysexits.h do BSD, e o resto é decidido por cada programa, como o grep, que retorna 1 quando não encontra nada.
Exemplos
Last State: Terminated · Reason: OOMKilled · Exit Code: 137137 = 128 + 9 · SIGKILLO contêiner excedeu seu limite de memória e o kernel o matou com SIGKILL. É preciso aumentar o limite em resources.limits.memory ou descobrir por que o processo consome tanto; reiniciá-lo não resolve.Error: connect ECONNREFUSED 127.0.0.1:5432ECONNREFUSED · Linux 111 · macOS 61 · Connection refusedO Node.js não conseguiu se conectar ao PostgreSQL porque ninguém escuta na porta 5432. Se a aplicação roda em um contêiner, 127.0.0.1 é o próprio contêiner e não a máquina: é preciso usar o nome do serviço do banco de dados.OSError: [Errno 48] Address already in useEADDRINUSE · Linux 98 · macOS 48O 48 revela que o programa roda no macOS: no Linux, o mesmo erro é o 98. Em ambos os casos, outro processo já usa a porta; lsof -i :PORTA mostra qual.Casos de uso
- Entender um erro de uma aplicação em Python, Node.js, Go ou C que só mostra o número ou o nome do errno.
- Descobrir, a partir do código de saída, por que um contêiner do Docker foi encerrado ou um pod do Kubernetes reinicia.
- Converter um número de errno do macOS no nome correto, que a partir do 35 não coincide com o do Linux.
- Interpretar o código de saída de um script, um cron ou um job de CI que falhou.
- Escolher qual sinal enviar com kill e saber o que o processo faz se não o capturar.
- Escrever um tratamento de erros portável que compare por nome em vez de por número.
Perguntas frequentes
O que significa o exit code 137?
Que o processo foi encerrado pelo sinal 9, SIGKILL (128 + 9). A causa mais comum é a memória: o contêiner excedeu seu limite, e o Kubernetes informa isso como OOMKilled, ou o OOM killer do kernel escolheu esse processo, o que fica registrado no dmesg como “Out of memory: Killed process”. Também acontece com docker kill, ou quando o processo não termina dentro do prazo depois de SIGTERM: 10 segundos no docker stop e 30 no Kubernetes.
Qual é a diferença entre SIGTERM e SIGKILL?
SIGTERM pede ao processo que termine, e o processo pode capturá-lo para fechar conexões, salvar dados e sair. Com SIGKILL, o kernel o encerra na hora, sem que o processo possa fazer nada. O correto é enviar SIGTERM, esperar alguns segundos e recorrer a SIGKILL só se ele continuar vivo, que é o que fazem o systemd, o docker stop e o Kubernetes.
Por que o mesmo errno tem outro número no macOS?
Porque o POSIX define os nomes, mas não os números. De 1 a 34, todos os sistemas herdaram os do Unix original; depois, o BSD, do qual vem o macOS, e o System V, que o Linux seguiu, os numeraram separadamente. Por isso convém comparar sempre pelo nome, com errno.ECONNREFUSED no Python, err.code no Node.js ou a constante em C, e não pelo número.
Qual é a diferença entre EACCES e EPERM?
EACCES (“Permission denied”) significa que as permissões do arquivo ou de algum diretório do caminho não o permitem, ou que uma ACL ou o SELinux o impedem: resolve-se com chmod, chown ou a política correspondente. EPERM (“Operation not permitted”) significa que a própria operação requer privilégios, independentemente das permissões, como mudar o dono de um arquivo ou matar um processo de outro usuário: é preciso ser root, ter uma capability ou remover um atributo como o de imutável.
Como vejo o código de saída de um comando ou de um contêiner?
No bash e no zsh, echo $? mostra o do último comando; no PowerShell, $LASTEXITCODE. No Docker, docker ps -a o mostra na coluna STATUS, como “Exited (137)”. No Kubernetes, kubectl describe pod o mostra em “Last State: Terminated”, junto com o motivo, como OOMKilled ou Error.