Bagaimana cara membuat ctrl + c / tidak / mengganggu while-loop?

11

Diberikan loop ini:

while sleep 10s ; do
  something-that-runs-forever
done

Ketika saya menekan Ctrl + C seluruh loop sementara terputus. Yang ingin saya lakukan adalah menghentikan proses "sesuatu", biarkan 10 detik berlalu, dan kemudian mulai kembali "sesuatu".

Bagaimana cara membuat ctrl + c hanya memengaruhi "sesuatu", dan bukan loop-sementara?

Sunting: "interupsi" seperti pada SIGINT. Membunuh. Menggugurkan. Mengakhiri. Bukan "interupsi" seperti pada "jeda".

bos
sumber
Jika Anda hanya ingin menjeda, mengapa tidak menggunakan Ctrl + Z, tunggu 10 detik dan jalankan fg? Mengapa menggunakan Ctrl + C?
terdon
@terdon: Terima kasih atas komentarnya, mungkin saya bergegas dengan jawabannya. Perlu membaca lebih lanjut tentang persyaratan
OPs
@terdon: Saya tidak ingin menghentikannya. Saya ingin 10 detik berlalu, seperti yang saya tulis.
bos
Anda mengatakan: What I want to do is to interrupt the "something"-process, let 10 seconds pass, and then restart "something". Jika Anda menekan Ctrl + Z, tunggu 10s dan kemudian jalankan fg, itulah yang akan terjadi. Mungkin Anda bisa mengedit pertanyaan Anda dan memberikan contoh spesifik sehingga kami dapat memahami dengan lebih baik?
terdon
3
Saya pikir dalam konteks Ctrl + C interrupt tidak ambigu, tapi jelas saya salah. Saya sekarang telah mengedit.
bos

Jawaban:

18

Ini harus bekerja jika Anda hanya trap SIGINTmelakukan sesuatu. Suka :( true).

#!/bin/sh
trap ":" INT    
while sleep 10s ; do
    something-that-runs-forever
done

Mengganggu something...tidak membuat shell keluar sekarang, karena mengabaikan sinyal. Namun, jika Anda ^ C sleepproses, itu akan keluar dengan kegagalan, dan loop berhenti karena itu. Pindahkan sleepke bagian dalam loop atau tambahkan sesuatu seperti || trueuntuk mencegahnya.

Perhatikan bahwa jika Anda menggunakan trap "" INTuntuk mengabaikan sinyal sepenuhnya (alih-alih menetapkan perintah untuk itu), itu juga diabaikan dalam proses anak, jadi Anda juga tidak dapat menyela something.... Ini secara eksplisit disebutkan dalam setidaknya manual Bash :

Jika arg adalah string nol, maka sinyal yang ditentukan oleh masing-masing sigspec diabaikan oleh shell dan memerintahkannya. [...] Sinyal yang diabaikan saat masuk ke shell tidak dapat dijebak atau direset.

ilkkachu
sumber
Bisakah ini dicapai dalam shell saat ini juga? (Tidak dalam skrip.)
1
Anda mungkin ingin do (trap - INT; something-that-runs-forever)mengizinkan interupsi dari perintah. Juga, Anda tidak perlu run :- Anda hanya dapat menggunakan string kosong untuk mengabaikan sinyal: trap '' INT. Semua ini POSIX, dan harus bekerja pada shell yang sesuai (bukan hanya Bash).
Toby Speight
Perhatikan juga bahwa menulis SIGINTsecara penuh tidak sepenuhnya portabel: " Implementasi dapat mengizinkan nama dengan SIGawalan atau mengabaikan huruf dalam nama sinyal sebagai ekstensi . " (Penekanan saya)
Toby Speight
Anda dapat melewatkan string kosong sebagai tindakan untuk mengabaikan sinyal misalnya trap "" INT(juga posix)
daf
@TobySpeight, alasan saya menggunakan trap :bukannya trap ""tepatnya itu, untuk tidak mengabaikan sinyal (tetapi menjadikannya sebagai no-op sebagai gantinya), sehingga kita tidak perlu melakukan hal lain untuk dapat mengganggu somethingprogram utama .
ilkkachu
0

Pilihan lain adalah something-that-runs-forevermenangani sinyal (keluar dengan anggun saat diterima). Tentu saja, itu hanya masuk akal untuk dilakukan ketika program ini digunakan dalam banyak skrip, dan perilaku yang diinginkan pada CTRL+ Csecara sistematis sama - untuk melanjutkan eksekusi skrip.

Dmitry Grigoryev
sumber
ITYM "tidur dan ulangi sendiri", bukan "keluar dengan anggun"?
Toby Speight