Як зробити ctrl + c / not / перервати цикл while?


11

Враховуючи цю петлю:

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

Коли я натискаю Ctrl + C, весь цикл while переривається. Що я хочу зробити, це перервати процес "щось", дати пройти 10 секунд, а потім перезапустити "щось".

Як зробити так, щоб ctrl + c впливав лише на "щось", а не на цикл while?

EDIT: "перервати", як у SIGINT. Убити. Аборт. Припинити. Не «переривайте», як у «паузі».


Якщо ви просто хочете призупинити його, чому б не використовувати Ctrl + Z, почекати 10 секунд і запустити fg? Навіщо взагалі використовувати Ctrl + C?
тердон

@terdon: Дякую за коментар, може, я кинувся у відповідь. Потрібно детальніше ознайомитися з вимогою щодо ОП
Ініан

@terdon: Я не хочу призупиняти це. Я хочу пройти 10 секунд, як я писав.
bos

Ви сказали: What I want to do is to interrupt the "something"-process, let 10 seconds pass, and then restart "something". Якщо ви натиснете Ctrl + Z, зачекайте 10s, а потім запустіть fg, саме так і станеться. Можливо, ви могли б відредагувати своє запитання та надати конкретний приклад, щоб ми могли краще зрозуміти?
тердон

3
Я вважав, що в контексті Ctrl + C переривання було однозначним, але явно я помилявся. Я зараз редагував.
bos

Відповіді:


18

Це має спрацювати, якщо ви просто trap SIGINTна щось. Як :( true).

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

Переривання something...не робить оболонку вихід, оскільки вона ігнорує сигнал. Однак якщо ви ^ C sleepпроцес, він закінчиться з помилкою, і цикл припиняється через це. Перемістіть sleepдо внутрішньої частини циклу або додайте щось подібне, || trueщоб запобігти цьому.

Зауважте, що якщо ви trap "" INTповністю ігноруєте сигнал (замість того, щоб призначити йому команду), він також ігнорується в дочірньому процесі, тож ви також не можете перервати something...його. Про це прямо вказано в принаймні посібнику Баша :

Якщо arg є нульовим рядком, то сигнал, визначений кожним знаком , ігнорується оболонкою і командами, які вона викликає. [...] Сигнали, ігноровані при вході в оболонку, не можуть бути захоплені або скинуті.


Чи можна цього досягти і в поточній оболонці? (Не в сценарії.)

1
Ви do (trap - INT; something-that-runs-forever)можете дозволити перервати команду. Крім того , вам не потрібно бігти :- ви можете просто використовувати порожній рядок , щоб ігнорувати сигнал: trap '' INT. Все це POSIX і повинно працювати на будь-якій сумісній оболонці (не тільки Bash).
Toby Speight

Зауважте також, що написання SIGINTв повному обсязі не є строго переносним: " Реалізація може дозволити імена з SIGпрефіксом або ігнорувати регістр в імен сигналів як розширення . " (Мій акцент)
Toby Speight

ви можете передавати порожній рядок як дію з ігнорування сигналу, наприклад trap "" INT(також posix)
daf

@TobySpeight, чому я використав trap :замість того, trap ""було саме те, щоб не ігнорувати сигнал (а зробити його замість нього неоперативним), так що нам не потрібно робити нічого іншого, щоб перервати основну somethingпрограму.
ilkkachu

0

Інший варіант - зробити так, щоб something-that-runs-foreverобробляти сигнал (виходить вишукано, коли він отриманий). Звичайно, це має сенс робити лише тоді, коли ця програма використовується у багатьох сценаріях, а бажана поведінка на CTRL+ Cсистематично однакова - продовжувати виконання сценарію.


ITYM "спати і знову виконувати себе", а не "виходити витончено"?
Toby Speight
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.