Пастка "Ctrl + c" для скрипта bash, але не для процесу, відкритого в цьому сценарії


11

Я намагався мати інтерактивну програму в баш-скрипті:

my_program

І я хотів би мати можливість закрити це знаком "Ctrl + c". Але коли я це роблю, мій сценарій також закривається.

Я знаю про.

trap '' 2
my_program
trap 2

Але в цьому випадку я просто не можу закрити my_programCtrl + c.

Чи маєте ви якесь уявлення про те, як дозволити Ctrl + c в програмі, але не закривати запуск сценарію?

EDIT: додайте приклад

#!/bin/bash
my_program
my_program2

Якщо я використовую Ctrl + c для закриття my_program, my_program2він ніколи не виконується, тому що весь сценарій вийшов.

Відповіді:


13

Ви повинні використовувати trap true 2або trap : 2замість цього trap '' 2. Ось що про це говорить "допомога в пастці" в оболонці:

Якщо 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

2
Як щодо вбивства tails, а не вбивства котів наступного разу?
kubanczyk

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в нижній частині, щоб бути трохи ефективнішим.
Toby Speight

@R .. це абсолютно не специфічно для оболонки - якщо ви встановите сигнал на SIG_IGN (саме це робить пастка з порожньою рядком), цей стан буде успадкований через exec (), за винятком SIGCHLD. Це поведінка, зобов'язана POSIX. Дивіться також відповідь на stackoverflow.com/questions/32708086 / ...
mosvy

@mosvy: Я не бачу, з якою частиною мого коментаря ви не згодні. Весь мій сенс полягав у тому, що "маска / ігнорувати перед форк, маскувати / unignore у дитини перед exec" є загальним принципом, який корисно знати поза контекстом просто програмування оболонки.
R .. GitHub СТОП ДОПОМОГА ВІД

1
Це дуже корисна відповідь. Як досвідчений користувач Linux, я можу сказати, що раніше цього не чув. Він має досить багато застосувань ... Ви отримали мою інформацію та мою закладку.
Dev

-1


Коли ви використовуєте Crtl+ C, ви перериваєте програму (" вбиваєте " її).
Напевно, ви шукаєте - призупинити програму (" призупинити " її). Для цього можна використовувати Crtl+ Z.
Коли ваша програма призупинена, ви можете побачити її за допомогою jobs. Наприклад:
[1]+ Stopped ./foobar
Тут у мене є лише одна робота, робота №1, але їх може бути більше - кожна робота має свій номер.
Ви можете керувати призупиненим процесом, використовуючи ряд команд, наприклад bg, fgта kill.
bg %1перезапустить роботу №1 в b ack g раунді
fg %1перезапустить роботу №1 у ф рудіg раунд
kill %1знищить роботу №1.
Зверніть увагу, що ви можете використовувати bgта fgбез аргументів, якщо у вас є лише одна активна робота.


Дякую, але ні, я хочу зробити Ctrl + c.
bob dylan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.