Cara Menggunakan Sinyal Linux di Skrip Bash
Diterbitkan: 2022-08-09
Kernel Linux mengirimkan sinyal ke proses tentang peristiwa yang mereka butuhkan untuk bereaksi. Skrip yang berperilaku baik menangani sinyal dengan elegan dan kuat dan dapat membersihkan di belakangnya sendiri bahkan jika Anda menekan Ctrl+C. Begini caranya.
Sinyal dan Proses
Sinyal adalah pesan singkat, cepat, satu arah yang dikirim ke proses seperti skrip, program, dan daemon. Mereka membiarkan proses tahu tentang sesuatu yang telah terjadi. Pengguna mungkin telah menekan Ctrl+C, atau aplikasi mungkin mencoba menulis ke memori yang tidak dapat diaksesnya.
Jika pembuat proses telah mengantisipasi bahwa sinyal tertentu mungkin dikirim ke sana, mereka dapat menulis rutin ke dalam program atau skrip untuk menangani sinyal itu. Rutinitas seperti itu disebut penangan sinyal . Ini menangkap atau menjebak sinyal, dan melakukan beberapa tindakan sebagai tanggapannya.
Linux menggunakan banyak sinyal, seperti yang akan kita lihat, tetapi dari sudut pandang skrip, hanya ada sebagian kecil sinyal yang mungkin menarik bagi Anda. Khususnya, dalam skrip non-sepele, sinyal yang memberi tahu skrip untuk dimatikan harus dijebak (jika memungkinkan) dan pematian yang anggun dilakukan.
Misalnya, skrip yang membuat file sementara atau membuka port firewall dapat diberi kesempatan untuk menghapus file sementara atau menutup port sebelum dimatikan. Jika skrip mati begitu menerima sinyal, komputer Anda dapat dibiarkan dalam keadaan yang tidak terduga.
Inilah cara Anda dapat menangani sinyal dalam skrip Anda sendiri.
Memenuhi Sinyal
Beberapa perintah Linux memiliki nama yang samar. Tidak begitu perintah yang menjebak sinyal. Itu disebut trap
. Kita juga dapat menggunakan trap
dengan opsi -l
(list) untuk menunjukkan kepada kita seluruh daftar sinyal yang digunakan Linux.
perangkap -l
Meskipun daftar bernomor kami berakhir pada 64, sebenarnya ada 62 sinyal. Sinyal 32 dan 33 hilang. Mereka tidak diimplementasikan di Linux. Mereka telah digantikan oleh fungsionalitas di kompiler gcc
untuk menangani utas waktu nyata. Semuanya mulai dari sinyal 34, SIGRTMIN
, hingga sinyal 64, SIGRTMAX
, adalah sinyal waktu nyata.
Anda akan melihat daftar yang berbeda pada sistem operasi mirip Unix yang berbeda. Di OpenIndiana misalnya, sinyal 32 dan 33 hadir, bersama dengan sekelompok sinyal tambahan yang membuat jumlah total menjadi 73.
Sinyal dapat direferensikan dengan nama, nomor, atau dengan nama singkatnya. Nama singkat mereka hanyalah nama mereka dengan "SIG" terkemuka dihapus.
Sinyal dinaikkan karena berbagai alasan. Jika Anda dapat menguraikannya, tujuan mereka terkandung dalam nama mereka. Dampak sinyal termasuk dalam salah satu dari beberapa kategori:
- Terminate: Proses dihentikan.
- Abaikan: Sinyal tidak mempengaruhi proses. Ini adalah sinyal informasi saja.
- Core: File dump-core dibuat. Hal ini biasanya dilakukan karena proses telah melanggar dalam beberapa cara, seperti pelanggaran memori.
- Berhenti: Proses dihentikan. Artinya, itu dijeda , bukan dihentikan.
- Continue: Memberi tahu proses yang dihentikan untuk melanjutkan eksekusi.
Ini adalah sinyal yang paling sering Anda temui.
- SIGHUP : Sinyal 1. Sambungan ke host jarak jauh—seperti server SSH—telah tiba-tiba terputus atau pengguna telah keluar. Skrip yang menerima sinyal ini mungkin berhenti dengan baik, atau mungkin memilih untuk mencoba menyambung kembali ke host jarak jauh.
- SIGINT : Sinyal 2. Pengguna telah menekan kombinasi Ctrl+C untuk memaksa proses menutup, atau perintah
kill
telah digunakan dengan sinyal 2. Secara teknis, ini adalah sinyal interupsi, bukan sinyal penghentian, tetapi skrip yang terputus tanpa penangan sinyal biasanya akan berhenti. - SIGQUIT : Sinyal 3. Pengguna telah menekan kombinasi Ctrl+D untuk memaksa proses berhenti, atau perintah
kill
telah digunakan dengan sinyal 3. - SIGFPE : Sinyal 8. Proses mencoba melakukan operasi matematika ilegal (tidak mungkin), seperti pembagian dengan nol.
- SIGKILL : Sinyal 9. Ini adalah sinyal yang setara dengan guillotine. Anda tidak dapat menangkap atau mengabaikannya, dan itu terjadi secara instan. Proses segera dihentikan.
- SIGTERM : Signal 15. Ini adalah versi
SIGKILL
yang lebih perhatian.SIGTERM
juga memberi tahu proses untuk dihentikan, tetapi dapat terjebak dan proses dapat menjalankan proses pembersihannya sebelum ditutup. Ini memungkinkan shutdown yang anggun. Ini adalah sinyal default yang dimunculkan oleh perintahkill
.
Sinyal di Baris Perintah
Salah satu cara untuk menjebak sinyal adalah dengan menggunakan trap
dengan nomor atau nama sinyal, dan respon yang diinginkan terjadi jika sinyal diterima. Kita dapat mendemonstrasikan ini di jendela terminal.
Perintah ini menjebak sinyal SIGINT
. Responsnya adalah mencetak sebaris teks ke jendela terminal. Kami menggunakan opsi -e
(enable escapes) dengan echo
sehingga kami dapat menggunakan penentu format “ \n
”.
trap 'echo -e "\nCtrl+c Terdeteksi."' TANDA
Baris teks kita dicetak setiap kali kita menekan kombinasi Ctrl+C.
Untuk melihat apakah jebakan dipasang pada sinyal, gunakan opsi -p
(perangkap cetak).
perangkap -p TANDA
Menggunakan trap
tanpa opsi melakukan hal yang sama.
Untuk mengatur ulang sinyal ke keadaan normal yang tidak dijebak, gunakan tanda hubung “ -
” dan nama sinyal yang terperangkap.
perangkap - TANDA
perangkap -p TANDA
Tidak ada keluaran dari perintah trap -p
menunjukkan tidak ada perangkap yang dipasang pada sinyal tersebut.
Menjebak Sinyal dalam Skrip
Kita dapat menggunakan perintah trap
format umum yang sama di dalam skrip. Skrip ini menjebak tiga sinyal berbeda, SIGINT
, SIGQUIT
, dan SIGTERM
.
#!/bin/bash jebakan "echo I was SIGINT dihentikan; keluar" SIGINT jebakan "gema saya dihentikan SIGQUIT; keluar" SIGQUIT jebakan "gema saya dihentikan SIGTERM; keluar" SIGTERM gema $$ penghitung = 0 sementara benar melakukan echo "Nomor lingkaran:" $((++penghitung)) tidur 1 selesai
Tiga pernyataan trap
ada di bagian atas skrip. Perhatikan bahwa kami telah menyertakan perintah exit
di dalam respons untuk setiap sinyal. Ini berarti skrip bereaksi terhadap sinyal dan kemudian keluar.
Salin teks ke editor Anda dan simpan dalam file bernama “simple-loop.sh”, dan buat agar dapat dieksekusi menggunakan perintah chmod
. Anda harus melakukannya untuk semua skrip dalam artikel ini jika Anda ingin mengikutinya di komputer Anda sendiri. Cukup gunakan nama skrip yang sesuai dalam setiap kasus.

