[Редактировать: это похоже на некоторые другие вопросы, спрашивающие, как убить все порожденные процессы - ответы, похоже, используют pkill. Таким образом, суть моего вопроса может заключаться в следующем: есть ли способ распространения Ctrl-C / Z на все процессы, созданные скриптом?]
При вызове SoX rec
с помощью timeout
команды из coreutils (обсуждаемой здесь ), кажется, нет никакого способа убить его нажатием клавиши, после того как он был вызван из скрипта Bash.
Примеры:
timeout 10 rec test.wav
... можно убить с помощью Ctrl+ Cили Ctrl+ Zиз bash, но не тогда, когда он вызывается из скрипта.
timeout 10 ping nowhere
... можно убить с помощью Ctrl+ Cили Ctrl+ Zиз bash, и с Ctrl+, Zкогда он запускается из скрипта.
Я могу найти идентификатор процесса и уничтожить его таким образом, но почему я не могу использовать стандартное нажатие клавиши разрыва? И есть ли способ структурировать мой сценарий так, чтобы я мог?
источник
bg
изfg
команд. В любом случае, есть ли разница между вашими 1-м и 3-м примерами?timeout
в моей системе, но уничтожениеsleep
работает независимо от того, набирается ли оно непосредственно в командной строке, происходит из источника, выполняется или явно передается через интерпретаторОтветы:
Сигнальные клавиши, такие как Ctrl+, Cотправляют сигнал всем процессам в группе процессов переднего плана .
В типичном случае группа процессов представляет собой конвейер. Например, в
head <somefile | sort
, запущенный процесс и запущенныйhead
процессsort
находятся в той же группе процессов, что и оболочка, поэтому все они получают сигнал. Когда вы запускаете задание в фоновом режиме (somecommand &
), оно находится в собственной группе процессов, поэтому нажатие Ctrl+ Cне влияет на него.timeout
Программа ставит себя в своей собственной группе процессов. Из исходного кода:Когда происходит таймаут,
timeout
проходит простой способ уничтожения группы процессов, членом которой он является. Поскольку он помещен в отдельную группу процессов, его родительский процесс не будет в группе. Использование здесь группы процессов гарантирует, что если дочернее приложение разветвляется на несколько процессов, все его процессы получат сигнал.Когда вы запускаете
timeout
непосредственно в командной строке и нажимаете Ctrl+ C, результирующий SIGINT принимаетсяtimeout
и дочерним процессом, и не интерактивной оболочкой, которая являетсяtimeout
родительским процессом. Когдаtimeout
вызывается из скрипта, только оболочка, выполняющая скрипт, получает сигнал:timeout
не получает его, поскольку находится в другой группе процессов.Вы можете установить обработчик сигнала в сценарии оболочки с помощью
trap
встроенной функции. К сожалению, не все так просто. Учти это:Если вы нажмете Ctrl+ Cчерез 2 секунды, все 5 секунд будут ждать, а затем напечатайте сообщение «Прервано». Это связано с тем, что оболочка воздерживается от выполнения кода прерывания, когда задание переднего плана активно.
Чтобы исправить это, запустите задание в фоновом режиме. В обработчике сигналов вызовите
kill
для передачи сигнала группеtimeout
процессов.источник
Опираясь на отличный ответ, предоставленный Жилем. Команда timeout имеет опцию переднего плана, если она используется, CTRL + C завершит команду timeout.
источник
timeout
GNU coreutils.В основном Ctrl+ Cотправляет
SIGINT
сигнал, а Ctrl+ Z отправляетSIGTSTP
сигнал.SIGTSTP
просто останавливает процесс, аSIGCONT
продолжит его.Это работает на переднем плане-процесс, который был разветвлен в командной строке.
Если ваш процесс является фоновым процессом, вам придется отправлять этот сигнал другим процессам.
kill
сделаю это. В теории оператор «-» - при этом уничтожении также должен сигнализировать о дочерних процессах, но это редко работает так, как ожидалось.Для дальнейшего чтения: Unix-Signals
источник
Улучшение ответа @Gilles путем предоставления подхода «найти и заменить» для существующих сценариев:
INT
обработчик:timeout
командыmy_timeout
функцией в вашем скрипте.пример
Вот пример сценария:
источник