Как убить скрипт, работающий в терминале, не закрывая терминал (Ctrl + C не работает)?

36

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

Ctrl + CЯ думаю, что нажатие иногда не обрезает его, потому что иногда скрипт выполняет другую программу, и по какой-то причине сигнал kill не работает.

Однако, если я закрываю окно терминала, это убивает скрипт.

Есть ли что-то, что я могу сделать (комбинация клавиш), аналогично закрытию окна терминала, без фактического закрытия окна терминала (я не хочу терять историю команд, текущий каталог, историю вывода и т. Д.)?

becko
источник
8
В таких случаях я стараюсьCtrl + z
Kenn
И после Ctrl + zзапуска:kill -9 $(pgrep -f your_script.sh)
Ноам Манос

Ответы:

38

У вас есть несколько вариантов. Один из них - остановить скрипт ( CtrlZ), получить PID скрипта и отправить SIGKILLв группу процессов.

Когда команда выполняется в оболочке, процесс, который она запускает, и все ее дочерние элементы являются частью одной группы процессов (в данном случае, группы процессов переднего плана). Чтобы отправить сигнал всем процессам в этой группе, вы отправляете его руководителю процесса. Для killкоманды лидер процесса обозначается так:

kill -PID

Где PIDнаходится идентификатор процесса скрипта.

Пример:

Рассмотрим скрипт, test.shкоторый запускает некоторые процессы. Скажем, вы запустили его в оболочке:

$ ./test.sh

В другом терминале

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

В этом случае, чтобы отправить сигнал группе процессов, созданной test.sh, вы должны сделать:

kill -INT -17802

-INTиспользуется для отправки SIGINT, и поэтому эта команда эквивалентна нажатию CtrlCна терминал. Отправить SIGKILL:

kill -KILL -17802

Вам нужно остановить скрипт, только если вы не можете открыть другой терминал. Если вы можете, используйте, pgrepчтобы найти PID.

Одной из команд, запускаемых сценарием, может быть прерывание SIGINT, поэтому, вероятно, CtrlCоно неэффективно. Тем SIGKILLне менее, не может быть пойман в ловушку, и это, как правило, последний вариант. Возможно, вы захотите попробовать SIGTERM( -TERM), прежде чем идти на убийство. Ни SIGKILLили SIGTERMне может быть установлен как клавиатура ярлыка пути SIGINTесть.

Все это спорный вопрос , если ваш сценарий не содержит притон линии. Из этого так ответьте :

Обычно родительская оболочка предполагает, что сценарий написан для той же оболочки (минимальные оболочки типа Борна запускают сценарий с / bin / sh, bash запускает его как подпроцесс bash) ...

Из-за этого при выполнении сценария вы не найдете процесс, названный в соответствии со сценарием (или процесс с именем сценария в командной строке), и pgrepпроизойдет сбой.

Всегда используйте линию Шебанга.

Мур
источник
Есть ли комбинация клавиш для SIGKILLили SIGTERM?
Бекко
@becko Нет, и вы не можете настроить один: superuser.com/a/417991/334516
Muru
pgrep test.shне возвращает PID для меня. Я попробовал простой test.sh: во for i in {1..30}; do sleep 1 echo $i done время test.shработы я выполняю pgrep test.shв другом терминале, но ничего не возвращается. В чем дело?
Бекко
1
@becko как ты запустил скрипт? Также попробуйте pgrep -f test.sh.
Муру
pgrep -f test.shтоже не работает Я запускаю сценарий с./test.sh
becko
6

Если вы знаете процессы, связанные со сценарием, вы можете найти их PID, используя

 ps -A

а затем использовать номер PID, чтобы убить соответствующие процессы, используя

 kill -9 PID_Number
Харрис
источник
1
Это слишком сложно. Сценарий порождает несколько других программ, и эти программы также порождают параллельные процессы. Очень сложно отслеживать все эти процессы. Должно быть более простое решение, аналогичное тому, что происходит при закрытии окна терминала.
becko
Можете ли вы попробовать pkill -P $$
Harris
1

Как сказал Харрис, вы можете запустить, Kill -9 PID_Numberно вы также можете установить пакет, известный как htopинтерактивный браузер процессов, который значительно упрощает поиск определенных процессов. htop также поддерживает процессы уничтожения.

Бульбазаур лишен сна
источник