GNU/Linux >> Belajar Linux >  >> Linux

Mengidentifikasi nama sinyal yang diterima di Bash

(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

Linux
  1. Bagaimana saya tahu nama file skrip dalam skrip Bash?

  2. Bagaimana cara mengonversi .. dalam nama jalur menjadi nama absolut dalam skrip bash?

  3. BASH:kirim sinyal SIGTSTP (ctrl+z)

  1. Tampilkan hanya nama direktori saat ini (bukan path lengkap) di bash prompt

  2. Bagaimana cara menghapus atau menghapus fungsi bash?

  3. Bagaimana cara menghapus karakter tambahan dalam nama file di Bash?

  1. Referensi Nama Edaran Dalam Fungsi Bash Shell, Tapi Tidak Di Ksh?

  2. Bash + Verifikasi Nama Dengan Ekspresi Reguler?

  3. 5 Contoh Pernyataan Kasus Bash