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".


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.


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.


ITYM "tidur dan ulangi sendiri", bukan "keluar dengan anggun"?
Toby Speight
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.