Recentemente, deparei-me com esta lista de códigos de saída com significados especiais do Advanced Bash-Scripting Guide. Eles se referem a esses códigos como reservados e recomendam que:
De acordo com a tabela acima, os códigos de saída 1-2, 126-165 e 255 têm significados especiais e, portanto, devem ser evitados para parâmetros de saída especificados pelo usuário.
Há um tempo atrás, escrevi um script que usava os seguintes códigos de status de saída:
- 0 - sucesso
- 1 - nome de host incorreto
- 2 - argumentos inválidos especificados
- 3 - privilégios de usuário insuficientes
Quando escrevi o script, não tinha conhecimento de nenhum código de saída especial, então comecei em 1 para a primeira condição de erro e incrementei o status de saída para cada tipo de erro sucessivo.
Escrevi o script com a intenção de que, posteriormente, ele pudesse ser chamado por outros scripts (que poderiam verificar códigos de saída diferentes de zero). Ainda não fiz isso; até agora, eu apenas executei o script do meu shell interativo (Bash) e fiquei imaginando o que / ou algum problema poderia ser causado usando meus códigos de saída personalizados. Quão relevante / importante é a recomendação do Advanced Bash-Scripting Guide?
Não encontrei nenhum conselho que comprove a documentação do Bash; sua seção no Status da saída simplesmente lista os códigos de saída usados pelo Bash, mas não afirma que nenhum deles está reservado ou avisa sobre o uso deles para seus próprios scripts / programas.
fonte
Respostas:
Houve várias tentativas de padronizar os significados dos códigos de saída do processo. Além do que você mencionou, eu sei:
os BSDs possuem o
sysexits.h
que define significados para valores de 64 em diante.Os
grep
documentos GNU que encerram o código 0 significam que pelo menos uma correspondência foi encontrada, 1 significa que nenhuma correspondência foi encontrada e 2 significa que ocorreu um erro de E / S; obviamente, essa convenção também é útil para outros programas para os quais a diferença entre "nada deu errado, mas eu não encontrei nada" e "ocorreu um erro de E / S" é significativa.Muitas implementações da função de biblioteca C
system
usam o código de saída 127 para indicar que o programa não existe ou falhou ao iniciar.No Windows, os
NTSTATUS
códigos (que estão espalhados de maneira inconveniente por todo o espaço numérico de 32 bits) podem ser usados como códigos de saída, particularmente aqueles que indicam que um processo foi encerrado devido a um mau comportamento catastrófico (por exemploSTATUS_STACK_OVERFLOW
).Você não pode contar com nenhum programa que obedeça a uma dessas convenções em particular. A única regra confiável é que o código de saída 0 seja bem-sucedido e qualquer outra coisa seja algum tipo de falha. (Observe que não
EXIT_SUCCESS
é garantido que o C89 tenha o valor zero; no entanto, é necessário que ele se comporte de maneira idêntica, mesmo que os valores não sejam os mesmos.)exit(0)
exit(EXIT_SUCCESS)
fonte
Nenhum código de saída tem um significado especial, mas o valor em
$?
pode ter um significado especial.A maneira como o Bourne Shell e o ksh93 manipularam e encaminharam códigos de saída e situações de erro para a variável do shell
$?
é o problema. Ao contrário do que você lista, apenas os seguintes valores para$?
têm um significado especial:Além disso, existe um shell não especificado e um intervalo de
$?
códigos específico da plataforma > 128 reservado para um programa que foi interrompido por um sinal:Outros valores não apresentam problemas, pois podem ser diferenciados dos
$?
valores especiais do shell .Em particular, os valores 1 e 2 não são usados para condições especiais, mas são apenas códigos de saída usados por comandos internos que podem agir da mesma maneira quando não há elementos internos. Parece que o ponteiro para o guia de scripts do bash que você forneceu não é um bom manual, pois apenas lista os códigos usados pelo bash sem comentar se um código específico é um valor especial que deve ser evitado para os próprios scripts.
Versões mais recentes do Bourne Shell usam em
waitid()
vez dewaitpid()
aguardar a saída do programa ewaitid()
(introduzido em 1989 no SVr4) usam uma interface syscall melhor (semelhante ao que o UNOS já usava em 1980).Como as versões mais recentes do Bourne Shell codificam o motivo da saída em uma variável separada
${.sh.code}
/${.sh.codename}
do código de saída que está em${.sh.status}
/${.sh.termsig}
, consulte http://schillix.sourceforge.net/man/man1/bosh.1.html , o código de saída não está sobrecarregado com estados especiais e, como resultado do uso de `waitid (), o Bourne Shell agora suporta o retorno de todos os 32 bits do código de saída - não apenas dos baixos 8 bits.BTW: tenha cuidado para não ser
exit(256)
semelhante a um programa C ou script de shell, pois isso resulta em$?
ser interpretado como 0 em um shell clássico.fonte
waitid()
bug no final de maio. O pessoal do FreeBSD resolveu o problema em 20 horas, o pessoal do Linux não está interessado em corrigir o erro. ... e as pessoas Cygwin diz que eles são bug pelo bug Linux compatível ;-)_exit
. Por favor, vincule o relatório de bug do FreeBSD ao qual você está se referindo, talvez eu esteja entendendo mal o problema que você descreve.${.sh.}
variáveis. É verdade, no entanto, que você diz "Bourne" e não "derivado de Bourne" (embora você inclua ksh93)./bin/sh
pode confiar para se comportar de forma consistente com esses códigos de saída especiais em várias plataformas, o que não é verdade. (Eu não me importo se um sistema em particular/bin/sh
possa ser considerado um "shell Bourne real". Muito mais importante saber que nada disso está no POSIX e que a maioria das coisas que você cita como "sistemas Unix reais" não t fornecer um compatível com POSIX/bin/sh
de qualquer maneira).Para scripts de shell, às vezes eu in-source o equivalente a shell
sysexist.h
com códigos de saída reservados à shell (prefixados comS_EX_
), que chamei deexit.sh
É basicamente:
E pode ser gerado com:
Porém, eu não uso muito, mas o que eu uso é uma função shell que inverte códigos de erro em seus formatos de string. Eu o nomeei
exit2str
. Supondo que você tenha nomeado oexit.sh
gerador acimaexit.sh.sh
, o código paraexit2str
pode ser gerado com (exit2str.sh.sh
):Eu uso isso no
PS1
meu shell interativo para que, após cada comando executado, eu possa ver seu status de saída e seu formato de string (se ele tiver um formato de string conhecido):Para obtê-los, você precisa de um insourcable para a função exit2str:
e use-o no seu
~/.bashrc
para salvar e traduzir o código de saída em cada prompt de comando e exibir seu prompt (PS1
):É bastante útil para observar como alguns programas seguem as convenções de código de saída e outros não, para aprender sobre convenções de código de saída ou apenas para poder ver o que está acontecendo mais rapidamente. Depois de usá-lo há algum tempo, posso dizer que muitos scripts shell orientados ao sistema seguem as convenções.
EX_USAGE
é particularmente bastante comum, embora outros códigos, não muito. Eu tento seguir as convenções de tempos em tempos, embora sempre exista$S_EX_ANY
(1) pessoas preguiçosas (eu sou uma).fonte
Contanto que você documente seus códigos de saída para lembrá-los daqui a um ano, quando precisar voltar e ajustar o script, tudo ficará bem. A idéia de "códigos de saída reservados" não se aplica mais do que dizer que é habitual usar
0
como código de sucesso e qualquer outra coisa como código de falha.fonte
A melhor referência que pude encontrar foi esta: http://tldp.org/LDP/abs/html/exitcodes.html
De acordo com isso:
1
é uma regra geral para erros, e sempre o vi usado para erros definidos pelo usuário.2
é para uso indevido de shell built ins, como um erro de sintaxePara responder sua pergunta diretamente, seu script funcionará bem usando os códigos de erro reservados, ele funcionará como esperado, supondo que você lide com o erro com base no código de erro = 1/2/3.
No entanto, seria confuso se você encontrar alguém que conhece e usa os códigos de erro reservados, o que parece bastante raro.
Outra opção disponível é repetir o erro se houver um e depois sair, assumindo que o script segue a convenção do Linux de "nenhuma notícia é boa notícia" e o eco não é nada de sucesso.
fonte
Com base nas respostas que recebi (foi difícil escolher uma sobre as outras), não é prejudicial indicar certos tipos de erros usando um código de saída que o Bash também usa. O Bash (ou qualquer outro shell Unix) não fará nada de especial (como executar manipuladores de exceção) se um script de usuário sair com um desses códigos de erro.
Parece que o autor do Advanced Bash-Scripting Guide concorda com as tentativas do BSD de padronizar os códigos de saída (
sysexits.h
) e está simplesmente recomendando que, quando os usuários escrevam scripts shell, eles não especifiquem códigos de saída que já entrem em conflito com códigos de saída predefinidos. em uso, ou seja, eles restringem seus códigos de saída personalizados aos 50 códigos de status disponíveis no intervalo de 64 a 113.Aprecio a idéia (e a justificativa), mas eu preferiria que o autor fosse mais explícito que não é prejudicial ignorar o conselho - exceto nos casos em que o consumidor de um script está verificando erros, como o exemplo citado de 127 (
command not found
)Especificações POSIX relevantes
Pesquisei o que o POSIX tem a dizer sobre códigos de saída e a especificação do POSIX parece concordar com o autor do Advanced Bash-Scripting Guide. Citei as especificações POSIX relevantes (ênfase minha):
Status de saída para comandos
O
exit
utilitárioOutras informações
Pelo que vale, pude verificar tudo, exceto um da lista de códigos de saída com significados especiais . Esta tabela de códigos de saída é útil, pois fornece mais detalhes - e exemplos de como gerar os códigos de erro documentados na referência do bash .
Tentativa de gerar o status de saída 128
Usando as versões 3.2.25 e 4.2.46 do Bash, tentei gerar um
128 Invalid argument to exit
erro, mas sempre que recebia um 255 (status de saída fora do intervalo). Por exemplo, seexit 3.14159
for executado como parte de um script de shell ou em um shell filho interativo, o shell será encerrado com um código de255
:Para ainda mais diversão, eu também tentei executar um programa C simples, mas neste caso, parece que a
exit(3)
função simplesmente converteu o float em int (3 neste caso) antes de sair:fonte