(Jika Anda hanya memiliki nomor sinyal dan menginginkan namanya, kill -l $SIGNAL_NUM
mencetak nama sinyal; Anda dapat menghindarinya dengan menggunakan nama sinyal alih-alih angka dalam panggilan Anda ke trap
seperti di bawah ini.)
Jawaban ini mengatakan bahwa tidak ada cara untuk mengakses nama sinyal, tetapi jika Anda memiliki fungsi terpisah untuk setiap sinyal yang Anda jebak, maka Anda sudah mengetahui nama sinyalnya:
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
Dalam banyak kasus, itu mungkin cukup, tetapi jawaban lain untuk pertanyaan yang sama menggunakan fakta itu untuk memberikan solusi untuk memalsukan perilaku yang Anda inginkan. Dibutuhkan fungsi dan daftar sinyal dan menetapkan jebakan terpisah untuk setiap sinyal pada fungsi yang disebut dengan nama sinyal, jadi secara internal sebenarnya fungsi terpisah untuk setiap sinyal tetapi terlihat seperti jebakan tunggal pada satu fungsi yang mendapatkan nama sinyal sebagai argumen:
Kode:
#!/bin/bash
trap_with_arg() {
func="$1" ; shift
for sig ; do
trap "$func $sig" "$sig"
done
}
func_trap() {
echo "Trapped: $1"
}
trap_with_arg func_trap INT TERM EXIT
echo "Send signals to PID $$ and type [enter] when done."
read # Wait so the script doesn't exit.
Jika saya menjalankannya, maka saya dapat mengirim sinyal ke proses dan saya mendapatkan output seperti
Trapped: INT
Trapped: TERM
Trapped: EXIT
Mengacu pada $?
solusi di atas:$?
akan mencerminkan kode keluar dari perintah yang terakhir dieksekusi. Pertimbangkan ini:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
Jika Anda menjalankan ini dan menekan Ctrl-C , itu akan mencetak CODE: 130
. Itu karena sleep
executable terganggu oleh SIGINT dan keluar dengan kode itu.
Bandingkan dengan:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
Jika Anda menjalankan ini dan tekan Ctrl-C , itu akan mencetak CODE: 0
, mungkin karena read
perintah adalah bawaan dan aturan kode keluar berbeda (hal yang sama terjadi jika Anda akan menginterupsi while : ; do : ; done
).
Jadi, $?
hanya memberi tahu Anda tentang sinyal jika mengganggu perintah eksternal, dan jika program tertentu itu tidak menangkap sinyal dan keluar dengan kode keluarnya sendiri. Intinya adalah skrip bash di atas:setelah menerima SIGINT, ia akan keluar dengan kode 1
, bukan 130
.
Di dalam jebakan (ketika dipicu melalui sinyal), $? variabel awalnya disetel ke nomor sinyal ditambah 128, sehingga Anda dapat menetapkan nomor sinyal ke variabel dengan membuat pernyataan pertama dari tindakan jebakan ke sesuatu seperti
sig=$(($? - 128))
Anda kemudian bisa mendapatkan nama sinyal menggunakan perintah kill
kill -l $sig
Pembaruan:Seperti disebutkan dalam komentar, ini tidak berfungsi untuk beberapa perintah Shell bawaan. Untuk mengatur ini $ jebakannya? variabel, mereka dapat dijalankan dalam subkulit, Misalnya
(read)
bukannya
read
cara sederhana untuk melakukannya:
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT