Come rendere ctrl + c / not / interrompere il ciclo while?


11

Dato questo ciclo:

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

Quando premo Ctrl + C l'intero ciclo while viene interrotto. Quello che voglio fare è interrompere il processo "qualcosa", lasciare passare 10 secondi e quindi riavviare "qualcosa".

Come posso fare in modo che ctrl + c influisca solo su "qualcosa", e non sul ciclo while?

EDIT: "interrompere" come in SIGINT. Uccidere. Abort. Terminare. Non "interrompere" come in "pausa".


Se vuoi solo metterlo in pausa, perché non usare Ctrl + Z, attendere 10 secondi ed eseguire fg? Perché usare Ctrl + C?
terdon

@terdon: grazie per il commento, potrei essermi precipitato dentro con la risposta. Hai bisogno di leggere di più sui requisiti dei PO
Inian,

@terdon: non voglio metterlo in pausa. Voglio passare 10 secondi, come ho scritto.
bos

Lei ha detto: What I want to do is to interrupt the "something"-process, let 10 seconds pass, and then restart "something". Se premi Ctrl + Z, attendi 10 secondi e poi corri fg, è esattamente quello che succederà. Forse potresti modificare la tua domanda e dare un esempio specifico in modo che possiamo capire meglio?
terdon

3
Pensavo che nel contesto di Ctrl + C l'interruzione fosse inequivocabile, ma ovviamente mi sbagliavo. Ora ho modificato.
bos

Risposte:


18

Dovrebbe funzionare solo trap SIGINTper qualcosa. Mi piace :( true).

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

L'interruzione di something...non fa uscire adesso la shell, poiché ignora il segnale. Tuttavia, se ^ C il sleepprocesso, termina con un errore e il ciclo si interrompe a causa di ciò. Sposta l' sleepinterno del loop o aggiungi qualcosa di simile || trueper impedirlo.

Nota che se usi trap "" INTper ignorare completamente il segnale (invece di assegnare un comando ad esso), viene anche ignorato nel processo figlio, quindi non puoi nemmeno interrompere something.... Questo è esplicitamente menzionato almeno nel manuale di Bash :

Se arg è la stringa nulla, il segnale specificato da ciascun sigspec viene ignorato dalla shell e dai comandi che invoca. [...] I segnali ignorati all'entrata nella shell non possono essere intrappolati o resettati.


Questo può essere ottenuto anche nella shell attuale? (Non in uno script.)

1
Potresti voler do (trap - INT; something-that-runs-forever)consentire l'interruzione del comando. Inoltre, non è necessario eseguire :- si può semplicemente utilizzare una stringa vuota per ignorare un segnale: trap '' INT. Tutto questo è POSIX e dovrebbe funzionare su qualsiasi shell conforme (non solo su Bash).
Toby Speight,

Si noti inoltre che la scrittura SIGINTin piena non è strettamente portatile: " Le implementazioni possono permettere i nomi con il SIGprefisso o ignorare lettere maiuscole nei nomi dei segnali come estensione . (Corsivo mio)"
Toby Speight

puoi passare la stringa vuota come azione per ignorare un segnale, ad esempio trap "" INT(anche posix)
daf

@TobySpeight, il motivo che ho usato trap :invece di trap ""era esattamente questo, per non ignorare il segnale (ma renderlo invece no-op), quindi non abbiamo bisogno di fare altro per poter interrompere il somethingprogramma principale .
ilkkachu,

0

Un'altra opzione è quella di something-that-runs-forevergestire il segnale (uscendo con grazia quando viene ricevuto). Ovviamente, ha senso farlo solo quando questo programma viene utilizzato in molti script e il comportamento desiderato su CTRL+ Cè sistematicamente lo stesso - per continuare l'esecuzione degli script.


ITYM "dormire e ri-eseguirsi", non "uscire con grazia"?
Toby Speight,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.