[Sunting: Ini terlihat mirip dengan beberapa pertanyaan lain yang menanyakan cara membunuh semua proses yang muncul - semua jawaban tampaknya menggunakan pkill. Jadi inti dari pertanyaan saya mungkin: Apakah ada cara untuk menyebarkan Ctrl-C / Z ke semua proses yang dihasilkan oleh skrip?]
Saat memanggil SoX rec
dengan timeout
perintah dari coreutils (dibahas di sini ), sepertinya tidak ada cara untuk membunuhnya dengan keystroke setelah dipanggil dari dalam skrip Bash.
Contoh:
timeout 10 rec test.wav
... dapat dibunuh dengan Ctrl+ Catau Ctrl+ Zdari bash, tetapi tidak ketika dipanggil dari dalam skrip.
timeout 10 ping nowhere
... dapat dibunuh dengan Ctrl+ Catau Ctrl+ Zdari bash, dan dengan Ctrl+ Zketika dijalankan dari dalam skrip.
Saya dapat menemukan ID proses dan mematikannya seperti itu, tetapi mengapa saya tidak dapat menggunakan keystroke break standar? Dan apakah ada cara untuk menyusun skrip saya sehingga saya bisa?
sumber
bg
darifg
perintah. Lagi pula, apakah ada perbedaan antara contoh 1 dan 3d Anda?timeout
pada sistem saya tetapi membunuhsleep
karya apakah itu diketik langsung pada baris perintah, bersumber, dieksekusi, atau melewati penerjemah secara eksplisitJawaban:
Kunci sinyal seperti Ctrl+ Cmengirim sinyal ke semua proses dalam grup proses latar depan .
Dalam kasus khas, grup proses adalah pipa. Misalnya, dalam
head <somefile | sort
, proses yang berjalanhead
dan proses yang berjalansort
berada dalam kelompok proses yang sama, seperti halnya shell, sehingga mereka semua menerima sinyal. Saat Anda menjalankan pekerjaan di latar belakang (somecommand &
), pekerjaan itu berada di grup prosesnya sendiri, jadi menekan Ctrl+ Ctidak memengaruhinya.The
timeout
Program menempatkan diri dalam kelompok proses sendiri. Dari kode sumber:Ketika timeout terjadi,
timeout
berjalan melalui cara sederhana membunuh kelompok proses yang menjadi anggotanya. Karena telah menempatkan dirinya dalam grup proses terpisah, proses induknya tidak akan berada dalam grup. Menggunakan grup proses di sini memastikan bahwa jika aplikasi anak bercabang menjadi beberapa proses, semua prosesnya akan menerima sinyal.Ketika Anda menjalankan
timeout
langsung pada baris perintah dan tekan Ctrl+ C, SIGINT yang dihasilkan diterima olehtimeout
dan oleh proses anak, tetapi tidak oleh shell interaktif yang merupakantimeout
proses induk. Ketikatimeout
dipanggil dari skrip, hanya shell yang menjalankan skrip yang menerima sinyal:timeout
tidak mendapatkannya karena berada di grup proses yang berbeda.Anda dapat mengatur penangan sinyal dalam skrip shell dengan
trap
builtin. Sayangnya, itu tidak sesederhana itu. Pertimbangkan ini:Jika Anda menekan Ctrl+ Csetelah 2 detik, ini masih menunggu 5 detik penuh, lalu cetak pesan "Terganggu". Itu karena shell menahan diri dari menjalankan kode jebakan sementara pekerjaan latar depan aktif.
Untuk mengatasinya, jalankan pekerjaan di latar belakang. Di penangan sinyal, panggilan
kill
untuk menyampaikan sinyal ketimeout
grup proses.sumber
Membangun jawaban luar biasa yang diberikan oleh Gilles. Perintah batas waktu memiliki opsi latar depan, jika digunakan maka CTRL + C akan keluar dari perintah batas waktu.
sumber
timeout
dari GNU coreutils.Pada dasarnya Ctrl+ Cmengirim
SIGINT
sinyal, sedangkan Ctrl+ Z mengirimSIGTSTP
sinyal.SIGTSTP
hanya menghentikan proses,SIGCONT
akan melanjutkannya.Ini bekerja pada foreground-proses yang bercabang pada baris perintah.
Jika proses Anda adalah proses latar belakang, Anda harus mengirim sinyal itu ke proses dengan cara yang berbeda.
kill
akan melakukan itu. Secara teori, operator "-" - pada pembunuhan itu juga harus menandakan proses anak tetapi ini jarang bekerja seperti yang diharapkan.Untuk bacaan lebih lanjut: Unix-Sinyal
sumber
Meningkatkan jawaban @Gilles dengan memberikan pendekatan "temukan dan ganti" untuk skrip yang ada:
INT
handler Anda :timeout
perintah denganmy_timeout
fungsi di skrip Anda.Contoh
Berikut ini contoh skrip:
sumber