Почему удар Управляет + C, когда в приложении, запущенном из сценария, повредите сценарий?

Переходить прямо в:

while true; do
    #---  MENU LOGIC HERE, stick response in $MENUEXIT

    #----Deal with responses here

    if [ $S1 == $MENUEXIT ];
    then
            tail -f /path-to-file
    else
            sleep 2
    fi
done

Я попытался сохранить это максимально простым, если Вам нужен больше, сообщить мне.

В основном я прикрепляю меню в цикл, таким образом, если существует неправильный ввод данных пользователем, или команда заканчивается, это предназначено, чтобы вновь отобразить меню.

Это хорошо работало, пока я не добавил команду хвоста.

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

Я попробовал различные вещи те, которые продолжают/захватывают и больше, но, я врезался в кирпичную стену и хотел бы некоторую справку?!

3
задан 9 August 2014 в 05:59

1 ответ

Когда Вы отправляете сигнал как SIGINT (CtrlC) или SIGSTOP (CtrlZ) от терминала, сигнал отправляется группе приоритетного процесса. Таким образом, группа, включающая задание переднего плана (Ваш сценарий), и любые дочерние процессы, это имеет на переднем плане ( tail команда). Это заставляет все эти процессы выходить (или сделать независимо от того, что это, они делают путем обработки сигнала). Можно протестировать различие путем отправки сигнала с помощью kill команда:

В одном терминале выполните этот сценарий (я называю его test в следующих командах):

#! /bin/bash

while true
do
    if [[ $1 = a ]]
    then
        yes 
    else
        echo no
        sleep 2
    fi
done

В другом выполните эти команды:

pstree -ps $(pgrep -f test)
pkill -f test
pstree -ps $(pgrep -f yes)

Вывод команд был бы чем-то вроде этого:

init(1)───lightdm(1032)───lightdm(1154)───init(1173)───x-terminal-emul(17009)───bash(24262)───test.sh(24996)───yes(24997)
# No output for pkill
init(1)───lightdm(1032)───lightdm(1154)───init(1173)───yes(24997)

(Фактические числа и программы могут варьироваться, но первый init будет всегда иметь pid 1.)
Как Вы видите, yes команда не была уничтожена и была присоединена к init потому что его родитель был уничтожен. Это все еще весело печатает ys на первом терминале. Поэтому уничтожьте его с pkill -f yes. Теперь повторите эксперимент с одним изменением. Вместо pkill -f test, сделайте:

kill -INT -25165 
# Use the pid of test.sh given in parentheses in the output of pstree 
# instead of 25165

Отметьте продвижение -. В Linux, для kill команда, -25165 группа процесса, у лидера которой есть pid 25165. Таким образом эта команда является эквивалентом отправки прерывания от терминала.

Конечно, точное поведение зависит от конфигурации TTY, оболочка входа в систему и так далее. Это насколько мое понимание идет.Дальнейшее чтение:


Я предлагаю:

  1. Отправка tail к фону
  2. Захватите сигнал
  3. Уничтожьте фоновый процесс.
  4. Удалите прерывание

Пример:

#! /bin/bash

kill_jobs ()
{
    kill %1
}

while true
do
    if [[ $1 = "a" ]]
    then
        trap kill_jobs INT
        tail -f /var/log/syslog &
        wait %%
        shift #You don't need to shift, I just didn't want loop tail on this example
        trap - INT
    else
        echo some output
        sleep 2
    fi
done

Это может стать очень мощным, при помощи различных функций для захвата и каждого выполнения их собственной работы уборки.

7
ответ дан 17 November 2019 в 19:32

Другие вопросы по тегам:

Похожие вопросы: