O shell usado é uma preocupação, pois shells diferentes lidam com o controle de tarefas de maneira diferente (e o controle de tarefas é complicado; job.c
in bash
atualmente pesa 3.300 linhas de C de acordo com cloc
). pdksh
5.2.14 versus bash
3.2 no Mac OS X 10.11 por exemplo show:
$ cat code
pkill yes
yes >/dev/null &
pid=$!
echo $pid
sleep 2
kill -INT $pid
sleep 2
pgrep yes
$ bash code
38643
38643
$ ksh code
38650
$
Também relevante aqui é que yes
não executa manipulação de sinais, portanto, herda o que houver para ser herdado do processo de shell pai; se, ao contrário, fizermos o manuseio do sinal -
$ cat sighandlingcode
perl -e '$SIG{INT} = sub { die "ouch\n" }; sleep 5' &
pid=$!
sleep 2
kill -INT $pid
$ bash sighandlingcode
ouch
$ ksh sighandlingcode
ouch
$
- o SIGINT é acionado independentemente do shell pai, já que perl
aqui, ao contrário de yes
, alterou o tratamento do sinal. Existem chamadas de sistema relevantes para o tratamento de sinais que podem ser observadas com coisas como o DTrace ou aqui strace
no Linux:
-bash-4.2$ cat code
pkill yes
yes >/dev/null &
pid=$!
echo $pid
sleep 2
kill -INT $pid
sleep 2
pgrep yes
pkill yes
-bash-4.2$ rm foo*; strace -o foo -ff bash code
21899
21899
code: line 9: 21899 Terminated yes > /dev/null
-bash-4.2$
Descobrimos que o processo yes
termina com SIGINT
ignorado:
-bash-4.2$ egrep 'exec.*yes' foo.21*
foo.21898:execve("/usr/bin/pkill", ["pkill", "yes"], [/* 24 vars */]) = 0
foo.21899:execve("/usr/bin/yes", ["yes"], [/* 24 vars */]) = 0
foo.21903:execve("/usr/bin/pgrep", ["pgrep", "yes"], [/* 24 vars */]) = 0
foo.21904:execve("/usr/bin/pkill", ["pkill", "yes"], [/* 24 vars */]) = 0
-bash-4.2$ grep INT foo.21899
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f18ebee0250}, {SIG_DFL, [], SA_RESTORER, 0x7f18ebee0250}, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f18ebee0250}, {SIG_DFL, [], SA_RESTORER, 0x7f18ebee0250}, 8) = 0
rt_sigaction(SIGINT, {SIG_IGN, [], SA_RESTORER, 0x7f18ebee0250}, {SIG_DFL, [], SA_RESTORER, 0x7f18ebee0250}, 8) = 0
--- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=21897, si_uid=1000} ---
-bash-4.2$
Repita este teste com o código perl
e deve-se ver que SIGINT
não é ignorado, ou também que sob pdksh
não há nenhum ignorar sendo definido como em bash
. Com o "modo monitor" ativado como está no modo interativo em bash
, yes
é eliminado.
-bash-4.2$ cat monitorcode
#!/bin/bash
set -m
pkill yes
yes >/dev/null &
pid=$!
echo $pid
sleep 2
kill -INT $pid
sleep 2
pgrep yes
pkill yes
-bash-4.2$ ./monitorcode
22117
[1]+ Interrupt yes > /dev/null
-bash-4.2$