Bash: наконец (попробуй, кроме) исключение - PullRequest
3 голосов
/ 22 октября 2010

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

Я знаю, что могу запустить скрипт bash из другого языка программирования (например, Python), чтобы я мог использовать блок finally (try-finally) для выполнения некоторого кода.

Но, зная, что StackOverflow является центром обмена невероятными идеями, я спрашиваю, есть ли способ сделать то, что я хочу, из моего скрипта bash.

Итак, идеи?

EDIT:

Мне нужно уничтожить все процессы, открытые в моем bash, то есть процессы Selenium и Xvfb.

Я пытался записать это в код:

 trap "selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}');for pid in $selenium_pids; do kill -9 $pid;done; xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}'); for pid in $xvfb_pids; do kill -9 $pid; done" EXIT

Но это обязывает меня многократно нажимать "CTRL + C" при каждом запуске подпроцесса из моего скрипта, что-то вроде:

Testing nsi.bd.helpcenter ...^C:  --  Total time: 0min 0seg
Testing nsi.bibliography ...^C:  --  Total time: 0min 0seg
Testing nsi.digitallibrary ...^C:  --  Total time: 0min 0seg
Testing nsi.digitallibraryinstaller ...^C:  --  Total time: 0min 1seg
Testing nsi.digitallibraryskins ...^C:  --  Total time: 0min 0seg
....#continues

Изменение финала строки ловушки с EXIT на SIGINT, например так:

trap "selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}');for pid in $selenium_pids; do kill -9 $pid;done; xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}'); for pid in $xvfb_pids; do kill -9 $pid; done" SIGINT

Делает то же самое.

Что теперь выходить по первому CTRL + C?

Потому что я пытался добавить «выход 1» в финал строки, например trap "... ;exit 1"

Он работал, чтобы выйти на первом CTRL + C, но не убивал процессы, которые я хотел.

Идеи

Ответы [ 2 ]

8 голосов
/ 22 октября 2010

Получил то, что хотел с этим кодом:

finalize_xvfb_and_selenium() {
    selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}')
    for pid in $selenium_pids; do 
        kill -9 $pid
    done 
    xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}') 
    for pid in $xvfb_pids; do 
        kill -9 $pid
    done
}

finalize_xvfb_and_selenium_and_exit() {
    finalize_xvfb_and_selenium
    echo -e "\n\nXvfb and seleniumrc finalized. Exiting ..."
    exit 13
}

#trap (CTRL+C) signal, to finalize proccess running before exit
trap finalize_xvfb_and_selenium_and_exit SIGINT

Я знаю, что есть лучшие ресурсы, чем везде kill -9.

6 голосов
/ 22 октября 2010

Вы хотите перехватывать сигналы.

Когда пользователь нажимает control-c на терминале, ОС выдает SIGINT текущему процессу. Этот сигнал можно поймать и обработать. Как это сделать, зависит от оболочки, и вы должны проверить страницу справки по оболочке.

Обратите внимание, что некоторые сигналы не могут быть перехвачены. Особенно SIGKILL, который kill -9 посылает.


В свете редактирования: bash может вернуть идентификатор процесса запускаемых вами программ. Можно было бы захватить их все по ходу, чтобы вам не приходилось анализировать вывод ps. Вы также можете подумать о том, чтобы отправить своим детям какой-то другой сигнал (возможно, SIGUSR1), уже установив ловушку, чтобы они рекурсивно убивали своих детей.

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

...