Existem códigos de status de saída padrão no Linux?

308

Considera-se que um processo foi concluído corretamente no Linux se o status de saída for 0.

Vi que falhas de segmentação geralmente resultam em um status de saída 11, embora eu não saiba se essa é simplesmente a convenção em que trabalho (os aplicativos que falharam assim foram todos internos) ou um padrão.

Existem códigos de saída padrão para processos no Linux?

Nathan Fellman
fonte
6
Se você está procurando a coisa chamado "número de erro de sistema" retornado por funções do sistema olhar aqui no errno
marinara

Respostas:

86

8 bits do código de retorno e 8 bits do número do sinal de extermínio são misturados em um único valor no retorno da wait(2)& co. .

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

int main() {
    int status;

    pid_t child = fork();
    if (child <= 0)
        exit(42);
    waitpid(child, &status, 0);
    if (WIFEXITED(status))
        printf("first child exited with %u\n", WEXITSTATUS(status));
    /* prints: "first child exited with 42" */

    child = fork();
    if (child <= 0)
        kill(getpid(), SIGSEGV);
    waitpid(child, &status, 0);
    if (WIFSIGNALED(status))
        printf("second child died with %u\n", WTERMSIG(status));
    /* prints: "second child died with 11" */
}

Como você está determinando o status da saída? Tradicionalmente, o shell armazena apenas um código de retorno de 8 bits, mas define o bit alto se o processo foi finalizado de maneira anormal.

$ sh -c 'saída 42'; eco $?
42.
$ sh -c 'kill -SEGV $$'; eco $?
falha de segmentação
139
$ 139 - 128
11

Se você estiver vendo algo diferente disso, provavelmente o programa possui um SIGSEGVmanipulador de sinal que chama exitnormalmente, para que não seja realmente morto pelo sinal. (Os programas podem optar por manipular qualquer sinal além de SIGKILLe SIGSTOP.)

efémero
fonte
8
Dada a maneira como a pergunta agora aparece, essa não parece ser a resposta mais útil (e, portanto, aceita).
David J.
332

Parte 1: Guia de script avançado do Bash

Como sempre, o Advanced Bash Scripting Guide possui ótimas informações : (isso foi vinculado em outra resposta, mas a um URL não canônico).

1: Captura de erros gerais
2: Uso incorreto dos componentes internos do shell (de acordo com a documentação do Bash)
126: O comando invocado não pode executar
127: "comando não encontrado"
128: Argumento inválido para sair
128 + n: Sinal de erro fatal "n"
255: Sair status fora do intervalo (a saída leva apenas argumentos inteiros no intervalo de 0 a 255)

Parte 2: sysexits.h

O ABSG faz referência sysexits.h.

No Linux:

$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h

/*
 * Copyright (c) 1987, 1993
 *  The Regents of the University of California.  All rights reserved.

 (A whole bunch of text left out.)

#define EX_OK           0       /* successful termination */
#define EX__BASE        64      /* base value for error messages */
#define EX_USAGE        64      /* command line usage error */
#define EX_DATAERR      65      /* data format error */
#define EX_NOINPUT      66      /* cannot open input */    
#define EX_NOUSER       67      /* addressee unknown */    
#define EX_NOHOST       68      /* host name unknown */
#define EX_UNAVAILABLE  69      /* service unavailable */
#define EX_SOFTWARE     70      /* internal software error */
#define EX_OSERR        71      /* system error (e.g., can't fork) */
#define EX_OSFILE       72      /* critical OS file missing */
#define EX_CANTCREAT    73      /* can't create (user) output file */
#define EX_IOERR        74      /* input/output error */
#define EX_TEMPFAIL     75      /* temp failure; user is invited to retry */
#define EX_PROTOCOL     76      /* remote error in protocol */
#define EX_NOPERM       77      /* permission denied */
#define EX_CONFIG       78      /* configuration error */

#define EX__MAX 78      /* maximum listed value */
Schof
fonte
5
Observe que em alguns tipos de unix, alguns comandos usam um status de saída 2 para indicar outras coisas. Por exemplo, muitas implementações do grep usam um status de saída 2 para indicar um erro e usam um status de saída 1 para significar que nenhuma linha selecionada foi encontrada.
NamshubWriter 25/10/12
3
Em BSDs há uma página do homem que resume a informação de sysexits.h:man sysexits
georgebrock
6
O que @NamshubWriter disse. O status de saída 2 é o objetivo universal do uso incorreto da linha de comando nos utilitários Unix, não apenas em "alguns sabores do unix", mas em geral. O cabeçalho mostrado nesta resposta não reflete convenções reais, agora ou quando foi escrito em 1987.
alexis
O ABS não é "ótimo". Por favor, leia sobre o assunto; não é exatamente difícil encontrar críticas.
Tripleee
Mas onde está o código fonte oficial atual sysexits.h? A página de manual que todo mundo mantém referência é apenas uma prosa. Por exemplo, ele faz referência, EX_OKmas na verdade não o define de maneira normativa, como os outros códigos. Há mais que estão faltando?
Garret Wilson
71

