Os processos podem chamar a chamada do _exit()sistema (no Linux, consulte também exit_group()) com um argumento inteiro para relatar um código de saída ao pai. Embora seja um número inteiro, apenas os 8 bits menos significativos estão disponíveis para o pai (a exceção é quando se usa waitid()ou manipula SIGCHLD no pai para recuperar esse código , embora não no Linux).
O pai normalmente faz um wait()ou waitpid()para obter o status de seu filho como um número inteiro (embora também waitid()possa ser usada uma semântica um pouco diferente).
No Linux e na maioria dos Unices, se o processo terminar normalmente, os bits 8 a 15 desse número de status conterão o código de saída conforme passado exit(). Caso contrário, os 7 bits menos significativos (0 a 6) conterão o número do sinal e o bit 7 será definido se um núcleo for despejado.
perl, $?por exemplo, contém esse número, conforme definido por waitpid():
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Os shells tipo Bourne também fazem o status de saída do último comando de execução em sua própria $?variável. No entanto, ele não contém diretamente o número retornado por waitpid(), mas uma transformação e é diferente entre os shells.
O que é comum entre todos os shells é que $?contém os 8 bits mais baixos do código de saída (o número passado para exit()) se o processo terminar normalmente.
A diferença é quando o processo é finalizado por um sinal. Em todos os casos, e isso é exigido pelo POSIX, o número será maior que 128. O POSIX não especifica qual pode ser o valor. Na prática, porém, em todas as conchas semelhantes a Bourne que eu conheço, os 7 bits mais baixos $?conterão o número do sinal. Mas, onde nestá o número do sinal,
em ash, zsh, pdksh, bash, a concha Bourne, $?é 128 + n. O que isto significa é que nessas conchas, se você receber um $?dos 129, você não sabe se é porque o processo foi encerrado com exit(129)ou se ele foi morto pelo sinal 1( HUPna maioria dos sistemas). Mas a lógica é que os shells, quando saem por si mesmos, por padrão, retornam o status de saída do último comando encerrado. Ao garantir que $?nunca seja maior que 255, isso permite ter um status de saída consistente:
$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
bash: line 1: 16720 Terminated sh -c "kill \$\$"
8f # 128 + 15
$ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
bash: line 1: 16726 Terminated sh -c "kill \$\$"
8f # here that 0x8f is from a exit(143) done by bash. Though it's
# not from a killed process, that does tell us that probably
# something was killed by a SIGTERM
ksh93, $?É 256 + n. Isso significa que, a partir de um valor, $?você pode diferenciar entre um processo morto e não morto. As versões mais recentes de ksh, na saída, se $?eram maiores que 255, se matam com o mesmo sinal para poder relatar o mesmo status de saída ao pai. Embora isso pareça uma boa ideia, isso significa que kshirá gerar um despejo de núcleo extra (potencialmente substituindo o outro) se o processo for interrompido por um sinal de geração de núcleo:
$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
ksh: 16828: Terminated
10f # 256 + 15
$ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?"
ksh: 16816: Illegal instruction(coredump)
Illegal instruction(coredump)
104 # 256 + 15, ksh did indeed kill itself so as to report the same
# exit status as sh. Older versions of `ksh93` would have returned
# 4 instead.
Onde você pode até dizer que há um bug é que se ksh93mata mesmo que $?provenha de return 257uma função:
$ ksh -c 'f() { return "$1"; }; f 257; exit'
zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit'
# ksh kills itself with a SIGHUP so as to report a 257 exit status
# to its parent
yash. yashoferece um compromisso. Retorna 256 + 128 + n. Isso significa que também podemos diferenciar entre um processo morto e um que terminou corretamente. E ao sair, será relatado 128 + nsem ter que se suicidar e os efeitos colaterais que pode ter.
$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
18f # 256 + 128 + 15
$ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
8f # that's from a exit(143), yash was not killed
Para obter o sinal do valor de $?, a maneira portátil é usar kill -l:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(para portabilidade, você nunca deve usar números de sinal, apenas nomes de sinal)
Nas frentes não Bourne:
csh/ tcshe o fishmesmo que o shell Bourne, exceto que o status está em $statusvez de $?(observe que zshtambém define $statuscompatibilidade com csh(além de $?)).
rc: o status de saída $statustambém está, mas quando morto por um sinal, essa variável contém o nome do sinal (como sigtermou sigill+corese um núcleo foi gerado) em vez de um número, que é mais uma prova do bom design desse shell .
es. o status de saída não é uma variável. Se você se importa com isso, execute o comando como:
status = <={cmd}
que retornará um número sigtermou sigsegv+coreigual a rc.
Talvez para a completude, devemos mencionar zsh's $pipestatuse bash' s $PIPESTATUSmatrizes que contêm o status de saída dos componentes do último pipeline.
E também para completar, quando se trata de funções de shell e arquivos de origem, as funções padrão retornam com o status de saída do último comando executado, mas também podem definir um status de retorno explicitamente com o returnbuiltin. E vemos algumas diferenças aqui:
bashe mksh(desde R41, uma regressão ^ aparentemente alterada intencionalmente ) truncará o número (positivo ou negativo) para 8 bits. Assim, por exemplo, return 1234será definido $?como 210, return -- -1será definido $?como 255.
zshe pdksh(e derivadas que não sejam mksh) permitem qualquer número inteiro decimal de 32 bits assinado (-2 31 a 2 31 -1) (e truncar o número para 32 bits ).
ashe yashpermita qualquer número inteiro positivo de 0 a 2 31 -1 e retorne um erro para qualquer número desse valor.
ksh93para return 0a return 320set $?como é, mas para qualquer outra coisa, truncado para 8 bits. Cuidado, como já mencionado, que retornar um número entre 256 e 320 pode causar o kshsuicídio ao sair.
rce espermitir retornar qualquer coisa par.
Observe também que alguns shells também usam valores especiais de $?/ $statuspara relatar algumas condições de erro que não são o status de saída de um processo, como 127ou 126para comando não encontrado ou não executável (ou erro de sintaxe em um arquivo de origem) ...
killall myScriptobras, portanto, o retorno do killall (e não do script!) é 0. Você pode colocar umkill -x $$[x sendo o número do sinal e $$ geralmente expandido pelo shell para o PID do script (funciona em sh, bash, ...)] dentro do script e teste o que era seu núcleo de saída.