O script Bash não vê SIGHUP?


11

Eu tenho o seguinte script:

#!/bin/bash
echo "We are $$"
trap "echo HUP" SIGHUP
cat    # wait indefinitely

Quando envio SIGHUP(usando kill -HUP pid), nada acontece.

Se eu mudar um pouco o script:

#!/bin/bash
echo "We are $$"
trap "kill -- -$BASHPID" EXIT    # add this
trap "echo HUP" SIGHUP
cat    # wait indefinitely

... então o script faz a echo HUPcoisa certa quando sai (quando pressiono Ctrl + C):

roger@roger-pc:~ $ ./hupper.sh 
We are 6233
^CHUP

O que está acontecendo? Como devo enviar um sinal (não necessariamente precisa ser SIGHUP) para esse script?


4
O sinal será entregue e o manipulador de sinal será executado quando o catprocesso terminar. Experimente o seu script original e pressione Ctrl+Dpara sair do catprocesso. Enquanto o catprocesso estiver em primeiro plano, o HUPsinal não será acionado. Tente novamente com catsubstituído por read(um shell interno).
— Kusalananda

Perfeito. Alguém gosta de transformar isso em resposta?
— Roger Lipscombe

Sei que funciona dessa maneira, mas deixarei alguém que tenha mais discernimento do que eu nos porquês e por onde fazer a resposta.
— Kusalananda

Eu usei while true; do read; doneno final, caso contrário, a inserção de texto também fará com que ele saia e quero que saia em Ctrl + C.
— Roger Lipscombe

Respostas:


21

O manual do Bash declara:

Se o bash estiver aguardando a conclusão de um comando e receber um sinal para o qual uma captura foi configurada, a captura não será executada até que o comando seja concluído.

Isso significa que, apesar do sinal ser recebido bashquando você o envia, sua armadilha no SIGHUP será chamada apenas quando catterminar.

Se esse comportamento for indesejável, use bashbuiltins (por exemplo, read+ printfem um loop em vez de cat) ou use trabalhos em segundo plano (consulte a resposta de Stéphane ).


9

O @xhienne já explicou o motivo , mas se você deseja que o sinal atue imediatamente (e não saia do script), você pode alterar seu código para:

#! /bin/bash -
interrupted=true
trap 'interrupted=true; echo HUP' HUP

{ cat <&3 3<&- & pid=$!; } 3<&0

while
  wait "$pid"
  ret=$?
  "$interrupted"
do
  interrupted=false
done
exit "$ret"

A pequena dança dos descritores de arquivo é contornar o fato de que o bashredirecionamento do stdin é /dev/nullpara comandos iniciados em segundo plano.


Isso funciona porque o bloco de código é executado em um subshell?
— Pysis 23/08/17
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.