'1' >>> Catchall para erros gerais

'2' >>> Uso indevido de componentes internos do shell (de acordo com a documentação do Bash)

'126' >>> O comando invocado não pode ser executado

'127' >>> "comando não encontrado"

'128' >>> Argumento inválido para sair

'128 + n' >>> Sinal de erro fatal "n"

'130' >>> Script finalizado por Control-C

'255' >>> Status de saída fora do intervalo

Isto é para bash. No entanto, para outros aplicativos, existem códigos de saída diferentes.

segfault
fonte
1
Parece que vocês dois responderam no mesmo minuto. Tian teria que ser muito rápido para ver seus links e colá-los no.
Nathan Fellman
6
Observe que 'controle-C produz 130' é consistente com '128 + n' para o sinal n; controlo-C gera SIGINT que é sinal 2.
Jonathan Leffler
3
Isso parece ser plagiado do ABS sem atribuição. (Podemos dizer que o ABS contém informações incorretas ou pelo menos enganosas.) #
Tripleee 10/10/16
4
Esses são códigos de saída RESERVADOS, de acordo com o Advanced Bash-Scripting Guide . Isso significa que esses valores devem ser evitados para os parâmetros de saída especificados pelo usuário .
ingyhere
53

Nenhuma das respostas mais antigas descreve o status de saída 2 corretamente. Ao contrário do que eles afirmam, o status 2 é o que seus utilitários de linha de comando realmente retornam quando chamados incorretamente. (Sim, uma resposta pode ter nove anos, ter centenas de votos positivos e ainda estar errada.)

Aqui está a convenção real de status de saída de longa data para terminação normal, ou seja, não por sinal:

  • Status de saída 0: sucesso
  • Status de saída 1: "falha", conforme definido pelo programa
  • Status de saída 2: erro de uso da linha de comandos

Por exemplo, diffretorna 0 se os arquivos comparados forem idênticos e 1 se eles diferirem. Por convenção de longa data, programas Unix retornar status de saída 2 quando chamado incorretamente (opções desconhecidos, número errado de argumentos, etc.) Por exemplo, diff -N, grep -You diff a b ctudo vai resultar em $?ser definido como 2. Este é e tem sido a prática desde o primeiros dias do Unix na década de 1970.

A resposta aceita explica o que acontece quando um comando é finalizado por um sinal. Em resumo, a terminação devido a um sinal não capturado resulta no status de saída 128+[<signal number>. Por exemplo, a terminação por SIGINT( sinal 2 ) resulta no status de saída 130.

Notas

  1. Várias respostas definem o status de saída 2 como "Uso indevido de bash builtins". Isso se aplica somente quando o bash (ou um script do bash) sai com o status 2. Considere-o um caso especial de erro de uso incorreto.

  2. Em sysexits.h, mencionado na resposta mais popular , o status de saída EX_USAGE("erro de uso da linha de comando") é definido como 64. Mas isso não reflete a realidade: não conheço nenhum utilitário Unix comum que retorne 64 com invocação incorreta (exemplos bem-vindos ) Uma leitura cuidadosa do código fonte revela que sysexits.hé aspiracional, e não um reflexo do uso real:

     *    This include file attempts to categorize possible error
     *    exit statuses for system programs, notably delivermail
     *    and the Berkeley network.
    
     *    Error numbers begin at EX__BASE [64] to reduce the possibility of 
     *    clashing with oth­er exit statuses that random programs may 
     *    already return. 
    

    Em outras palavras, essas definições não refletem a prática comum na época (1993), mas eram intencionalmente incompatíveis com ela. Mais é uma pena.

alexis
fonte
O que um programa deve retornar quando faz rescisão pega pela captura SIGINT / Ctrl-C? Ainda 130? O uso de outro shell além do bash é importante?
Gringo Suave
1
O shell que está executando o programa é irrelevante; teoricamente, um processo pode optar por sair com status diferente, dependendo do processo pai, mas nunca ouvi falar de um caso em que isso ocorra.
alexis
1
Se um programa pegar o SIGINT, limpar e sair de qualquer maneira, o status será o que fizer sentido para o programa. Por exemplo, moreredefinirá os modos do terminal e sairá com o status 0 (você pode tentar).
21418 alexis
1
Essa resposta implica um grau muito mais alto de padronização do que realmente é o caso. Não existe uma padronização adequada do significado do valor 2, e a prática real é previsivelmente muito mista. É verdade que muitas ferramentas retornam 2 por uso indevido, mas não está exatamente bem definido o que significa "uso indevido" e muitas outras não aderem a esta convenção.
Tripleee
@tripleee "tools" também não está bem definido! :-) Claro, qualquer um pode escrever um programa de linha de comando e ele pode retornar qualquer coisa, mas os "utilitários de linha de comando Unix" antigos que existem há mais tempo que o Linux ou o conteúdo dos coreutils do GNU são bastante consistente nisso. Se você pensar de outra forma, nomeie algumas ferramentas deste grupo que não usam o status 2 dessa maneira. Além disso, "uso inadequado" é o seu termo (e eu concordo que é um termo vago); Eu escrevi "erro de linha de uso do comando", que é bastante específica: opções não-existentes ou incompatíveis, número errado de argumentos não-opção, etc.
alexis
25

