Подтвердить что ты не робот

Убить bash script детей переднего плана при поступлении сигнала

Я обертываю приложение fastcgi в bash script следующим образом:

#!/bin/bash
# stuff
./fastcgi_bin
# stuff

Поскольку bash выполняет только ловушки для сигналов, когда заканчивается передний план script, я не могу просто kill -TERM scriptpid, потому что приложение fastcgi останется в живых.
Я попытался отправить двоичный код на задний план:

#!/bin/bash
# stuff
./fastcgi_bin &
PID=$!
trap "kill $PID" TERM
# stuff

Но если я так делаю это, очевидно, что stdin и stdout не перенаправлены должным образом, потому что он не соединяется с lighttpds mod_fastgi, версия переднего плана работает.

EDIT: Я рассматривал проблему, и это происходит потому, что bash перенаправляет /dev/null на stdin, когда программа запускается в фоновом режиме, поэтому любой способ избежать этого должен решить мою проблему.

Любой намек на то, как это решить?

4b9b3361

Ответ 1

Есть несколько вариантов, которые приходят мне на ум:

  • Когда процесс запускается из оболочки script, оба относятся к одной и той же группе процессов. Убивание родительского процесса оставляет детей живыми, поэтому вся группа процессов должна быть убита. Это может быть достигнуто путем передачи отрицательного PGID (идентификатора группы процессов) для уничтожения, что совпадает с родительским PID. ej: kill -TERM -$PARENT_PID

  • Не выполняйте двоичный код как ребенок, но заменив script процесс с exec. Вы теряете способность выполнять вещи потом хотя, поскольку exec полностью заменяет родительский процесс.

  • Не убивайте процесс оболочки script, а бинарный файл FastCGI. Затем, в script, проверьте код возврата и действуйте соответствующим образом. например: ./fastcgi_bin || exit -1

В зависимости от того, как mod_fastcgi обрабатывает рабочие процессы, возможен только второй вариант.

Ответ 2

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

Не могли бы вы переписать bash script в Perl? Perl имеет несколько методов управления дочерними процессами. Вы можете читать perldoc perlipc и более подробно в основных модулях IPC::Open2 и IPC::Open3.

Я не знаю, как это будет взаимодействовать с lighttpd и т.д., или если в этом подходе есть больше функциональности, но, по крайней мере, это дает вам еще большую гибкость и еще кое-что для чтения в вашей охоте.

Ответ 3

Я написал этот script всего несколько минут назад, чтобы убить bash script и все его дочерние элементы...

#!/bin/bash
# This script will kill all the child process id for a  given pid
# based on http://www.unix.com/unix-dummies-questions-answers/5245-script-kill-all-child-process-given-pid.html

ppid=$1

if [ -z $ppid ] ; then
   echo "This script kills the process identified by pid, and all of its kids";
   echo "Usage: $0 pid";
   exit;
fi

for i in `ps j | awk '$3 == '$ppid' { print $2 }'`
do
    $0 $i   
    kill -9 $i
done

Убедитесь, что script выполним, или вы получите сообщение об ошибке $0 $i

Ответ 4

Я не уверен, что полностью понимаю вашу точку зрения, но вот то, что я пробовал, и процесс, похоже, способен управлять ловушкой (назовите его trap.sh):

#!/bin/bash

trap "echo trap activated" TERM INT
echo begin
time sleep 60
echo end

Запустите его:

./trap.sh &

И играйте с ним (только одна из этих команд сразу):

kill -9 %1
kill -15 %1

Или запустите на переднем плане:

./trap.sh

И прерывание с помощью control-C.

Кажется, работает для меня. Что именно не работает для вас?

Ответ 5

Вы можете переопределить неявный </dev/null для фонового процесса, перенаправив stdin самостоятельно, например:

sh -c 'exec 3<&0; { read x; echo "[$x]"; } <&3 3<&- & exec 3<&-; wait'

Ответ 6

Попробуйте сохранить исходный stdin с помощью ./fastcgi_bin 0<&0 &:

#!/bin/bash
# stuff
./fastcgi_bin 0<&0 &
PID=$!./fastcgi_bin 0<&0 &
trap "kill $PID" TERM
# stuff


# test
#sh -c 'sleep 10 & lsof -p ${!}'
#sh -c 'sleep 10 0<&0 & lsof -p ${!}'

Ответ 7

Вы можете сделать это с помощью coprocess.

Изменить: ну, сопроцессоры - это фоновые процессы, которые могут иметь stdin и stdout open (потому что bash готовит для них фифы). Но вам все равно нужно читать/писать для этих филонов, и единственный полезный примитив для этого - bash read (возможно, с тайм-аутом или файловым дескриптором); ничего достаточно прочного для cgi. Итак, во-вторых, мой совет заключается не в том, чтобы делать это в bash. Выполнение дополнительной работы в fastcgi или в http-обертке, такой как WSGI, было бы более удобным.