1

На моем рабочем месте у нас есть высокопроизводительный вычислительный кластер, управляемый SLURM.

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

Из-за природы этой среды не разумно (без какой-либо действительной причины) ожидать, что они это исправят.

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

По умолчанию ps захватывает все процессы, связанные с текущим сеансом tty. Однако SLURM делает глупости, и ps - это не только процессы для ЭТОЙ задачи этой работы, но и ДРУГИЕ задачи, поэтому он убивает все на физическом узле всякий раз, когда одна работа умирает.

Итак, как мне получить / убить все задания, которые являются дочерними для текущего скрипта bash?

1 ответ1

1

Текущий процесс (процесс сценариев или оболочки, в зависимости от случая) хранится в $$. Используя этот PID, вы можете использовать команду pgrep с флагом -P:pgrep -P $$
получить список всех PID с родительским PID $$

Вот очень простой скрипт для проверки концепции:

#!/bin/bash

curpid="$$"
#launch 2 useless child processes
cat /dev/random > /dev/null &
cat /dev/random > /dev/null &
cpid=`pgrep -P $curpid`  && echo "$(basename $0) pid: $curpid; child pids:" $cpid
#kill the child pids
kill $cpid
# check if any child pids still exist
newcpid=`pgrep -P $curpid`
if [ $? -ne "0" ] || [ "$newcpid" != "" ]; then
  echo "no child pids left..."
else
  echo $newcpid
fi

Выход:

{0} 02:34:57] $ ./test3.sh 
test3.sh pid: 7015; child pids: 7016 7017
./test3.sh: line 12:  7016 Terminated              cat /dev/random > /dev/null
./test3.sh: line 12:  7017 Terminated              cat /dev/random > /dev/null
no child pids left...

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

cat /dev/random > /dev/null &

линии к

sudo cat /dev/random > /dev/null &

вы не сможете убить этот процесс (при условии, что вы изначально запустили скрипт с учетной записью обычного пользователя)

Модифицированный скрипт (запуск одного потомка от имени root и вывод информации diff в конце)

#!/bin/bash

curpid="$$"
#launch 2 useless child processes
cat /dev/random > /dev/null &
sudo cat /dev/random > /dev/null &
cpid=`pgrep -P $curpid`  && echo "$(basename $0) pid: $curpid; child pids:" $cpid
#kill the child pids
kill $cpid
sleep 0.5
#check on children
for i in $cpid; do
  echo -n "PID: $i; Orig PPID: $curpid; Cur PPID: "`/usr/bin/ps --ppid $i | grep -Eo '[0-9]{3,}'`
  echo
done

Вывод с одним из потомков, работающим от имени root:

[{0} 02:53:51] $ ./test3.sh 
test3.sh pid: 8144; child pids: 8145 8146
./test3.sh: line 9: kill: (8146) - Operation not permitted
./test3.sh: line 10:  8145 Terminated              cat /dev/random > /dev/null
PID: 8145; Orig PPID: 8144; Cur PPID: 
PID: 8146; Orig PPID: 8144; Cur PPID: 8150

Запущенный дочерний PID, запущенный от имени пользователя root, больше не рассматривает исходный сценарий как родительский, а представляет собой подоболочку, созданную с помощью вызова sudo. Выход из ps auxf
это ясно показывает:

root      8146  0.0  0.0 244996  7444 pts/2    S    02:54   0:00 sudo cat /dev/random
root      8150  0.0  0.0 113828   744 pts/2    S    02:54   0:00  \_ cat /dev/random

Эта проблема не суть вашего вопроса, но что-то стоит иметь в виду.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .