Script Bash tidak melihat SIGHUP?

11

Saya punya skrip berikut:

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

Ketika saya mengirim SIGHUP(menggunakan kill -HUP pid), tidak ada yang terjadi.

Jika saya mengubah sedikit skrip:

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

... lalu skrip melakukan echo HUPhal yang benar saat keluar (ketika saya menekan Ctrl + C):

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

Apa yang sedang terjadi? Bagaimana saya harus mengirim sinyal (tidak harus SIGHUP) ke skrip ini?

Roger Lipscombe
sumber
4
Sinyal akan dikirim dan penangan sinyal akan mengeksekusi ketika catproses selesai. Coba skrip asli Anda dan tekan Ctrl+Duntuk membuat catproses keluar. Sementara catproses berada di latar depan, HUPsinyal tidak ditindaklanjuti. Coba lagi dengan catdiganti oleh read(built-in shell).
Kusalananda
Sempurna. Apakah seseorang suka mengubahnya menjadi jawaban?
Roger Lipscombe
Saya tahu itu bekerja seperti itu, tetapi saya akan membiarkan seseorang yang memiliki lebih banyak wawasan daripada saya ke dalam mengapa dan di mana jawabannya.
Kusalananda
Saya menggunakan while true; do read; donepada akhirnya, jika tidak memasukkan teks menyebabkannya berhenti juga, dan saya ingin itu berhenti pada Ctrl + C.
Roger Lipscombe

Jawaban:

21

Manual Bash menyatakan:

Jika bash sedang menunggu perintah untuk menyelesaikan dan menerima sinyal yang telah ditetapkan jebakan, jebakan tidak akan dieksekusi sampai perintah selesai.

Itu berarti bahwa meskipun sinyal diterima bashketika Anda mengirimkannya, jebakan Anda pada SIGHUP hanya akan dipanggil saat catberakhir.

Jika perilaku ini tidak diinginkan, maka gunakan bashbuiltin (misal read+ printfdalam lingkaran alih-alih cat) atau gunakan pekerjaan latar belakang (lihat jawaban Stéphane ).

xienne
sumber
9

@xhienne telah menjelaskan alasannya , tetapi jika Anda ingin agar sinyal langsung bekerja (dan tidak keluar dari skrip), Anda dapat mengubah kode Anda menjadi:

#! /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"

Tarian kecil dengan deskriptor file adalah untuk mengatasi kenyataan bahwa bashpengalihan stdin ke /dev/nulluntuk perintah diluncurkan di latar belakang.

Stéphane Chazelas
sumber
Apakah ini berhasil karena blok kode berjalan dalam subkulit?
Pysis