Apa yang terjadi
Saat Anda menekan Ctrl+ C, SIGINT
sinyal dikirim ke seluruh grup proses latar depan . Ini dikirim ke find
proses dan proses shell panggilan. find
bereaksi dengan keluar segera, dan shell bereaksi dengan memanggil perangkap.
Jika kode dalam jebakan kembali (yaitu tidak menelepon exit
), eksekusi dilanjutkan dengan perintah setelah kode yang terputus oleh sinyal. Di sini, setelah find
perintah muncul akhir skrip, jadi skrip segera keluar. Tetapi Anda dapat melihat perbedaan antara memasukkan 0 dan 1 dengan menambahkan perintah lain:
find /
echo "find returned $?"
Cara untuk melakukan apa yang Anda inginkan (tapi mungkin tidak boleh dilakukan)
Anda dapat melakukan apa yang Anda inginkan; tapi ini bagian dari jawaban saya lebih tentang menemukan pemrograman shell daripada menyelesaikan masalah yang sebenarnya.
- Sebagai masalah desain, sinyal yang dapat dimulai kembali bukanlah yang biasanya Anda harapkan dalam jenis program yang relatif sederhana seperti shell script biasanya. Harapannya adalah Ctrl+ Cakan membunuh skrip.
- Seperti yang akan Anda lihat di bawah, itu memperluas kemampuan shell agak jauh.
Jika Anda ingin menghindari pembunuhan find
, Anda harus memulainya di latar belakang : find / &
. Kemudian gunakan wait
builtin untuk menunggu keluar secara normal. Sebuah sinyal akan mengganggu wait
built-in, yang dapat Anda jalankan dalam satu lingkaran sampai Anda menerima sinyal yang ingin Anda sebarkan. Kemudian gunakan kill
untuk mematikan pekerjaan.
hell () {
echo "Do you want to quit? Press 1 for yes and 0 for no"
read n
if [ "$n" = 1 ]; then
# Kill the job if it's running, then exit
if [ -n "$job_pid" ]; then kill $job_pid; fi
exit 1
fi
}
job_pid=
trap "hell" SIGINT
# Start a demo job in the background
for i in 1 2 3 4 5; do date; sleep 1; done &
job_pid=$!
# Call wait in a loop; wait will return 0 if the job exits, and 128+$signum if interrupted by a signal.
while ! wait; do
echo "resuming wait"
done
job_pid=
echo last exit code: $?
Ada batasan untuk pendekatan ini di shell:
- Ada kondisi balapan: jika Anda menekan Ctrl+ Ctepat setelah pekerjaan selesai tetapi sebelum
job_pid=
garis, pawang sinyal akan mencoba untuk membunuh $jobpid
, tetapi proses tidak lagi ada (bahkan sebagai zombie, karena wait
sudah menuai), dan prosesnya ID mungkin telah digunakan kembali oleh proses lain. Ini tidak mudah diperbaiki di shell (mungkin dengan mengatur handler untuk SIGCHLD
?).
- Jika Anda memerlukan status pengembalian dari pekerjaan, Anda harus menggunakan
wait $job_pid
formulir. Tapi kemudian Anda tidak dapat membedakan " wait
terganggu oleh sinyal" dari "pekerjaan terbunuh oleh sinyal" (atau dari "pekerjaan yang diakhiri dengan sendirinya dengan status pengembalian ≥128", tapi itu fakta umum dalam shell pemrograman).
- Ini tidak akan meluas dengan mudah jika sama sekali ke beberapa orang. Perhatikan bahwa perilaku jebakan dan sinyal sering mengejutkan ketika Anda melampaui dasar-dasar di sebagian besar implementasi shell (hanya ksh yang melakukan ini dengan baik).
Untuk mengatasi keterbatasan ini, gunakan bahasa yang lebih bagus seperti Perl atau Python.