Topik ini membahas sinyal sebagai mekanisme kernel untuk memberi tahu proses bahwa sesuatu perlu ditangani, dengan kill sebagai perintah pengirimnya dari shell. Fokusnya ada pada dua sinyal yang paling sering dipakai untuk menghentikan proses, yaitu SIGTERM yang memberi kesempatan berhenti dengan rapi dan SIGKILL yang bekerja tanpa peringatan. Setelah membacanya, pemilihan antara kill, kill -9, dan sinyal lain menjadi keputusan yang sadar, bukan kebiasaan mengetik yang sama untuk semua keadaan.
Sinyal sebagai pesan kernel#
Sinyal (signal) adalah pemberitahuan pendek yang dikirim kernel atau proses lain kepada sebuah proses. Isinya hanya nomor dan nama, misalnya “sinyal 15 datang”, tanpa data tambahan. Setiap proses menentukan sikapnya sendiri terhadap sinyal yang diterima: menangkapnya dengan penangan khusus, mengabaikannya, atau membiarkan perilaku bawaannya berjalan. Untuk banyak sinyal, perilaku bawaan itu berarti proses berhenti. Perintah kill mengirim sinyal dari shell, dan padanannya di banyak bahasa pemrograman disebut dengan nama yang sama.
Setiap sinyal memiliki nomor yang tetap, dan kill -l menerjemahkan dua arah antara nama dan nomornya.
mkdir -p /tmp/kerja-sinyal
cd /tmp/kerja-sinyal
# kill -l menerjemahkan nama dan nomor sinyal dua arah
kill -l TERM
kill -l KILL
kill -l 9
kill -l 1515
9
KILL
TERM| Sinyal | Nomor | Peran yang lazim |
|---|---|---|
| SIGHUP | 1 | Putusnya sesi terminal, juga dipakai sebagai permintaan memuat ulang konfigurasi |
| SIGINT | 2 | Tekanan Ctrl-C pada proses latar depan |
| SIGKILL | 9 | Penghentian paksa yang tidak dapat ditolak |
| SIGTERM | 15 | Permintaan berhenti yang sopan, bawaan dari kill |
| SIGSTOP dan SIGCONT | 19 dan 18 | Menahan dan melanjutkan proses |
Nomor 9 dan 15 layak dihafal karena keduanya menjadi pilihan sehari-hari, sedangkan sinyal-sinyal lain dicari melalui kill -l ketika diperlukan.
kill dan SIGTERM#
Perintah kill tanpa opsi mengirim SIGTERM, yaitu permintaan berhenti yang diharapkan ditanggapi dengan sopan. Program yang dirancang baik menangkap sinyal ini untuk menutup berkas yang terbuka, menulis sisa data, dan memberi tahu rekan-rekannya sebelum benar-benar berakhir. Contoh berikut melahirkan satu proses sleep 300, mengirim SIGTERM kepadanya, lalu memeriksa akibatnya dengan ps.
sleep 300 &
PID=$!
sleep 0.3
ps -o stat=,cmd= -p "$PID"
# kill tanpa opsi mengirim SIGTERM
kill "$PID"
wait "$PID" 2>/dev/null
echo "status keluar: $?"
ps -o stat= -p "$PID"
echo "ps tidak menampilkan apa pun dan keluar dengan status $?"S sleep 300
status keluar: 143
ps tidak menampilkan apa pun dan keluar dengan status 1Proses sleep tidak menangkap SIGTERM, sehingga sinyal itu langsung mengakhirinya dan ps tidak lagi menemukan baris apa pun untuk PID tersebut. Status keluar yang direkam wait adalah 143, yaitu 128 ditambah nomor sinyal 15, pola yang berlaku untuk setiap proses yang berakhir karena sinyal. Angka ini berulang kali muncul pada skrip dan layanan, sehingga mengenalinya mempercepat pembacaan log.
Setelah kill dikirim, apakah prosesnya benar-benar berhenti perlu diverifikasi, bukan diasumsikan. Pembandingannya mudah dilakukan dengan ps -p PID seperti pada contoh, karena keluaran kosong berarti proses sudah berakhir, sedangkan baris dengan keadaan T berarti proses masih hidup tetapi ditahan. Program yang besar memerlukan waktu sekejap untuk menyelesaikan pembersihannya, sehingga perlu ada jeda beberapa detik sebelum disimpulkan bahwa sinyal gagal.
SIGKILL tidak dapat ditolak#
Sinyal SIGKILL diimplementasikan langsung oleh kernel dan tidak pernah sampai ke tangan program, sehingga tidak bisa ditangkap, ditunda, atau diabaikan. Contoh berikut mengulang pola yang sama dengan kill -9.
sleep 300 &
PID=$!
sleep 0.3
kill -9 "$PID"
wait "$PID" 2>/dev/null
echo "status keluar: $?"
ps -o stat= -p "$PID"
echo "ps tidak menampilkan apa pun dan keluar dengan status $?"status keluar: 137
ps tidak menampilkan apa pun dan keluar dengan status 1Pada sleep, hasil keduanya tampak mirip karena program kecil itu tidak menangkap sinyal apa pun, hanya nomor statusnya yang berbeda menjadi 137, yaitu 128 ditambah 9. Perbedaan yang sesungguhnya baru terlihat pada program yang memang menangani SIGTERM, dan itulah yang diuji pada bagian berikut.
Karena pengirimannya ditangani kernel, SIGKILL bekerja bahkan pada proses yang sedang berputar tanpa henti atau yang mengabaikan SIGTERM, dan itulah alasan keberadaannya. Kasus yang pantas menerima kill -9 adalah proses yang macet total, misalnya program yang berputar dalam perulangan tanpa akhir setelah error dan tidak lagi menanggapi apa pun. Perlu dicatat bahwa proses yang baru dihentikan kadang masih terdaftar pada ps dengan keadaan Z, yaitu zombie, karena proses induknya belum merekam status akhirnya, dan baris semacam itu bukan tanda sinyal gagal.
Perbedaannya pada program yang menangkap sinyal#
Skrip shell dapat menetapkan penangan sinyal (signal handler) dengan trap. Skrip contoh berikut menjaga sebuah berkas penanda, dan penangan SIGTERM-nya menghapus penanda tersebut sebelum keluar.
rm -f penanda
printf '#!/bin/bash\ntrap "rm -f penanda; echo penanda dibersihkan; exit 0" TERM\nwhile true; do sleep 0.2; done\n' > tugas.sh
touch penanda
bash tugas.sh &
PID=$!
sleep 0.3
kill "$PID"
wait "$PID" 2>/dev/null
echo "status keluar: $?"
test -f penanda || echo "penanda sudah dihapus"penanda dibersihkan
status keluar: 0
penanda sudah dihapusSIGTERM ditangkap, penanda dihapus, dan skrip keluar dengan status 0 karena memang berhenti sesuai rencana. Percobaan yang sama dengan SIGKILL berjalan sangat berbeda.
rm -f penanda
touch penanda
bash tugas.sh &
PID=$!
sleep 0.3
kill -9 "$PID"
wait "$PID" 2>/dev/null
echo "status keluar: $?"
test -f penanda && echo "penanda masih ada"status keluar: 137
penanda masih adaPesan dari penangan sinyal tidak muncul, dan berkas penanda tertinggal karena penangan itu tidak pernah berkesempatan berjalan. Inilah harga SIGKILL: prosesnya pasti berhenti, tetapi semua pembersihan yang seharusnya dilakukan ikut batal. Pola pada skrip kecil ini berlaku sama pada program besar. Layanan web, misalnya, menutup koneksi dan menulis log ketika menerima SIGTERM, sehingga perhentian paksa dengan kill -9 pada layanan semacam itu meninggalkan keadaan yang tidak selesai.
Kesalahan umum#
- Memakai
kill -9sebagai refleks pertama. Kebiasaan ini menghilangkan kesempatan program merapikan dirinya. Urutan yang sehat adalahkill, menunggu sebentar, memeriksa denganps, lalukill -9bila prosesnya masih bertahan. - Menganggap proses macet hanya karena belum berakhir beberapa ratus milidetik setelah
kill. Program yang menangkap SIGTERM memerlukan waktu untuk merapikan dirinya, dan durasinya wajar mencapai beberapa detik pada program dengan banyak koneksi. - Mengirim sinyal ke proses milik pengguna lain. Kernel menolaknya dengan pesan error
Operation not permitted, dan hanya root yang dapat mengirim sinyal ke proses milik siapa pun. - Menyasar PID dari ingatan atau dari log lama. Nomor dapat dipakai ulang, sehingga sinyal bisa terkirim ke proses yang tidak diinginkan. Cari nomor terkini dengan
psterlebih dahulu, atau gunakan perintah sepertipkillyang menerima nama proses sebagai sasarannya. Kecocokan nama tetap diperiksa melaluipssebelum sinyal dikirim.
Ringkasan#
- Sinyal adalah pemberitahuan bernomor dari kernel atau proses lain, dan
killbesertakill -lmengirim serta menerjemahkannya dari shell. killmengirim SIGTERM 15 sebagai permintaan berhenti yang dapat ditangkap, sedangkankill -9mengirim SIGKILL 9 yang langsung dijalankan kernel tanpa bisa ditolak.- Status keluar 143 dan 137, yaitu 128 ditambah nomor sinyalnya, menandai proses yang berakhir karena sinyal.
- SIGKILL membatalkan seluruh pembersihan yang ditangani program, sehingga kedudukannya adalah upaya terakhir setelah SIGTERM diberi waktu.
Referensi#
- signal(7) — Linux man-pages project — Daftar lengkap sinyal, nomornya, dan perilaku bawaannya.
- kill(1) — Linux man-pages project — Pemakaian kill untuk mengirim sinyal beserta bentuk nama dan nomornya.
- bash(1) — Linux man-pages project — Penjelasan trap, yaitu penetapan penangan sinyal pada skrip shell.