Não há códigos de saída padrão, além de 0, significando sucesso. Diferente de zero também não significa necessariamente falha.

stdlib.h define EXIT_FAILUREcomo 1 e EXIT_SUCCESScomo 0, mas é isso.

O 11 no segfault é interessante, pois 11 é o número do sinal que o kernel usa para interromper o processo no caso de um segfault. Provavelmente, existe algum mecanismo, no kernel ou no shell, que o converte no código de saída.

Chris Arguin
fonte
20

sysexits.h tem uma lista de códigos de saída padrão. Parece que remonta a pelo menos 1993 e alguns grandes projetos como o Postfix o usam, então imagino que seja o caminho a seguir.

Na página do manual do OpenBSD:

De acordo com o estilo (9), não é uma boa prática chamar exit (3) com valores arbitrários para indicar uma condição de falha ao finalizar um programa. Em vez disso, os códigos de saída predefinidos de sysexits devem ser usados, para que o responsável pelo processo possa obter uma estimativa aproximada da classe de falha sem consultar o código-fonte.

fonte
8

Para uma primeira aproximação, 0 é sucesso, diferente de zero é falha, sendo 1 uma falha geral e qualquer coisa maior que uma sendo uma falha específica. Além das exceções triviais de false e test, que são projetadas para fornecer 1 para o sucesso, há outras exceções que encontrei.

Mais realisticamente, 0 significa sucesso ou talvez falha, 1 significa falha geral ou talvez sucesso, 2 significa falha geral se 1 e 0 forem usados ​​para o sucesso, mas talvez também o sucesso.

O comando diff fornece 0 se os arquivos comparados forem idênticos, 1 se eles diferirem e 2 se os binários forem diferentes. 2 também significa falha. O comando less fornece 1 para falha, a menos que você não forneça um argumento; nesse caso, ele sai 0, apesar de falhar.

O comando more e o comando spell fornecem 1 para falha, a menos que a falha seja resultado de permissão negada, arquivo inexistente ou tentativa de ler um diretório. Em qualquer um desses casos, eles saem de 0 apesar de falharem.

Em seguida, o comando expr fornece 1 para sucesso, a menos que a saída seja a sequência vazia ou zero; nesse caso, 0 é sucesso. 2 e 3 são falhas.

Depois, há casos em que o sucesso ou o fracasso é ambíguo. Quando o grep falha em encontrar um padrão, sai 1, mas sai 2 por uma falha genuína (como permissão negada). O Klist também sai do 1 quando falha em encontrar um ticket, embora isso não seja mais uma falha do que quando o grep não encontra um padrão ou quando você está em um diretório vazio.

Portanto, infelizmente, os poderes do unix que parecem existir não impõem nenhum conjunto lógico de regras, mesmo em executáveis ​​muito usados.

Frederick
fonte
Eu estava prestes a apontar o comportamento do diff também. wget erros também tem detalhados (por exemplo 6 para falha de autenticação), mas, em seguida, eles usam 1 = erro genérico, 2..n = erro específico
PypeBros
5

Os programas retornam um código de saída de 16 bits. Se o programa foi interrompido com um sinal, o byte de alta ordem contém o sinal usado; caso contrário, o byte de baixa ordem é o status de saída retornado pelo programador.

Como esse código de saída é atribuído à variável de status $? é então até o shell. O Bash mantém os 7 bits inferiores do status e, em seguida, usa 128 + (sinal nr) para indicar um sinal.

A única convenção "padrão" para programas é 0 para êxito, diferente de zero para erro. Outra convenção usada é retornar errno por erro.

Dean Povey
fonte
3

Os códigos de saída padrão do Unix são definidos por sysexits.h, como outro pôster mencionado. Os mesmos códigos de saída são usados ​​por bibliotecas portáteis como o Poco - aqui está uma lista deles:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

Um sinal 11 é um sinal SIGSEGV (violação de segmento), que é diferente de um código de retorno. Este sinal é gerado pelo kernel em resposta a um acesso incorreto à página, o que faz com que o programa seja encerrado. Uma lista de sinais pode ser encontrada na página de manual do sinal (execute "man signal").

Daniel Schuler
fonte
1

Quando o Linux retorna 0, significa sucesso. Qualquer outra coisa significa falha, cada programa tem seus próprios códigos de saída, por isso demorou bastante para listá-los todos ...!

Sobre o código de 11 erros, é realmente o número da falha de segmentação, significando principalmente que o programa acessou um local de memória que não foi atribuído.

Amadeus45
fonte
1
É sempre 11 porque o kernel o mata e atribui o "valor de saída". Da mesma forma, outros tipos de falhas sempre terão o mesmo valor de saída.
Alex Gartrell