Предоставление другим пользователям возможности останавливать / перезапускать простые демоны bash - использовать сигналы или что? - PullRequest
6 голосов
/ 24 февраля 2012

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

Вдохновленный http://mywiki.wooledge.org/ProcessManagement, Я пишу сценарий называется daemonise.sh, который выглядит как

#!/bin/sh
while :; do
    ./myprogram lotsadata.xml
    echo "Restarting server..." 1>&2
done

чтобы "демон" работал. Так как мне иногда нужно это остановить, или просто перезапустите его, я запускаю этот скрипт в сеансе экрана, например:

$ ./daemonise.sh & DPID=$!
$ screen -d

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

$ screen -r
$ kill $DPID
$ screen -d

Это прекрасно работает, когда я единственный сопровождающий, но теперь я хочу дать кто-то другой остановит / перезапустит программу, не важно, кто ее запустил. А также чтобы усложнить ситуацию, скрипт daemonise.sh на самом деле запускает около 16 программ, что затрудняет убить каждую если вы не знаете их PID.

Каким будет «лучший метод», позволяющий другому пользователю остановить / перезапустить демонов?

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

#!/bin/bash
DPID=
trap './daemonise.sh & DPID=$!' USR1
trap 'kill $DPID' USR2 EXIT

# Ensure trapper wrapper doesn't exit:
while :; do
    sleep 10000 & wait $!
done

Теперь, если другому пользователю нужно остановить демонов, а я не могу этого сделать, она просто должна знать pid обертки, и, например, sudo kill -s USR2 $wrapperpid. (Также это позволяет запускать демоны перезагружается и все равно убивает их чисто.)

Есть ли лучшее решение? Есть ли очевидные проблемы с этим Решение, которое я не вижу?

(Прочитав Breg Wiki Грега, я бы хотел избежать решения, связанного с pgrep или PID-файлами ...)

Ответы [ 2 ]

1 голос
/ 12 марта 2013

Об улучшении вашего подхода: разве не было бы целесообразно убедиться, что ваша команда sleep в sleep 10000 & wait $! правильно завершается, если ваш скрипт pidwrapper завершается каким-либо образом?

В противном случае в таблице процессов в течение некоторого времени остался бы зависший sleep процесс.

Точно так же не было бы чище правильно завершить myprogram в daemonise.sh приперезапуск (т. е. если daemonise.sh получает сигнал TERM)?

Кроме того, возможно подавление уведомлений о заданиях и проверка существования pid перед уничтожением.

#!/bin/sh
# cat daemonise.sh

# cf. "How to suppress Terminated message after killing in bash?",
# http://stackoverflow.com/q/81520

trap '
   echo "server shut down..." 1>&2
   kill $spid1 $spid2 $spid3 &&
      wait  $spid1 $spid2 $spid3 2>/dev/null
   exit
' TERM

while :; do
    echo "Starting server..." 1>&2
    #./myprogram lotsadata.xml
    sleep 100 &
    spid1=${!}
    sleep 100 &
    spid2=${!}
    sleep 100 &
    spid3=${!}
    wait
    echo "Restarting server..." 1>&2
done

#------------------------------------------------------------

#!/bin/bash
# cat pidwrapper

DPID=

trap '
   kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null
   ./daemonise.sh & DPID=${!}
' USR1

trap '
   kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null
   kill -0 $DPID 2>/dev/null && kill $DPID && wait ${DPID} 2>/dev/null
' USR2 

trap '
   trap - EXIT
   kill -0 $DPID 2>/dev/null && kill $DPID && wait ${DPID} 2>/dev/null
   kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null
   exit 0
' EXIT

# Ensure trapper wrapper does not exit:
while :; do
    sleep 10000 & wait $!
done

#------------------------------------------------------------

# test

{
wrapperpid="`exec sh -c './pidwrapper & echo ${!}' | head -1`"
echo "wrapperpid: $wrapperpid"
for n in 1 2 3 4 5; do
   sleep 2
   # start daemonise.sh
   kill -s USR1 $wrapperpid 
   sleep 2
   # kill daemonise.sh
   kill -s USR2 $wrapperpid 
done
sleep 2
echo kill $wrapperpid
kill $wrapperpid
}
1 голос
/ 25 февраля 2012

Я рекомендую PID-скрипт инициализации.Любой пользователь с привилегией sudo для скрипта сможет запускать и останавливать процессы сервера.

...