Ловушка Ctrl + C для скрипта bash, но не для процесса, открытого в этом скрипте

11

Я пытался создать интерактивную программу в скрипте bash:

my_program

И я хочу иметь возможность закрыть его с помощью Ctrl + C. Но когда я это делаю, мой скрипт тоже закрывается.

Я знаю о.

trap '' 2
my_program
trap 2

Но в этом случае я просто не могу закрыть my_programс помощью Ctrl + c.

У вас есть идея, как разрешить Ctrl + C в программе, но не закрывать скрипт, выполняющий ее?

РЕДАКТИРОВАТЬ: добавить пример

#!/bin/bash
my_program
my_program2

Если я использую Ctrl + C, чтобы закрыть my_program, my_program2никогда не выполняется, потому что весь сценарий завершен.

Боб Дилан
источник

Ответы:

13

Вы должны использовать trap true 2или trap : 2вместо trap '' 2. Вот что говорит «ловушка помощи» в оболочке bash:

Если ARG является пустой строкой, то каждый SIGNAL_SPEC игнорируется оболочкой и вызываемыми командами .

Пример:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done
mosvy
источник
2
Как насчет убийства tails вместо убийства кошек в следующий раз?
Кубанчик
12

Вы можете сбросить ловушку по умолчанию, указав команду trap в -качестве аргумента действия. Если вы сделаете это в подоболочке , это не повлияет на ловушку в родительской оболочке. В вашем скрипте вы можете сделать это для каждой команды, которую нужно прервать с помощью Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.
Марк Плотник
источник
1
Хотя принятый ответ, вероятно, лучше и более каноничен для оболочки, сам по себе он является отличным ответом, поскольку он вводит общий принцип (не специфичный для оболочки), касающийся того, как безопасно выполнять / игнорировать такого рода сигналы.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
Я думаю, что вы можете exec my_programв подоболочке быть немного более эффективным.
Тоби Спейт
@R .. это абсолютно не зависит от оболочки - если вы установите сигнал в SIG_IGN (это то, что делает ловушка с пустой строкой), это состояние будет наследоваться через exec (), за исключением SIGCHLD. Это обязательное поведение POSIX. См. Также ответ на stackoverflow.com/questions/32708086/…
mosvy
@mosvy: я не вижу, с какой частью моего комментария вы не согласны. Все, что я хотел сказать, это то, что «маска / игнорирование перед fork, unmask / unignore в потомке перед exec» - это общий принцип, который полезно знать вне контекста простого программирования оболочки.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
1
Это очень полезный ответ. Как опытный пользователь Linux, я могу сказать, что никогда не слышал об этом раньше. У него довольно много применений ... ты получил мое возражение и мою закладку.
Девятого
-1


Когда вы используете Crtl+ C, вы прерываете программу (« убиваете » ее).
То, что вы, вероятно, ищете, это приостановить вашу программу (« приостановить » ее). Для этого вы можете использовать Crtl+ Z.
Как только ваша программа приостановлена, вы можете увидеть ее, используя jobs. Например:
[1]+ Stopped ./foobar
здесь у меня есть только одно задание, задание №1, но их может быть несколько - у каждого задания свой номер.
Вы можете контролировать приостановленный процесс с помощью ряда команд, например bg, fgи kill.
bg %1перезапустит работу # 1 в б извед г круглый
fg %1перезапуск работы # 1 в ф рудег раунд
kill %1убьет JOB # 1
Обратите внимание , что вы можете использовать bgи fgбез каких - либо аргументов , если у вас есть только одна активной работы.

pi0tr
источник
Спасибо, но нет, я хочу сделать Ctrl + c.
Боб Дилан