2017-01-06 2 views
3

В bash я могу получить идентификатор процесса (pid) последнего подпроцесса через переменную $!. Затем я могу убить этот подпроцесс до его завершения:Bash: Уничтожение всех процессов в подпроцессе

(sleep 5) & pid=$! 
kill -9 $pid 

Это работает как рекламируется. Если теперь я продолжу подпроцесс с дополнительными командами после sleep, команда sleep будет продолжена после того, как подпроцесс будет убит, хотя другие команды никогда не будут выполнены.

В качестве примера, рассмотрим следующее, который раскручивает подпроцесс и следить за его убийство с помощью ps:

# Start subprocess and get its pid 
(sleep 5; echo done) & pid=$! 

# grep for subprocess 
echo "grep before kill:" 
ps aux | grep "$pid\|sleep 5" 

# Kill the subprocess 
echo 
echo "Killing process $pid" 
kill -9 $pid 

# grep for subprocess 
echo 
echo "grep after kill:" 
ps aux | grep "$pid\|sleep 5" 

# Wait for sleep to finish 
sleep 6 

# grep for subprocess 
echo 
echo "grep after sleep is finished:" 
ps aux | grep "$pid\|sleep 5" 

Если я сохранить это в файл с именем filename и запустить его, я получаю эту распечатку:

grep before kill: 
username 7464 <...> bash filename 
username 7466 <...> sleep 5 
username 7467 <...> grep 7464\|sleep 5 

Killing process 7464 

grep after kill: 
username 7466 <...> sleep 5 
username 7469 <...> grep 7464\|sleep 5 

grep after sleep is finished: 
username 7472 <...> grep 7464\|sleep 5 

, где несущественная информация из команды ps заменяется на <...>. Похоже, что kill убил общее выполнение bash filename, оставив sleep бег.

Как я могу правильно убить весь подпроцесс?

+0

Подсказка: он все еще там? –

+0

@ KarolyHorvath Что еще там? –

ответ

1

Вы можете установить ловушку в субоболочке убить все активные рабочие места до выхода:

(trap 'kill $(jobs -p)' EXIT; sleep 5; echo done) & pid=$! 
+0

Это не работает для меня. Что означает 'jobs -p', который должен выводиться? Когда я запускаю его, он ничего не выводит. –

+0

Ах, я забыл упомянуть один важный момент: вам не нужно использовать 'kill -9', потому что это заставляет ОС немедленно убивать процесс *, не давая ему возможности запускать обработчик' EXIT'. достаточно «убить». – chepner

+0

'jobs -p' перечисляет идентификаторы процессов всех текущих активных заданий, управляемых оболочкой. – chepner

1

Вы можете посмотреть на rkill, который, кажется, чтобы удовлетворить ваши требования:

http://www.unix.com/man-page/debian/1/rkill/

RKill [-SIG] PID/имя ...

При вызове в качестве RKill, это Утилита не отображает информацию о процессах, но отправляет им все сигналы. Если в командной строке не указано, отправляется сигнал завершения (SIGTERM).

+0

Работы, хотя 'rkill' /' pslist', похоже, не являются стандартным инструментом, установленным на большинстве Linux-систем. –

1

Я не знаю, почему именно этот процесс сна становится ненужным, так или иначе, а не убивать вы можете использовать pkill с -Р флаг также убить всех детей

pkill -TERM -P $pid 

EDIT: это означает, что для того, чтобы убить процесс и все это дети, вы должны использовать вместо этого

CPIDS=`pgrep -P $pid` # gets pids of child processes 
kill -9 $pid 
for cpid in $CPIDS ; do kill -9 $cpid ; done 
+0

Корпуса обычно не посылают сигналы, которые они получают своим детям. Но это не очевидно, потому что на терминале, если вы запустите сон, ребенок получает сигнал напрямую. –

+0

Это убивает 'sleep', но интересно, что' echo done' запускается. Я могу исправить это, объединив команды в подпроцессе вместе с '&&' вместо ';', что приведет к рабочему решению. –

+0

@jmd_dk - Я был на самом деле неправ, когда я сказал, что он убивает ** также ** убивает всех детей, на самом деле убивает только всех детей, я отредактирую свой ответ – MacHala

Смежные вопросы