Apa yang terjadi adalah bahwa baik bashdan pingmenerima SIGINT ( bashmenjadi tidak interaktif, baik pingdan bashberjalan dalam kelompok proses yang sama yang telah dibuat dan ditetapkan sebagai kelompok proses latar depan terminal oleh shell interaktif Anda berlari bahwa script dari).
Namun, bashmenangani SIGINT itu secara tidak sinkron, hanya setelah perintah yang saat ini berjalan telah keluar. bashhanya keluar setelah menerima SIGINT itu jika perintah yang sedang berjalan mati karena SIGINT (yaitu status keluarnya menunjukkan bahwa ia telah dibunuh oleh SIGINT).
$ bash -c 'sh -c "trap exit\ 0 INT; sleep 10; :"; echo here'
^Chere
Di atas, bash, shdan sleepmenerima SIGINT ketika saya menekan Ctrl-C, tapi shkeluar biasanya dengan kode 0 keluar, sehingga bashmengabaikan SIGINT, yang sebabnya kita melihat "di sini".
ping, setidaknya yang dari iputils, berperilaku seperti itu. Ketika terganggu, ia mencetak statistik dan keluar dengan status keluar 0 atau 1 tergantung pada apakah pingnya dijawab atau tidak. Jadi, ketika Anda menekan Ctrl-C saat pingsedang berjalan, bashperhatikan bahwa Anda telah menekan Ctrl-Cdi penangan SIGINT-nya, tetapi karena pingkeluar secara normal, bashtidak keluar.
Jika Anda menambahkan sleep 1dalam loop itu dan tekan Ctrl-Csaat sleepsedang berjalan, karena sleeptidak memiliki penangan khusus pada SIGINT, itu akan mati dan melaporkan bashbahwa itu mati karena SIGINT, dan dalam kasus itubash akan keluar (itu benar-benar akan bunuh diri dengan SIGINT sehingga untuk melaporkan gangguan ke induknya).
Mengenai mengapa bashberperilaku seperti itu, saya tidak yakin dan saya perhatikan perilaku tidak selalu deterministik. Saya baru saja mengajukan pertanyaan pada bashmilis pengembangan ( Pembaruan : @Jilles sekarang telah menemukan alasannya dalam jawabannya ).
Satu-satunya shell lain yang saya temukan berperilaku serupa adalah ksh93 (Pembaruan, seperti yang disebutkan oleh @Jilles, begitu juga FreeBSDsh ). Di sana, SIGINT tampaknya benar-benar diabaikan. Dan ksh93keluar setiap kali perintah dibunuh oleh SIGINT.
Anda mendapatkan perilaku yang sama seperti di bashatas tetapi juga:
ksh -c 'sh -c "kill -INT \$\$"; echo test'
Tidak menampilkan "tes". Yaitu, ia keluar (dengan membunuh dirinya sendiri dengan SIGINT di sana) jika perintah yang ditungguinya mati oleh SIGINT, bahkan jika itu, ia sendiri tidak menerima SIGINT itu.
Pekerjaan di sekitar adalah menambahkan:
trap 'exit 130' INT
Di bagian atas skrip untuk memaksa bashkeluar setelah menerima SIGINT (perhatikan bahwa dalam hal apa pun, SIGINT tidak akan diproses secara serempak, hanya setelah perintah yang saat ini berjalan telah keluar).
Idealnya, kami ingin melaporkan kepada orang tua kami bahwa kami meninggal karena SIGINT (sehingga jika itu adalah bashskrip lain misalnya, bashskrip itu juga terputus). Melakukan exit 130tidak sama dengan sekarat SIGINT (meskipun beberapa shell akan diatur$? nilai yang sama untuk kedua kasus), namun sering digunakan untuk melaporkan kematian oleh SIGINT (pada sistem di mana SIGINT adalah 2 yang paling banyak).
Namun untuk bash, ksh93atau FreeBSD sh, itu tidak berhasil. 130 status keluar tidak dianggap sebagai kematian oleh SIGINT dan skrip induk tidak akan dibatalkan di sana.
Jadi, alternatif yang mungkin lebih baik adalah bunuh diri dengan SIGINT setelah menerima SIGINT:
trap '
trap - INT # restore default INT handler
kill -s INT "$$"
' INT
for f in *.txt; do vi "$f"; cp "$f" newdir; done. Jika pengguna mengetik Ctrl + C saat mengedit salah satu file,vicukup tampilkan pesan. Tampaknya masuk akal bahwa perulangan harus dilanjutkan setelah pengguna selesai mengedit file. (Dan ya, saya tahu Anda bisa mengatakanvi *.txt; cp *.txt newdir; Saya hanya mengirimkanforperulangan sebagai contoh.)