Каков наилучший способ отправить сигнал всем членам группы процессов?
Я хочу убить целое дерево процессов. Каков наилучший способ сделать это, используя любые общие языки сценариев? Я ищу простое решение.
30 ответов
вы не говорите, является ли дерево, которое вы хотите убить, одной группой процессов. (Это часто бывает, если дерево является результатом разветвления от запуска сервера или командной строки оболочки.) Вы можете обнаружить группы процессов с помощью GNU ps следующим образом:
ps x -o "%p %r %y %x %c "
Если это группа процессов, которую вы хотите убить, просто используйте kill(1)
команда, но вместо того, чтобы дать ему номер процесса, дайте ему отрицание номер группы. Например, чтобы убить любой процесс в группе 5112, использовать kill -TERM -- -5112
.
убить все процессы, принадлежащие одному и тому же дерево процессов С помощью ID группы процессов (PGID
)
-
kill -- -$PGID
использовать сигнал по умолчанию (TERM
= 15) -
kill -9 -$PGID
использовать сигналKILL
(9)
вы можете получить PGID
любой Process-ID (PID
) из той же
-
kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*')
(сигналTERM
) -
kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*')
(сигналKILL
)
отдельное спасибо танагра и Speakus взносы $PID
оставшиеся пробелы и совместимость с OSX.
объяснение
-
kill -9 -"$PGID"
=> отправить сигнал 9 (KILL
) для всех детей и внук... -
PGID=$(ps opgid= "$PID")
=> получить Process-Group-ID любой Process-ID дерева, а не только Process-Parent-ID. Вариацияps opgid= $PID
isps -o pgid --no-headers $PID
здесьpgid
можно заменить наpgrp
.
но: -
grep -o [0-9]*
печатает только последовательные цифры (не печатает пробелы или алфавитные заголовки).
дополнительные команды линии
PGID=$(ps -o pgid= $PID | grep -o [0-9]*)
kill -TERM -"$PGID" # kill -15
kill -INT -"$PGID" # correspond to [CRTL+C] from keyboard
kill -QUIT -"$PGID" # correspond to [CRTL+\] from keyboard
kill -CONT -"$PGID" # restart a stopped process (above signals do not kill it)
sleep 2 # wait terminate process (more time if required)
kill -KILL -"$PGID" # kill -9 if it does not intercept signals (or buggy)
ограничение
- как заметил на и Юбер Карио, когда
kill
вызывается процессом, принадлежащим к тому же дереву,kill
рискует убить себя, прежде чем прекратить убийство всего дерева. - поэтому не забудьте запустить команду, используя процесс, имеющий другой Process-Group-ID.
долгая история
> cat run-many-processes.sh
#!/bin/sh
echo "ProcessID=$$ begins ()"
./child.sh background &
./child.sh foreground
echo "ProcessID=$$ ends ()"
> cat child.sh
#!/bin/sh
echo "ProcessID=$$ begins ()"
./grandchild.sh background &
./grandchild.sh foreground
echo "ProcessID=$$ ends ()"
> cat grandchild.sh
#!/bin/sh
echo "ProcessID=$$ begins ()"
sleep 9999
echo "ProcessID=$$ ends ()"
запустите дерево процессов в фоновом режиме с помощью '&'
> ./run-many-processes.sh &
ProcessID=28957 begins (./run-many-processes.sh)
ProcessID=28959 begins (./child.sh)
ProcessID=28958 begins (./child.sh)
ProcessID=28960 begins (./grandchild.sh)
ProcessID=28961 begins (./grandchild.sh)
ProcessID=28962 begins (./grandchild.sh)
ProcessID=28963 begins (./grandchild.sh)
> PID=$! # get the Parent Process ID
> PGID=$(ps opgid= "$PID") # get the Process Group ID
> ps fj
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
28348 28349 28349 28349 pts/3 28969 Ss 33021 0:00 -bash
28349 28957 28957 28349 pts/3 28969 S 33021 0:00 \_ /bin/sh ./run-many-processes.sh
28957 28958 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./child.sh background
28958 28961 28957 28349 pts/3 28969 S 33021 0:00 | | \_ /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3 28969 S 33021 0:00 | | | \_ sleep 9999
28958 28963 28957 28349 pts/3 28969 S 33021 0:00 | | \_ /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3 28969 S 33021 0:00 | | \_ sleep 9999
28957 28959 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./child.sh foreground
28959 28960 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3 28969 S 33021 0:00 | | \_ sleep 9999
28959 28962 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3 28969 S 33021 0:00 | \_ sleep 9999
28349 28969 28969 28349 pts/3 28969 R+ 33021 0:00 \_ ps fj
команда pkill -P $PID
не убивает внука:
> pkill -P "$PID"
./run-many-processes.sh: line 4: 28958 Terminated ./child.sh background
./run-many-processes.sh: line 4: 28959 Terminated ./child.sh foreground
ProcessID=28957 ends (./run-many-processes.sh)
[1]+ Done ./run-many-processes.sh
> ps fj
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
28348 28349 28349 28349 pts/3 28987 Ss 33021 0:00 -bash
28349 28987 28987 28349 pts/3 28987 R+ 33021 0:00 \_ ps fj
1 28963 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
1 28962 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
1 28961 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
1 28960 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
команда kill -- -$PGID
убивает все процессы, включая внука.
> kill -- -"$PGID" # default signal is TERM (kill -15)
> kill -CONT -"$PGID" # awake stopped processes
> kill -KILL -"$PGID" # kill -9 to be sure
> ps fj
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
28348 28349 28349 28349 pts/3 29039 Ss 33021 0:00 -bash
28349 29039 29039 28349 pts/3 29039 R+ 33021 0:00 \_ ps fj
вывод
я замечаю в этом примере PID
и PGID
равны (28957
).
Вот почему я первоначально думал kill -- -$PID
было достаточно. Но в случае, если процесс происходит в пределах a Makefile
the идентификатор процесса отличается от ID группы.
я думаю kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)
это лучший простой трюк, чтобы убить целое дерево процессов при вызове из другого ID группы (другое дерево процессов).
pkill -TERM -P 27888
Это убьет все процессы, которые имеют идентификатор родительского процесса 27888.
или более надежные:
CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS
который график убийства 33 секунд спустя и вежливо попросить процессы прекратить.
посмотреть ответ для прекращения всех потомков.
чтобы рекурсивно убить дерево процессов, используйте killtree ():
#!/bin/bash
killtree() {
local _pid=
local _sig=${2:--TERM}
kill -stop ${_pid} # needed to stop quickly forking parent from producing children between child killing and parent killing
for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
killtree ${_child} ${_sig}
done
kill -${_sig} ${_pid}
}
if [ $# -eq 0 -o $# -gt 2 ]; then
echo "Usage: $(basename ) <pid> [signal]"
exit 1
fi
killtree $@
rkill С программа pslist пакет посылает данный сигнал (или SIGTERM
по умолчанию) для указанного процесса и всех его потомков:
rkill [-SIG] pid/name...
бред-это то, что я бы тоже рекомендовал, за исключением того, что вы можете покончить с awk
в целом, если вы используете до ps
.
for child in $(ps -o pid -ax --ppid $PPID) do ....... done
Если вы знаете, передайте pid родительского процесса, вот сценарий оболочки, который должен работать:
for child in $(ps -o pid,ppid -ax | \
awk "{ if ( $2 == $pid ) { print $1 }}")
do
echo "Killing child process $child because ppid = $pid"
kill $child
done
Я использую немного измененную версию метода, описанного здесь: https://stackoverflow.com/a/5311362/563175
Так выглядит так:
kill `pstree -p 24901 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*//' | tr "\n" " "`
где 24901-Родительский PID.
это выглядит довольно уродливо, но делает это отлично.
измененная версия ответа Чжигана:
#!/usr/bin/env bash
set -eu
killtree() {
local pid
for pid; do
kill -stop $pid
local cpid
for cpid in $(pgrep -P $pid); do
killtree $cpid
done
kill $pid
kill -cont $pid
wait $pid 2>/dev/null || true
done
}
cpids() {
local pid= options=${2:-} space=${3:-}
local cpid
for cpid in $(pgrep -P $pid); do
echo "$space$cpid"
if [[ "${options/a/}" != "$options" ]]; then
cpids $cpid "$options" "$space "
fi
done
}
while true; do sleep 1; done &
cpid=$!
for i in $(seq 1 2); do
cpids $$ a
sleep 1
done
killtree $cpid
echo ---
cpids $$ a
чтобы добавить к ответу Нормана Рэмси, возможно, стоит посмотреть на setsid, если вы хотите создать процесс group.
http://pubs.opengroup.org/onlinepubs/009695399/functions/setsid.html
функция setsid() должна создать новый сеанс, если вызывающий процесс не руководитель группы процессов. На возврат вызывающего процесса должен быть лидер сессии нового сессия, будет группой процесса лидером новой группы процессов , и не имеет управляющего терминала. Идентификатор группы процессов вызова процесс устанавливается равным идентификатор вызывающего процесса. Этот вызывающий процесс должен быть единственным процесса в группе процессов и единственный процесс в новом сеансе.
что, как я понимаю, означает, что вы можете создать группу из начального процесса. Я использовал это в php, чтобы иметь возможность убить целое дерево процессов после его запуска.
Это может быть плохо идея. Меня интересуют комментарии.
Я не могу комментировать (не хватает репутации), поэтому я вынужден добавить новый ответ, хотя это на самом деле не ответ.
есть небольшая проблема с в противном случае очень хорошим и тщательным ответом, данным @olibre 28 февраля. Выход ps opgid= $PID
будет содержать начальные пробелы для PID короче пяти цифр, потому что ps
оправдывает столбец (rigth выравнивает числа). В пределах всей командной строки это приводит к отрицательному знаку, за которым следует пробел(ы), за которым следует группа PID. Простое решение-труба ps
to tr
удалять пробелы:
kill -- -$( ps opgid= $PID | tr -d ' ' )
вдохновленный комментарий ysth
kill -- -PGID
вместо того, чтобы давать ему номер процесса, дайте ему отрицание группы число. Как обычно с почти любой командой, если вы хотите нормальный аргумент, который начинается с
-
чтобы не интерпретироваться как переключатель, предшествуйте ему с--
следующая функция оболочки похожа на многие другие ответы, но она работает как на Linux, так и на BSD (OS X и т. д.) без внешних зависимостей, таких как pgrep
:
killtree() {
local parent= child
for child in $(ps -o ppid= -o pid= | awk "$1==$parent {print $2}"); do
killtree $child
done
kill $parent
}
это очень легко сделать с помощью python, используя psutil. Просто установите psutil с pip, а затем у вас есть полный набор инструментов манипуляции процессом:
def killChildren(pid):
parent = psutil.Process(pid)
for child in parent.get_children(True):
if child.is_running():
child.terminate()
основываясь на ответе Чжигана, это позволяет избежать самоубийства:
init_killtree() {
local pid= child
for child in $(pgrep -P $pid); do
init_killtree $child
done
[ $pid -ne $$ ] && kill -kill $pid
}
Если вы хотите убить процесс по имени:
killall -9 -g someprocessname
или
pgrep someprocessname | xargs pkill -9 -g
Это моя версия убийства всех дочерних процессов с помощью сценария bash. Он не использует рекурсию и зависит от команды pgrep.
использовать
killtree.sh PID SIGNAL
содержание killtrees.sh
#!/bin/bash
PID=
if [ -z $PID ];
then
echo "No pid specified"
fi
PPLIST=$PID
CHILD_LIST=`pgrep -P $PPLIST -d,`
while [ ! -z "$CHILD_LIST" ]
do
PPLIST="$PPLIST,$CHILD_LIST"
CHILD_LIST=`pgrep -P $CHILD_LIST -d,`
done
SIGNAL=
if [ -z $SIGNAL ]
then
SIGNAL="TERM"
fi
#do substring from comma to space
kill -$SIGNAL ${PPLIST//,/ }
вот вариант ответа @zhigang, который делает без AWK, полагаясь только на собственные возможности синтаксического анализа Bash:
function killtree {
kill -STOP ""
ps -e -o pid= -o ppid= | while read -r pid ppid
do
[[ $ppid = ]] || continue
killtree "$pid" || true # Skip over failures
done
kill -CONT ""
kill -TERM ""
}
похоже, он отлично работает как на Mac, так и на Linux. В ситуациях, когда вы не можете полагаться на возможность управлять группами процессов-например, при написании сценариев для тестирования программного обеспечения, которое должно быть построено в нескольких средах, - эта техника ходьбы по деревьям определенно полезна.
вероятно, лучше убить родителя перед детьми; в противном случае родитель может, вероятно, снова породить новых детей, прежде чем он сам убьет. Они переживут убийство.
моя версия ps отличается от приведенной выше; возможно, слишком старая, поэтому странная grepping...
использование сценария оболочки вместо функции оболочки имеет много преимуществ...
однако, это в основном идея zhigangs
#!/bin/bash
if test $# -lt 1 ; then
echo >&2 "usage: kiltree pid (sig)"
fi ;
_pid=
_sig=${2:-TERM}
_children=$(ps j | grep "^[ ]*${_pid} " | cut -c 7-11) ;
echo >&2 kill -${_sig} ${_pid}
kill -${_sig} ${_pid}
for _child in ${_children}; do
killtree ${_child} ${_sig}
done
следующее было протестировано на FreeBSD, Linux и MacOS X и зависит только от pgrep и kill (версии ps-o не работают под BSD). Первый аргумент-Родительский pid, дочерние элементы которого должны быть завершены. второй аргумент является логическим, чтобы определить, должен ли Родительский pid быть также завершен.
KillChilds() {
local pid=""
local self="${2:-false}"
if children="$(pgrep -P "$pid")"; then
for child in $children; do
KillChilds "$child" true
done
fi
if [ "$self" == true ]; then
kill -s SIGTERM "$pid" || (sleep 10 && kill -9 "$pid" &)
fi
}
KillChilds $$ > /dev/null 2>&1
это отправит SIGTERM любому процессу ребенка / внука в сценарии оболочки, и если SIGTERM не удастся, он будет ждать 10 секунд, а затем отправить убивать.
ранее в ответ:
следующее также работает, но убьет саму оболочку на BSD.
KillSubTree() {
local parent=""
for child in $(ps -o pid=$parent); do
if [ $$ -ne $child ]; then (kill -s SIGTERM $child || (sleep 10 && kill -9 $child & )) > /dev/null 2>&1 ; fi
done
}
# Example lanch from within script
KillSubTree $$ > /dev/null 2>&1
Я разрабатываю решение zhigang, xyuri и solidsneck дальше:
#!/bin/bash
if test $# -lt 1 ; then
echo >&2 "usage: kiltree pid (sig)"
exit 1 ;
fi ;
_pid=
_sig=${2:-TERM}
# echo >&2 "killtree($_pid) mypid = $$"
# ps axwwf | grep -6 "^[ ]*$_pid " >&2 ;
function _killtree () {
local _children
local _child
local _success
if test -eq ; then # this is killtree - don't commit suicide!
echo >&2 "killtree can´t kill it´s own branch - some processes will survive." ;
return 1 ;
fi ;
# this avoids that children are spawned or disappear.
kill -SIGSTOP ;
_children=$(ps -o pid --no-headers --ppid ) ;
_success=0
for _child in ${_children}; do
_killtree ${_child} ;
_success=$(($_success+$?)) ;
done ;
if test $_success -eq 0 ; then
kill -
fi ;
# when a stopped process is killed, it will linger in the system until it is continued
kill -SIGCONT
test $_success -eq 0 ;
return $?
}
_killtree $$ $_pid $_sig
эта версия будет избегать убийства своей родословной , что вызывает поток дочерних процессов в предыдущих решениях.
процессы правильно останавливаются перед определением дочернего списка, так что новые дочерние элементы не создаются и не исчезают.
после смерти остановленные задания должны продолжать исчезать из системы.
старый вопрос, я знаю, но все ответы, кажется, продолжают называть ps, что мне не понравилось.
это решение на основе awk не требует рекурсии и вызывает ps только один раз.
awk 'BEGIN {
p=1390
while ("ps -o ppid,pid"|getline) a[]=a[]" "
o=1
while (o==1) {
o=0
split(p, q, " ")
for (i in q) if (a[q[i]]!="") {
p=p""a[q[i]]
o=1
a[q[i]]=""
}
}
system("kill -TERM "p)
}'
или в одной строке:
awk 'BEGIN {p=1390;while ("ps -o ppid,pid"|getline) a[]=a[]" ";o=1;while (o==1) {o=0;split(p, q, " ");for (i in q) {if (a[q[i]]!="") {p=p""a[q[i]];o=1;a[q[i]]=""}}}system("kill -TERM "p)}'
В основном идея заключается в том, что мы создаем массив (a) записей parent:child, а затем обводим массив, находя детей для наших соответствующих родителей, добавляя их в список родителей (p) по мере продвижения.
Если вы не хотите убейте процесс верхнего уровня, а затем сделайте
sub(/[0-9]*/, "", p)
непосредственно перед тем, как строка system () удалит ее из набора убийств.
имейте в виду, что здесь есть расовое условие, но это верно (насколько я могу видеть) для всех решений. Он делает то, что мне нужно, потому что сценарий, для которого он нужен, не создает много недолговечных детей.
упражнение для читателя было бы сделать его циклом 2-pass: после первого прохода отправьте SIGSTOP всем процессам в список p, затем цикл для запуска ps снова и после второго прохода отправить SIGTERM, затем SIGCONT. Если вы не заботитесь о хороших концовках, то второй проход может быть просто SIGKILL, я полагаю.
Я знаю, что это старый, но это лучшее решение, которое я нашел:
killtree() {
for p in $(pstree -p | grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*" | tac);do
echo Terminating: $p
kill $p
done
}
Спасибо за вашу мудрость, люди. Мой скрипт оставлял некоторые дочерние процессы на выходе и отрицание совет сделал вещи легче. Я написал эту функцию для использования в других скриптах при необходимости:
# kill my group's subprocesses: killGroup
# kill also myself: killGroup -x
# kill another group's subprocesses: killGroup N
# kill that group all: killGroup -x N
# N: PID of the main process (= process group ID).
function killGroup () {
local prid mainpid
case in
-x) [ -n "" ] && kill -9 - || kill -9 -$$ ;;
"") mainpid=$$ ;;
*) mainpid= ;;
esac
prid=$(ps ax -o pid,pgid | grep $mainpid)
prid=${prid//$mainpid/}
kill -9 $prid 2>/dev/null
return
}
Ура.
если у вас есть pstree и perl в вашей системе, вы можете попробовать следующее:
perl -e 'kill 9, (`pstree -p PID` =~ m/\((\d+)\)/sg)'
Если вы знаете pid вещи, которую хотите убить, вы обычно можете перейти от идентификатора сеанса и всего в том же сеансе. Я бы дважды проверил, но я использовал это для сценариев, запускающих rsyncs в циклах, которые я хочу умереть, а не запускать другой (из-за цикла), как если бы я просто убил rsync.
kill $(ps -o pid= -s $(ps -o sess --no-heading --pid 21709))
Если вы не знаете pid, вы все еще можете вложить больше
kill $(ps -o pid= -s $(ps -o sess --no-heading --pid $(pgrep rsync )))
в sh команда jobs отобразит фоновые процессы. В некоторых случаях может быть лучше сначала убить новейший процесс, например, более старый создал общий сокет. В этих случаях сортируйте PIDs в обратном порядке. Иногда вы хотите дождаться момента, когда задания напишут что-то на диске или что-то в этом роде, прежде чем они остановятся.
и не убивайте, если вам не нужно!
for SIGNAL in TERM KILL; do
for CHILD in $(jobs -s|sort -r); do
kill -s $SIGNAL $CHILD
sleep $MOMENT
done
done
убийство дочернего процесса в сценарии оболочки:
много раз нам нужно убить дочерний процесс, который повешен или блокируется по какой-то причине. например. Проблема подключения FTP.
есть два подхода,
1) создать отдельный новый родитель для каждого ребенка, который будет контролировать и убивать дочерний процесс после достижения таймаута.
создать test.sh как следует,
#!/bin/bash
declare -a CMDs=("AAA" "BBB" "CCC" "DDD")
for CMD in ${CMDs[*]}; do
(sleep 10 & PID=$!; echo "Started $CMD => $PID"; sleep 5; echo "Killing $CMD => $PID"; kill $PID; echo "$CMD Completed.") &
done
exit;
и наблюдать процессы, которые имеют имя как "тест" в другом терминале, используя выполнить следующую команду.
watch -n1 'ps x -o "%p %r %c" | grep "test" '
выше скрипт создаст 4 новых дочерних процесса и их родителей. Каждый дочерний процесс будет выполняться в течение 10 секунд. Но как только тайм-аут 5sec достигнет, их соответствующие родительские процессы убьют этих детей. Таким образом, ребенок не сможет завершить выполнение(10sec). Играть вокруг этих таймингов(переключатель 10 и 5), чтобы увидеть другое поведение. В этом случае ребенок завершит выполнение в 5sec, прежде чем он достигнет таймаута 10sec.
2) Пусть текущий родитель монитор и убить дочерний процесс, как только тайм-аут достигнут. Это не создаст отдельного родителя для мониторинга каждого ребенка. Также вы можете правильно управлять всеми дочерними процессами внутри одного родителя.
создать test.sh как следует,
#!/bin/bash
declare -A CPIDs;
declare -a CMDs=("AAA" "BBB" "CCC" "DDD")
CMD_TIME=15;
for CMD in ${CMDs[*]}; do
(echo "Started..$CMD"; sleep $CMD_TIME; echo "$CMD Done";) &
CPIDs[$!]="$RN";
sleep 1;
done
GPID=$(ps -o pgid= $$);
CNT_TIME_OUT=10;
CNT=0;
while (true); do
declare -A TMP_CPIDs;
for PID in "${!CPIDs[@]}"; do
echo "Checking "${CPIDs[$PID]}"=>"$PID;
if ps -p $PID > /dev/null ; then
echo "-->"${CPIDs[$PID]}"=>"$PID" is running..";
TMP_CPIDs[$PID]=${CPIDs[$PID]};
else
echo "-->"${CPIDs[$PID]}"=>"$PID" is completed.";
fi
done
if [ ${#TMP_CPIDs[@]} == 0 ]; then
echo "All commands completed.";
break;
else
unset CPIDs;
declare -A CPIDs;
for PID in "${!TMP_CPIDs[@]}"; do
CPIDs[$PID]=${TMP_CPIDs[$PID]};
done
unset TMP_CPIDs;
if [ $CNT -gt $CNT_TIME_OUT ]; then
echo ${CPIDs[@]}"PIDs not reponding. Timeout reached $CNT sec. killing all childern with GPID $GPID..";
kill -- -$GPID;
fi
fi
CNT=$((CNT+1));
echo "waiting since $b secs..";
sleep 1;
done
exit;
и смотреть процессы, которые имеют имя как "тест" в другом терминале, используя следующую команду.
watch -n1 'ps x -o "%p %r %c" | grep "test" '
выше скрипт создаст 4 новых дочерних процесса. Мы храним pids всего дочернего процесса и зацикливаемся на них, чтобы проверить, они закончили свое исполнение или все еще работают. Дочерний процесс будет выполняться до времени CMD_TIME. Но если время ожидания CNT_TIME_OUT достигнет, все дети будут убиты родительским процессом. Вы можете переключать время и играть со сценарием, чтобы увидеть поведение. Одним из недостатков этого подхода является использование идентификатора группы для уничтожения всего дочернего дерева. Но сам родительский процесс принадлежит к той же группе, поэтому он также будет убит.
необходимо назначить другой ID группы родителя, если не хочу, чтобы родителя убили.
более подробную информацию можно найти здесь
этот скрипт тоже работает:
#/bin/sh
while true
do
echo "Enter parent process id [type quit for exit]"
read ppid
if [ $ppid -eq "quit" -o $ppid -eq "QUIT" ];then
exit 0
fi
for i in `ps -ef| awk ' == '$ppid' { print }'`
do
echo killing $i
kill $i
done
done