Para o
bash /bin/sleep 3 0
podemos observar isso com strace
$ strace -f -e trace=process bash -c 'sleep 1'
execve("/usr/bin/bash", ["bash", "-c", "sleep 1"], [/* 22 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7ffff7fe3740) = 0
execve("/usr/bin/sleep", ["sleep", "1"], [/* 22 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7ffff7fe3740) = 0
exit_group(0) = ?
+++ exited with 0 +++
$
que, sem nenhum sinal TERM
, mostra que bash
se substitui por sleep
; por contraste, o composto true;sleep 3
form mostrará um clone
(se no Linux), já que bash
irá forçar o sleep
e manipular o código de saída.
Com um SIGTERM
envolvido, vemos:
$ strace -f -e trace=process bash -c 'sleep 999'
execve("/usr/bin/bash", ["bash", "-c", "sleep 999"], [/* 22 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7ffff7fe3740) = 0
execve("/usr/bin/sleep", ["sleep", "999"], [/* 22 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7ffff7fe3740) = 0
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=3896, si_uid=0} ---
+++ killed by SIGTERM +++
$ echo $?
143
$
Isso nos leva ao código Perl, que é incorreto; em Perl $?
representa a palavra de status de 16 bits de wait(2)
, e não qualquer valor que um shell tenha manipulado essa palavra de status de 16 bits. Seu print $?>>8
imprime somente as informações do código de saída, que para um sinal é de fato 0. Se, em vez disso, uma inspeção correta do conteúdo de $?
for usada:
#!/usr/bin/env perl
use 5.14.0;
use warnings;
use IPC::Open3 qw(open3);
my ( $input, $output, $err );
open3( $input, $output, $err, qw(bash -c), "sleep 999" );
wait;
if ( $? == -1 ) {
say "noexec $!";
} elsif ( $? & 127 ) {
printf "died signal=%d core=%s\n",
( $? & 127 ), ( $? & 128 ) ? 'yea' : 'nay';
} else {
say "exit ", $? >> 8;
}
Em seguida, o Perl apresentará um relatório para o caso de bash -c 'sleep 3'
kill corretamente:
$ perl ipcopenfoo
died signal=15 core=nay
$