Los procesos pueden llamar a la llamada del _exit()
sistema (en Linux, ver también exit_group()
) con un argumento entero para informar un código de salida a su padre. Aunque es un número entero, solo los 8 bits menos significativos están disponibles para el padre (la excepción es cuando se usa waitid()
o maneja en SIGCHLD en el padre para recuperar ese código , aunque no en Linux).
El padre generalmente hará un wait()
o waitpid()
para obtener el estado de su hijo como un entero (aunque también waitid()
se puede usar una semántica algo diferente).
En Linux y en la mayoría de los Unices, si el proceso finalizó normalmente, los bits 8 a 15 de ese número de estado contendrán el código de salida que se le pasó exit()
. De lo contrario, los 7 bits menos significativos (0 a 6) contendrán el número de señal y el bit 7 se establecerá si se volcó un núcleo.
perl
's, $?
por ejemplo, contiene ese número establecido 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
Los shells tipo Bourne también hacen que el estado de salida del último comando de ejecución en su propia $?
variable. Sin embargo, no contiene directamente el número devuelto por waitpid()
, sino una transformación, y es diferente entre los shells.
Lo que es común entre todos los shells es que $?
contiene los 8 bits más bajos del código de salida (el número pasado exit()
) si el proceso terminó normalmente.
Donde difiere es cuando el proceso termina con una señal. En todos los casos, y eso es requerido por POSIX, el número será mayor que 128. POSIX no especifica cuál puede ser el valor. Sin embargo, en la práctica, en todos los shells tipo Bourne que conozco, los 7 bits más bajos $?
contendrán el número de señal. Pero, ¿dónde n
está el número de señal?
en ash, zsh, pdksh, bash, el shell Bourne, $?
es 128 + n
. Lo que eso significa es que en esos proyectiles, si obtienes uno $?
de 129
, no sabes si es porque el proceso salió exit(129)
o si la señal lo mató 1
( HUP
en la mayoría de los sistemas). Pero la razón es que los shells, cuando salen ellos mismos, por defecto devuelven el estado de salida del último comando salido. Al asegurarse de $?
que nunca sea mayor que 255, eso permite tener un estado de salida 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
, $?
Es 256 + n
. Eso significa que a partir de un valor de $?
usted puede diferenciar entre un proceso muerto y no muerto. Las versiones más nuevas de ksh
, al salir, si $?
eran superiores a 255, se suicidan con la misma señal para poder informar el mismo estado de salida a su padre. Si bien eso suena como una buena idea, eso significa que ksh
generará un volcado de núcleo adicional (posiblemente sobrescribiendo el otro) si el proceso fue eliminado por una señal generadora 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.
Donde incluso podría decir que hay un error es que se ksh93
suicida incluso si $?
proviene de una función return 257
realizada por:
$ 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
. yash
ofrece un compromiso Vuelve 256 + 128 + n
. Eso significa que también podemos diferenciar entre un proceso cancelado y uno que finalizó correctamente. Y al salir, informará 128 + n
sin tener que suicidarse y los efectos secundarios que puede tener.
$ 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 obtener la señal del valor de $?
, la forma portátil es usar kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(para portabilidad, nunca debe usar números de señal, solo nombres de señal)
En los frentes no Bourne:
csh
/ tcsh
e fish
igual que el shell Bourne, excepto que el estado está en $status
lugar de $?
(tenga en cuenta que zsh
también establece la $status
compatibilidad con csh
(además de $?
)).
rc
: El estado de salida está en $status
también, pero cuando matado por una señal, dicha variable contiene el nombre de la señal (como sigterm
o sigill+core
si se generó un núcleo) en lugar de un número, que es otra prueba del diseño bien de que shell .
es
. El estado de salida no es una variable. Si te importa, ejecutas el comando como:
status = <={cmd}
que devolverá un número sigterm
o me sigsegv+core
gusta en rc
.
Tal vez para completar, deberíamos mencionar zsh
las matrices 's $pipestatus
y bash
' $PIPESTATUS
que contienen el estado de salida de los componentes de la última tubería.
Y también para completar, cuando se trata de funciones de shell y archivos de origen, las funciones por defecto regresan con el estado de salida del último comando ejecutado, pero también pueden establecer un estado de retorno explícitamente con el return
incorporado. Y vemos algunas diferencias aquí:
bash
y mksh
(desde R41, una regresión ^ Wchange aparentemente introducida intencionalmente ) truncará el número (positivo o negativo) a 8 bits. Entonces, por ejemplo, return 1234
se establecerá $?
en 210
, return -- -1
se establecerá $?
en 255.
zsh
y pdksh
(y derivados distintos de mksh
) permiten cualquier entero decimal con signo de 32 bits (-2 31 a 2 31 -1) (y truncan el número a 32 bits).
ash
y yash
permitir cualquier número entero positivo de 0 a 2 31 -1 y devolver un error para cualquier número de eso.
ksh93
para return 0
al return 320
conjunto $?
como es, pero para cualquier otra cosa, truncado a 8 bits. Tenga en cuenta, como ya se mencionó, que devolver un número entre 256 y 320 podría causar la ksh
muerte al salir.
rc
y es
permitir devolver cualquier cosa, incluso listas.
También tenga en cuenta que algunos shells también usan valores especiales de $?
/ $status
para informar algunas condiciones de error que no son el estado de salida de un proceso, como 127
o 126
para el comando no encontrado o no ejecutable (o error de sintaxis en un archivo de origen) ...
killall myScript
trabajos, por lo tanto, el retorno del killall (¡y no del script!) es 0. Podría colocar unkill -x $$
[x como el número de señal, y $$ generalmente expandido por el shell al PID de ese script (funciona en sh, bash, ...)] dentro del script y luego pruebe cuál era su núcleo de salida.