Чего я на самом деле пытаюсь достичь:
Я пытаюсь заставить настраиваемого демона работать в системе, использующей 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!"