De acordo com a resposta de Matteo Italia :
Doing the same experiment with killall, instead, usually yields the "killed" message immediately, sign that the time/context switches/whatever required to execute an external command cause a delay long enough for the process to be killed before the control returns to the shell.
Em outras palavras, o atraso causado pela chamada do /bin/true
externo causa um atraso, o que permite ao shell imprimir a mensagem.
Eu também realizei testes com /bin/echo
vs echo
:
#!/bin/bash
if [[ -n "$1" ]]; then
sleep 1 &
p=$!
kill $p &> /dev/null
/bin/echo "a line"
else
sleep 1 &
p=$!
kill $p &> /dev/null
fi
Com este script:
$ bash ./mystery.sh
$ bash ./mystery.sh foo
a line
./mystery.sh: line 11: 10361 Terminated sleep 1
com echo
:
$ bash ./mystery.sh
$ bash ./mystery.sh foo
a line
Em outras palavras, o fato de haver um executável externo sendo chamado, força o shell a executar a verificação de processos filhos e trabalhos em segundo plano quando o último filho retornar. Em caso de:
if [[ -n "$1" ]]; then
sleep 1 &
p=$!
kill $p &> /dev/null
do seu script original, não há comando extra sendo chamado, apenas o último construído.
Entre outras coisas, realizei alguns testes com strace
:
Parece que o processo pai sai e não espera pela criança. Em outras palavras, o processo pai do shell sai muito cedo para executar uma verificação explícita.
$ strace -s 1024 -e kill bash mystery.sh
kill(9830, SIGTERM) = 0
mystery.sh: line 11: 9830 Terminated sleep 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=9830, si_uid=1000, si_status=SIGTERM, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
$ strace -s 1024 -e kill bash mystery.sh foo
kill(9839, SIGTERM) = 0
+++ exited with 0 +++
Notadamente, no rastreamento com parâmetro posicional, a chamada de espera também está ausente:
$ strace -s 1024 -e kill,wait4 bash mystery.sh foo
kill(9910, SIGTERM) = 0
+++ exited with 0 +++
$ strace -s 1024 -e kill,wait4 bash mystery.sh
kill(9916, SIGTERM) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=9916, si_uid=1000, si_status=SIGTERM, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], WNOHANG, NULL) = 9916
wait4(-1, 0x7ffe8e5bb110, WNOHANG, NULL) = -1 ECHILD (No child processes)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9917
mystery.sh: line 11: 9916 Terminated sleep 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffe8e5bb250, WNOHANG, NULL) = -1 ECHILD (No child processes)
+++ exited with 0 +++