chmod +x simple-loop.sh
Sisa skrip sangat sederhana. Kami perlu mengetahui ID proses skrip, jadi kami memiliki skrip yang menggemakannya kepada kami. Variabel $$
menyimpan ID proses skrip.
Kami membuat variabel yang disebut counter
dan mengaturnya ke nol.
Perulangan while
akan berjalan selamanya kecuali dihentikan secara paksa. Ini menambah variabel counter
, menggemakannya ke layar, dan tidur sebentar.
Mari jalankan skrip dan kirim sinyal berbeda ke sana.
./simple-loop.sh
Ketika kami menekan "Ctrl + C" pesan kami dicetak ke jendela terminal dan skrip dihentikan.
Mari kita jalankan lagi dan kirim sinyal SIGQUIT
menggunakan perintah kill
. Kita harus melakukannya dari jendela terminal lain. Anda harus menggunakan ID proses yang dilaporkan oleh skrip Anda sendiri.
./simple-loop.sh
bunuh -SIGQUIT 4575
Seperti yang diharapkan, skrip melaporkan sinyal yang tiba kemudian berakhir. Dan akhirnya, untuk membuktikan maksudnya, kita akan melakukannya lagi dengan sinyal SIGTERM
.
./simple-loop.sh
bunuh -SIGTERM 4584
Kami telah memverifikasi bahwa kami dapat menjebak banyak sinyal dalam skrip, dan bereaksi terhadap masing-masing sinyal secara independen. Langkah yang mempromosikan semua ini dari menarik menjadi bermanfaat adalah menambahkan penangan sinyal.
Menangani Sinyal dalam Script
Kami dapat mengganti string respons dengan nama fungsi dalam skrip Anda. Perintah trap
kemudian memanggil fungsi tersebut ketika sinyal terdeteksi.
Salin teks ini ke editor dan simpan sebagai file bernama “grace.sh”, dan buat itu dapat dieksekusi dengan chmod
.
#!/bin/bash trap graceful_shutdown SIGINT SIGQUIT SIGTERM anggun_shutdown() { echo -e "\nMenghapus file sementara:" $temp_file rm -rf "$temp_file" KELUAR } temp_file=$(mktemp -p /tmp tmp.XXXXXXXXXX) echo "File temp telah dibuat:" $temp_file penghitung = 0 sementara benar melakukan echo "Nomor lingkaran:" $((++penghitung)) tidur 1 selesai
Skrip menetapkan jebakan untuk tiga sinyal berbeda— SIGHUP
, SIGINT
, dan SIGTERM
—menggunakan pernyataan trap
tunggal. Responsnya adalah nama fungsi graceful_shutdown()
. Fungsi dipanggil setiap kali salah satu dari tiga sinyal yang terperangkap diterima.
Script membuat file sementara di direktori “/tmp”, menggunakan mktemp
. Template nama file adalah “tmp.XXXXXXXXXX”, jadi nama filenya adalah “tmp.” diikuti oleh sepuluh karakter alfanumerik acak. Nama file bergema di layar.
Sisa skrip sama dengan yang sebelumnya, dengan variabel counter
dan loop while
tak terbatas.
./grace.sh
Saat file dikirimi sinyal yang menyebabkannya ditutup, fungsi graceful_shutdown()
dipanggil. Ini menghapus file sementara tunggal kami. Dalam situasi dunia nyata, itu bisa melakukan pembersihan apa pun yang diperlukan skrip Anda.
Selain itu, kami menggabungkan semua sinyal yang terperangkap bersama-sama dan menanganinya dengan satu fungsi. Anda dapat menjebak sinyal satu per satu dan mengirimkannya ke fungsi pengendali khusus mereka sendiri.
Salin teks ini dan simpan dalam file bernama "triple.sh", dan buat itu dapat dieksekusi menggunakan perintah chmod
.
#!/bin/bash perangkap sigint_handler SIGINT perangkap sigusr1_handler SIGUSR1 perangkap exit_handler EXIT fungsi tanda_penangan() { ((++sign_count)) echo -e "\nSIGINT menerima $sigint_count waktu." if [[ "$sigint_count" -eq 3 ]]; kemudian echo "Memulai close-down." loop_flag=1 fi } fungsi sigusr1_handler() { echo "SIGUSR1 dikirim dan diterima $((++sigusr1_count)) waktu." } fungsi exit_handler() { echo "Penangan keluar: Skrip ditutup..." } gema $$ sigusr1_count=0 tanda_hitung=0 loop_flag=0 while [[ $loop_flag -eq 0 ]]; melakukan bunuh -SIGUSR1 $$ tidur 1 selesai
Kami mendefinisikan tiga jebakan di bagian atas skrip.
- Satu menjebak
SIGINT
dan memiliki penangan yang disebutsigint_handler()
. - Yang kedua menjebak sinyal yang disebut
SIGUSR1
dan menggunakan penangan yang disebutsigusr1_handler()
. - Perangkap nomor tiga menjebak sinyal
EXIT
. Sinyal ini dimunculkan oleh skrip itu sendiri saat ditutup. Menyetel pengendali sinyal untukEXIT
berarti Anda dapat mengatur fungsi yang akan selalu dipanggil saat skrip dihentikan (kecuali jika dimatikan dengan sinyalSIGKILL
). Handler kami disebutexit_handler()
.
SIGUSR1
dan SIGUSR2
adalah sinyal yang disediakan sehingga Anda dapat mengirim sinyal khusus ke skrip Anda. Bagaimana Anda menafsirkan dan bereaksi terhadap mereka sepenuhnya terserah Anda.
Mengesampingkan penangan sinyal untuk saat ini, isi skrip seharusnya sudah tidak asing lagi bagi Anda. Ini menggemakan ID proses ke jendela terminal dan membuat beberapa variabel. Variabel sigusr1_count
mencatat berapa kali SIGUSR1
ditangani, dan sigint_count
mencatat berapa kali SIGINT
ditangani. Variabel loop_flag
disetel ke nol.
Perulangan while
bukanlah perulangan tak berhingga. Ini akan berhenti mengulang jika variabel loop_flag
disetel ke nilai bukan nol. Setiap putaran while
loop menggunakan kill
untuk mengirim sinyal SIGUSR1
ke skrip ini, dengan mengirimkannya ke ID proses skrip. Script dapat mengirim sinyal ke diri mereka sendiri!
Fungsi sigusr1_handler()
menambah variabel sigusr1_count
dan mengirim pesan ke jendela terminal.
Setiap kali sinyal SIGINT
diterima, fungsi siguint_handler()
menambah variabel sigint_count
dan menggemakan nilainya ke jendela terminal.
Jika variabel sigint_count
sama dengan tiga, variabel loop_flag
disetel ke satu dan sebuah pesan dikirim ke jendela terminal yang memberi tahu pengguna bahwa proses shutdown telah dimulai.
Karena loop_flag
tidak lagi sama dengan nol, loop while
berakhir dan skrip selesai. Tapi tindakan itu secara otomatis memunculkan sinyal EXIT
dan fungsi exit_handler()
dipanggil.
./triple.sh
Setelah tiga kali menekan Ctrl+C, skrip akan berhenti dan secara otomatis memanggil fungsi exit_handler()
.
Baca Sinyalnya
Dengan menjebak sinyal dan menanganinya dalam fungsi handler langsung, Anda dapat membuat skrip Bash Anda rapi di belakang mereka sendiri bahkan jika tiba-tiba dihentikan. Itu memberi Anda sistem file yang lebih bersih. Ini juga mencegah ketidakstabilan saat Anda menjalankan skrip berikutnya, dan—tergantung pada tujuan skrip Anda—bahkan dapat mencegah lubang keamanan.
TERKAIT: Cara Mengaudit Keamanan Sistem Linux Anda dengan Lynis