Jawaban baru:
Pertanyaan ini jauh lebih menarik daripada yang saya duga sebelumnya. Jawabannya pada dasarnya diberikan di sini:
Apa yang terjadi pada SIGINT (^C) saat dikirim ke skrip perl yang berisi anak-anak?
Inilah berita gembira yang relevan. Saya menyadari Anda tidak menggunakan Perl, tapi saya menganggap Bash menggunakan konvensi C.
Fungsi sistem bawaan Perl berfungsi seperti fungsi sistem C (3) dari perpustakaan C standar sejauh menyangkut sinyal. Jika Anda menggunakan versi Perl dari sistem () atau pipa terbuka atau backticks, maka induknya - satu-satunya sistem pemanggil daripada yang dipanggil olehnya — akan MENGABAIKAN SIGINT dan SIGQUIT apa pun saat anak-anak sedang berlari.
Penjelasan ini adalah yang terbaik yang pernah saya lihat tentang berbagai pilihan yang bisa dibuat. Ia juga mengatakan bahwa Bash melakukan pendekatan WCE. Artinya, ketika proses induk menerima SIGINT, ia menunggu sampai proses anaknya kembali. Jika proses itu ditangani keluar dari SIGINT, itu juga keluar dengan SIGINT. Jika anak keluar dengan cara lain, SIGINT akan diabaikan.
Ada juga cara agar shell pemanggil dapat mengetahui apakah program yang dipanggil keluar dari SIGINT dan jika mengabaikan SIGINT (atau menggunakannya untuk tujuan lain). Seperti pada cara WUE, shell menunggu anak selesai. Ini menentukan apakah program diakhiri pada SIGINT dan jika demikian, skrip dihentikan. Jika program keluar lagi, skrip akan dilanjutkan. Saya akan menyebut cara melakukan sesuatu sebagai "WCE" (untuk "menunggu dan bekerja sama keluar") untuk sisa dokumen ini.
Saya tidak dapat menemukan referensi untuk ini di halaman manual Bash, tetapi saya akan terus mencari di info docs. Tapi saya 99% yakin ini adalah jawaban yang benar.
Jawaban lama:
Status keluar bukan nol dari perintah dalam skrip Bash tidak menghentikan program. Jika Anda melakukan echo $?
setelah ./script2.sh
itu akan menampilkan 130. Anda dapat mengakhiri skrip dengan menggunakan set -e
seperti yang disarankan phs.
$ help set
...
-e Exit immediately if a command exits with a non-zero status.
Bagian kedua dari jawaban @seanmcl yang diperbarui benar dan tautan ke http://www.cons.org/cracauer/sigint.html benar-benar bagus untuk dibaca dengan cermat.
Dari tautan itu, "Anda tidak dapat 'memalsukan' status keluar yang tepat dengan exit(3) dengan nilai numerik khusus, bahkan jika Anda mencari nilai numerik untuk sistem Anda ". Sebenarnya, itulah yang dicoba di script2.sh @Hermann Speiche.
Salah satu jawabannya adalah memodifikasi penangan fungsi di script2.sh sebagai berikut:
function handler {
# ... do stuff ...
trap INT
kill -2 $$
}
Ini secara efektif menghapus penangan sinyal dan "melempar kembali" SIGINT, menyebabkan proses bash keluar dengan flag yang sesuai sehingga proses bash induknya kemudian menangani SIGINT yang awalnya dikirim ke sana dengan benar. Dengan cara ini, gunakan set -e
atau peretasan lainnya sebenarnya tidak diperlukan.
Perlu juga dicatat bahwa jika Anda memiliki executable yang berperilaku salah saat mengirim SIGINT (tidak sesuai dengan "Bagaimana menjadi program yang tepat" di tautan di atas, misalnya keluar dengan kode pengembalian normal), salah satu cara cara mengatasinya adalah dengan membungkus panggilan ke proses itu dengan skrip seperti berikut:
#!/bin/bash
function handler {
trap INT
kill -2 $$
}
trap handler INT
badprocess "[email protected]"