2015-11-03 11 views
1

Я пытаюсь обработать прерывание SIGINT/CTRL + C таким образом, что если пользователь случайно нажимает ctrl-c, ему будет предложено сообщение: «Вы хотите выйти? (Y/n)». Если он войдет в «Да», выйдите из сценария. Если нет, то продолжайте с того места, где произошло прерывание. В принципе, мне нужно Ctrl-C работать аналогично Ctrl-Z/SINTSTP, но несколько иначе. Я пробовал различные способы, чтобы добиться этого, но я не получил ожидаемых результатов. Ниже приводится несколько сценариев, которые я пробовал.Как я могу обработать ловушку SIGINT с приглашением пользователя в сценарии оболочки?

Корпус: 1

Сценарий: play.sh

#!/bin/sh 
function stop() 
{ 
while true; do 
    read -rep $'\nDo you wish to stop playing?(y/n)' yn 
    case $yn in 
     [Yy]*) echo "Thanks for playing !!!"; exit 1;; 
     [Nn]*) break;; 
     *) echo "Please answer (y/n)";; 
    esac 
done 
} 
trap 'stop' SIGINT 
echo "going to sleep" 
for i in {1..100} 
do 
    echo "$i" 
    sleep 3 
done 
echo "end of sleep" 

Когда я бегу выше сценарий, я получаю ожидаемых результатов.

Выход:

$ play.sh 
    going to sleep 
    1 
    ^C 
    Do you wish to stop playing?(y/n)y 
    Thanks for playing !!! 

    $ play.sh 
    going to sleep 
    1 
    2 
    ^C 
    Do you wish to stop playing?(y/n)n 
    3 
    4 
    ^C 
    Do you wish to stop playing?(y/n)y 
    Thanks for playing !!! 
    $ 

Корпус: 2 Я переехал цикл на новый скрипт loop.sh, таким образом, становится play.sh родительский процесс и loop.sh ребенка обработать.

Сценарий: play.sh

#!/bin/sh 
function stop() 
{ 
while true; do 
    read -rep $'\nDo you wish to stop playing?(y/n)' yn 
    case $yn in 
     [Yy]*) echo "Thanks for playing !!!"; exit 1;; 
     [Nn]*) break;; 
     *) echo "Please answer (y/n)";; 
    esac 
done 
} 
trap 'stop' SIGINT 
loop.sh 

Сценарий: loop.sh

#!/bin/sh 
echo "going to sleep" 
for i in {1..100} 
do 
    echo "$i" 
    sleep 3 
done 
echo "end of sleep" 

Выход в данном случае не как ожидалось.

Выход:

$ play.sh 
going to sleep 
1 
2 
^C 
Do you wish to stop playing?(y/n)y 
Thanks for playing !!! 

$ play.sh 
going to sleep 
1 
2 
3 
4 
^C 
Do you wish to stop playing?(y/n)n 
$ 

Я понимаю, что когда процесс получает сигнал SIGINT, он распространяется сигнал на все дочерние процессы, таким образом, мой второй случай терпит неудачу. Есть ли способ, которым я могу избежать распространения SIGINT на дочерние процессы и, таким образом, сделать цикл loop.sh так же, как он работал в первом случае?

Примечание:Это всего лишь пример моего фактического применения. Приложение, в котором я работаю, имеет несколько дочерних скриптов в play.sh и loop.sh. Я должен убедиться, что приложение при получении SIGINT не должно заканчиваться, но оно должно запрашивать у пользователя сообщение.

+0

дубликат: http://unix.stackexchange.com/q/240602/4667 –

ответ

1

В вашей play.sh не вызвать новый сценарий, но источник его так:

source ./loop.sh 

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