Quais são os valores mínimo e máximo dos códigos de saída no Linux?

31

Quais são os valores mínimo e máximo dos seguintes códigos de saída no Linux:

  1. O código de saída retornado de um executável binário (por exemplo: a C programa).
  2. O código de saída retornado de um script bash (ao chamar exit ).
  3. O código de saída retornado de uma função (ao chamar return ). Eu acho que isso é entre 0 e 255 .
por user271801 22.01.2018 / 08:59

4 respostas

64

O número passado para a chamada de sistema _exit() / exit_group() (às vezes referida como o código de saída para evitar a ambiguidade com status de saída que também está se referindo a uma codificação do código de saída ou do número de sinal e informações adicionais, dependendo se o processo foi morto ou saiu normalmente) é do tipo int , portanto em sistemas semelhantes ao Unix como o Linux, geralmente um inteiro de 32 bits com valores de -2147483648 ( -2 31 ) para 2147483647 (2 31 -1).

No entanto, em todos os sistemas, quando o processo pai (ou o subagrupador filho ou init se o pai morreu) usa as chamadas de sistema wait() , waitpid() , wait3() , wait4() para recuperá-lo, apenas os 8 bits inferiores estão disponíveis (valores de 0 a 255 (2 8 -1)).

Ao usar a waitid() API (ou um manipulador de sinal no SIGCHLD), na maioria dos sistemas (e como POSIX agora mais requer claramente na edição de 2016 do padrão (consulte _exit() specification ) ), o número completo está disponível (no campo si_status da estrutura retornada). Esse não é o caso no Linux, embora também trunque o número para 8 bits com a API waitid() , embora seja provável que mude no futuro.

Geralmente, você desejaria usar somente valores 0 (geralmente significa sucesso) para 125 apenas, pois muitos shells usam valores acima de 128 em sua representação $? do status de saída para codificar o número de sinal de um processo sendo morto e 126 e 127 para condições especiais.

Você pode querer usar 126 a 255 em exit() para significar a mesma coisa que para o $? do shell (como quando um script faz ret=$?; ...; exit "$ret" ). Usando valores fora de 0 - > 255 geralmente não é útil. Em geral, você só faria isso se soubesse que o pai usará a waitid() API em sistemas que não truncam e, por acaso, você precisa do intervalo de 32 bits. Observe que, se você fizer um exit(2048) , por exemplo, isso será visto como um sucesso pelos pais que usam as tradicionais wait*() APIs.

Mais informações em:

O Q & A deve responder à maioria das suas outras perguntas e esclarecer o que significa status de saída . Vou adicionar mais algumas coisas:

Um processo não pode terminar a menos que seja eliminado ou chama as chamadas do sistema _exit() / exit_group() . Quando você retorna de main() em C , a libc chama essa chamada de sistema com o valor de retorno.

A maioria dos idiomas tem uma função exit() que envolve essa chamada de sistema e o valor que eles recebem, se houver, geralmente é passado como é para a chamada do sistema. (note que esses geralmente fazem mais coisas como a limpeza feita pela função exit() do C que libera os buffers stdio, executa os atexit() hooks ...)

Esse é o caso de pelo menos:

$ strace -e exit_group awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group mawk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group busybox awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ echo | strace -e exit_group sed 'Q1234'
exit_group(1234)                        = ?
$ strace -e exit_group perl -e 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group python -c 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group expect -c 'exit 1234'
exit_group(1234)                        = ?
$ strace -e exit_group php -r 'exit(1234);'
exit_group(1234)                        = ?
$ strace -e exit_group zsh -c 'exit 1234'
exit_group(1234)

Você ocasionalmente vê alguns que reclamam quando você usa um valor fora de 0-255:

$ echo 'm4exit(1234)' | strace -e exit_group m4
m4:stdin:1: exit status out of range: '1234'
exit_group(1)                           = ?

Algumas conchas reclamam quando você usa um valor negativo:

$ strace -e exit_group dash -c 'exit -1234'
dash: 1: exit: Illegal number: -1234
exit_group(2)                           = ?
$ strace -e exit_group yash -c 'exit -- -1234'
exit: '-1234' is not a valid integer
exit_group(2)                           = ?

POSIX deixa o comportamento indefinido se o valor passado para o exit especial interno estiver fora de 0- > 255.

Alguns shells mostram alguns comportamentos inesperados se você fizer isso:

  • bash (e mksh mas não pdksh no qual é baseado) assume a tarefa de truncar o valor para 8 bits:

    $ strace -e exit_group bash -c 'exit 1234'
    exit_group(210)                         = ?
    

    Então, nesses shells, se você quiser sair com um valor fora de 0-255, terá que fazer algo como:

    exec zsh -c 'exit -- -12345'
    exec perl -e 'exit(-12345)'
    

    Isso é executar outro comando no mesmo processo que pode chamar a chamada do sistema com o valor desejado.

  • como mencionado em outros Q & A, ksh93 tem o comportamento mais estranho para valores de saída de 257 a 256 + max_signal_number, onde, em vez de chamar exit_group() , ele se mata com o sinal correspondente¹.

    $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    zsh: suspended (signal)  ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    

    e, caso contrário, trunca o número como bash / mksh .

¹ É provável que mude na próxima versão. Agora que o desenvolvimento de ksh93 foi assumido como um esforço da comunidade fora da AT & T, esse comportamento, embora incentivado de alguma forma, por POSIX, está sendo revertido

    
por 22.01.2018 / 10:35
10

O mínimo é 0 e isso é considerado o valor de sucesso. Todos os outros são fracasso. O máximo é 255 , também conhecido como -1 .

Estas regras aplicam-se tanto a scripts como a outros executáveis, bem como a funções da shell.

Valores maiores resultam no módulo 256.

    
por 22.01.2018 / 09:07
5

Isso parece tão simples, mas é um problema.

A linguagem C (e seguindo a maioria dos outros idiomas direta ou indiretamente) requer que retornar de main seja equivalente a chamar exit com o mesmo argumento que o valor de retorno. Este é um número inteiro (o tipo de retorno é muito claramente int ), portanto, em princípio, o intervalo seria INT_MIN to INT_MAX .

No entanto, POSIX declara que somente os 8 bits mais baixos passados para exit serão disponibilizado para um processo pai em espera, literalmente como se fosse "status & 0xFF" .
Portanto, na prática, o código de saída é um inteiro (ainda assinado) do qual apenas os 8 bits mais baixos são definidos.

O mínimo será assim -128 e o máximo 127 . Espere, isso não é verdade. Será 0 a 255.

Mas, infelizmente, é claro que não pode ser assim tão simples . Na prática, o Linux (ou melhor, o bash) faz isso de maneira diferente . O intervalo válido de códigos de retorno é de 0 a 255 (isto é, sem sinal).

Para estar no lado seguro em termos de evitar confusão, provavelmente é uma boa idéia apenas assumir que os códigos de retorno são não assinados, e lançar qualquer coisa que você receber de wait para não assinado. Dessa forma, é consistente com o que você vê em um shell. Como os bits mais altos (incluindo o mais significativo) são apagados, isso nem é "errado" porque, embora seja assinado tecnicamente, os valores reais são sempre não assinados (já que o bit de sinal nunca é definido).
Isso também ajuda a evitar o erro comum de comparar um código de saída com -1 , o que por alguma estranha razão nunca parece aparecer mesmo quando um programa sai com -1 (bem, adivinhe porquê!).

Sobre o seu último ponto, retornando de uma função, se essa função for main , veja acima. Caso contrário, depende de qual é o tipo de retorno da função, poderia, em princípio, ser qualquer coisa (incluindo void ).

    
por 23.01.2018 / 11:46
2
  1. The exit code returned from a binary executable (for example: a C program).
  2. The exit code returned from a bash script (when calling exit).

Os códigos de saída de qualquer processo - seja um executável binário, um script de shell ou qualquer outra coisa - variam de 0 a 255. É possível passar um valor maior para exit() , mas apenas os 8 bits inferiores de o status é disponibilizado para outros processos através de wait() .

  1. The exit code returned from a function (when calling return). I think this is between 0 and 255.

Uma função C pode ser declarada como retornando quase qualquer tipo. Os limites de seu valor de retorno são determinados inteiramente por esse tipo: por exemplo, -128 a 127 para uma função retornando signed char , ou 0 a 4.2 bilhões para uma função retornando unsigned int , ou qualquer número de ponto flutuante até e incluindo inf para uma função que retorna double . E isso não está contando os tipos não numéricos, como void * ou struct ...

    
por 23.01.2018 / 05:17