O ponto de entrada do script Bash (PID = 1) mata o subprocesso 'tail' APENAS se uma armadilha falsa (que faz NADA) estava lá [fechada]

1

Estou com um comportamento estranho no meu script Bash , tenho este script Bash que está sendo executado com PID 1 (é um entrypoint para Docker container, se você não estiver familiarizado com o Docker , Eu suponho que você pode ignorar essa informação).

Quando executo o seguinte script, SIGTERM termina tudo muito rapidamente e tudo parece estar bem (lembre-se de que sshd service não existe! Meu sistema inteiro inicia apenas este script que executa tail nada mais, mas até agora não é o problema).

#!/bin/bash

trap "pkill sshd" SIGTERM

export PATH=/usr/local/samba/bin/:/usr/local/samba/sbin/:$PATH

if [ -f /usr/local/samba/etc/smb.conf ]; then
        exec /usr/local/samba/sbin/samba -i
else
        tail -f /dev/null & wait ${!}
fi

O problema surge quando eu apago esse trap . Agora meu sistema trava, e parece que a cauda ainda está em execução e não termina por algum motivo (se você estiver familiarizado com o Docker, o Docker aguarda 10 segundos e depois mata o contêiner, porque ele não respondeu pelo SIGTERM , novamente, se você não estiver familiarizado com o Docker, ignore esta informação).

#!/bin/bash

export PATH=/usr/local/samba/bin/:/usr/local/samba/sbin/:$PATH

if [ -f /usr/local/samba/etc/smb.conf ]; then
        exec /usr/local/samba/sbin/samba -i
else
        tail -f /dev/null & wait ${!}
fi

Alguém poderia me explicar qual é exatamente o problema? Por que esse falso trap faz tudo funcionar (embora não faça praticamente nada, mas funciona porque simplesmente está lá).

Eu ainda quero mencionar que usar um trap : trap "" SIGTERM vazio não ajuda, algo deve estar lá na armadilha para funcionar (mesmo que não faça nada).

Espero que alguém possa me ajudar, obrigado!

    
por Mohammed Noureldin 20.08.2017 / 04:03

2 respostas

0

Na verdade, adicionar o parâmetro t (para alocar tty) ao executar o contêiner resolve o problema. Eu estava rodando com o parâmetro -d , e agora com -td .

Não sei porque, mas consegui. Se seria ótimo se alguém pudesse explicar por que isso está acontecendo.

    
por 29.08.2017 / 01:10
0

Você não forneceu seu Dockerfile e não está claro como você envia o sinal SIGTERM para o contêiner.

No entanto, aqui está o que eu criei na tentativa de reproduzir o seu problema:

Meu Dockerfile :

FROM ubuntu
ADD ./entrypoint.sh /opt/entrypoint.sh
# Using the exec form here, so that the process is assigned PID 1.
ENTRYPOINT ["/opt/entrypoint.sh"]

Compilar o contêiner:

$ docker build -f Dockerfile -t test_image .

Não se esqueça de reconstruir seu contêiner sempre que alterar o script do ponto de entrada.

Executar contêiner com este comando:

$ docker run --rm -it --name test_trap test_image

Agora, vamos ver o que está acontecendo em cada corrida.

1) Com a linha trap no seu script Bash :

# The main process will receive SIGTERM, trap it and exit.
$ docker stop test_trap

# The main process will receive SIGTERM, trap it and exit.
$ docker kill -s=TERM test_trap

# The main process will receive SIGKILL and will be stopped immediately.
$ docker kill -s=KILL test_trap

2) Sem a linha trap :

# The main process will receive SIGTERM which will be ignored.
# After a grace period (10s by default) it will receive SIGKILL and will be stopped.
$ docker stop test_trap

# The main process will receive SIGTERM which will be ignored.
# Container will continue running.
$ docker kill -s=TERM test_trap

# The main process will receive SIGKILL and will be stopped immediately.
$ docker kill -s=KILL test_trap

O motivo é que o kernel trata um processo com PID 1 especialmente e não mata o processo que recebe o sinal SIGTERM (e também SIGINT ).

Mais informações sobre este assunto:

Any process can register its own handlers for TERM and use them to perform cleanup before exiting. If a process hasn't registered a custom signal handler, the kernel will normally fall back to the default behavior for a TERM signal: killing the process.

For PID 1, though, the kernel won't fall back to any default behavior when forwarding TERM. If your process hasn't registered its own handlers (which most processes don't), TERM will have no effect on the process.

Fonte - link

UPDATE

Ainda não posso comentar, por isso deixarei um comentário aqui. Este é o mesmo problema PID 1 . Com -d e -td o tratamento de sinais funciona conforme o esperado: TERM é ignorado, pois o processo de ponto de entrada é atribuído a PID 1 , enquanto KILL finaliza o processo. Se você adicionar a linha trap , o sinal TERM ficará preso nos dois casos. Se não estiver funcionando para você por qualquer motivo, você deve postar seu Dockerfile , os comandos exatos que você executa e atualizar sua pergunta de acordo.

    
por 28.08.2017 / 20:09