Назад | Перейти на главную страницу

Родительский сценарий bash не получает ловушку, несмотря на то, что процесс все еще запущен

Чего я на самом деле пытаюсь достичь:

Я пытаюсь заставить настраиваемого демона работать в системе, использующей SysVinit. У меня есть бутстраппер /etc/init.d/xyz скрипт, который вызывает мой демон, но не переводит его автоматически в фоновый режим. Это похоже на то, как службы вроде nginx вести себя: сам бинарный фон - т.е. это не ответственность /etc/init.d/nginx скрипт для демонстрации процесса, поэтому, если вы запустили /opt/nginx/sbin/nginx непосредственно вы также испытаете демонизированное / фоновое выполнение.

Эта проблема

Моя проблема в том, что при использовании моего текущего метода демон не завершает работу родительским процессом (который завершается, когда вы вызываете service xyz stop).

Я использую родителя launcher.sh сценарий, который запускает daemon.sh & сценарий. Однако когда я убиваю launcher.sh в daemon.sh продолжает работать, несмотря на все мои усилия с trap (он просто никогда не вызывается):

-> launcher.sh

#!/bin/bash

function shutdown {
    # Get our process group id
    PGID=$(ps -o pgid= $$ | grep -o [0-9]*)

    echo THIS NEVER GETS CALLED!

    # Kill process group in a new process group
    setsid kill -- -$$
    exit 0
}

trap "shutdown" SIGTERM

# Run daemon in background

./daemon.sh &

-> daemon.sh

#!/bin/bash

while true
do
    sleep 1
done

Чтобы запустить и убить:

./launcher.sh

<get PID for launcher>

kill -TERM 123 # PID of launcher.sh... which _is_ still running and has its own PID.

Результат: daemon.sh Все еще работает и в shutdown функция никогда не вызывается - я подтвердил это раньше, поместив echo here в теле функции.

Любые идеи?

РЕДАКТИРОВАТЬ: В launcher.sh сценарий запускается с использованием daemon launcher.sh, где daemon это функция, предоставляемая Amazon Linux init.d/functions файл (см. здесь: http://gist.github.com/ljwagerfield/ab4aed16878dd9a8241b14bc1501392‌ е).

В trap команда работает только до тех пор, пока выполняется сценарий.

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

Во-первых:

launcher.sh:

/path/to/daemon.sh &
echo "$!" > /var/run/xyz.pid

Простая и несколько наивная версия /etc/init.d/xyz:

# ... pull in functions or sysconfig files ...
start() {
    # ... do whatever is needed to set things up to start ...
    /path/to/launcher.sh
}
stop() {
    # ... do whatever is needed to set things up to stop ...
    kill `cat /var/run/xyz.pid`
}
# ... other functions ...

Ненавивный сценарий запуска будет зависеть от того, какую версию Linux вы используете; Я бы посоветовал посмотреть другие примеры в /etc/init.d чтобы увидеть, как они это делают.

Для меня не имеет смысла, почему вы хотите, чтобы для этого использовались два скрипта. Ты можешь просто позвонить daemon.sh & в вашем сценарии инициализации? Или, возможно, вы можете использовать daemon команда.

NAME
       daemon - turns other processes into daemons

SYNOPSIS
        usage: daemon [options] [--] [cmd arg...]

Если вам нужно использовать ловушку, возможно, вы сможете использовать ее в daemon.sh для чистого отключения. Трудно сказать, настоящие ли это сценарии или просто примеры.

Часть проблемы с launcher.sh в том, что он выходит ... его ничто не держит, поэтому вы не можете его убить - его уже нет. Я не просто говорю это, я действительно проверил ваш сценарий, чтобы убедиться, прежде чем ответить. Смотрите мои комментарии, добавленные к вашему сценарию.

#!/bin/bash

function shutdown {
    # Get our process group id
    PGID=$(ps -o pgid= $$ | grep -o [0-9]*)

    echo THIS NEVER GETS CALLED!

    # Kill process group in a new process group
    setsid kill -- -$$
    exit 0
}

trap "shutdown" SIGTERM

# Run daemon in background *** script keeps running ***

./daemon.sh &

# It exits here
echo "Exiting... bye!"