O script pai bash não está recebendo 'trap' apesar do processo ainda estar em execução

1

O que estou realmente tentando alcançar:

Estou tentando obter um daemon personalizado trabalhando em um sistema que use o SysVinit. Eu já tenho o script bootstrapper /etc/init.d/xyz , que chama meu daemon, mas não o coloca automaticamente em segundo plano. Isso é semelhante a como os serviços como nginx se comportam: os próprios fundos binários - ou seja, não é responsabilidade do script /etc/init.d/nginx daemonizar o processo, portanto, se você executasse /opt/nginx/sbin/nginx diretamente, também experimentaria a execução daemon / em segundo plano.

O problema

Meu problema é que, usando meu método atual, o daemon não termina com o processo pai (que é terminado quando você chama service xyz stop ).

Estou usando um script pai launcher.sh que executa um script daemon.sh & . No entanto, quando eu mato launcher.sh , o daemon.sh continua a ser executado, apesar dos meus melhores esforços com trap (ele simplesmente nunca é chamado):

- > 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

Para executar & matar:

./launcher.sh

<get PID for launcher>

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

Resultado: daemon.sh ainda em execução e a função shutdown nunca é chamada - Confirmei isso antes colocando um echo here no corpo da função.

Alguma idéia?

EDITAR: O script launcher.sh está sendo executado usando daemon launcher.sh , onde daemon é uma função fornecida pelo arquivo init.d/functions do Amazon Linux (veja aqui: link f).

    
por Lawrence Wagerfield 15.09.2016 / 13:23

2 respostas

1

O comando trap funciona somente enquanto o script está sendo executado.

A maneira como isso é feito normalmente é que, quando o daemon é forjado, ele grava seu PID em um arquivo. O script de inicialização usa esse arquivo para determinar qual processo deve ser eliminado ou chama seu script de ativação para eliminar o processo.

Para a primeira instância:

launcher.sh:

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

Uma versão simples e um pouco ingênua de /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 ...

Um script de inicialização não-ingênuo dependerá de qual versão do Linux você está executando; Eu sugeriria ver outros exemplos em /etc/init.d para ver como eles fazem isso.

    
por 15.09.2016 / 14:26
0

Não faz sentido para mim por que você gostaria de ter dois scripts fazendo isso. Você pode apenas chamar daemon.sh & em seu script de inicialização? Ou talvez você possa usar o comando daemon .

NAME
       daemon - turns other processes into daemons

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

Se você precisar usar o trap, talvez você possa usá-lo em daemon.sh para um desligamento limpo. É difícil dizer se esses são seus scripts reais ou apenas exemplos.

Parte do problema com launcher.sh é que ele sai ... não há nada para mantê-lo funcionando, então você não pode matá-lo - ele já foi embora. Eu não estou apenas dizendo isso, eu realmente testei seu roteiro para ter certeza antes de responder. Veja meus comentários adicionados ao seu script.

#!/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!"
    
por 15.09.2016 / 14:16