Inicia somente um serviço systemd * após * o soquete alvo estar escutando?

5

Eu tenho um serviço X que precisa se conectar ao soquete de escuta quando ele é iniciado. Esse socket de destino é ele mesmo aberto por outro serviço Y iniciado pelo systemd.

Existe alguma maneira de especificar no arquivo de unidade (ou outro) para apenas iniciar o serviço X após o serviço Y ter iniciado com sucesso e aberto o soquete de escuta?

Observe que não posso alterar o serviço X para tentar novamente se a conexão inicial falhar. Também os atrasos fixos não funcionam bem, porque o serviço Y leva quantidades variáveis de tempo antes de abrir o soquete de escuta.

    
por bigjosh 30.10.2016 / 16:23

2 respostas

6

O

systemd tende a funcionar de forma ligeiramente diferente. Você configura o systemd para criar e escutar no socket, e se alguém quiser que o X tente se conectar, então o systemd inicia o Y para manipular a conexão, passando o socket para ele. Então X pode começar de forma tradicional antes de Y, mas isso não importará. As conexões posteriores serão tratadas por Y. (Você também pode configurá-lo para que Y seja reiniciado para cada conexão, mas presumo que esse não seja o seu caso).

As mudanças mínimas para Y são para aceitar o soquete pré-criado como seu descritor de arquivo stdin / stdout, em vez de criar / vincular-se.

Aqui está uma configuração de teste que você pode tentar, não como root. Você precisa de 3 arquivos de unidade. ~/.local/share/systemd/user/mysock.socket diz ao systemd para criar o socket e como passá-lo:

# create listening socket. on 1st connect run mysock.service
[Socket]
ListenStream=5555
Accept=false

~/.local/share/systemd/user/mysock.service (com o mesmo nome mysock ) é o serviço que será iniciado se alguém se conectar ao soquete. É aqui que você inicia o Y, que eu substituí por algum python.

[Unit]
Description=started from mysock.socket
[Service]
ExecStart=/home/meuh/bin/python/mysock.py
StandardInput=socket

Finalmente, o seu serviço X tem uma Unidade dizendo que requer o socket. Para X, estou usando uma socat que grava a data no soquete. ~/.local/share/systemd/user/mysockdepend.service

[Unit]
Description=dependent on socket listening
Requires=mysock.socket
[Service]
ExecStart=/usr/bin/socat -U tcp:localhost:5555 exec:/usr/bin/date

O python pega o socket em stdin, ou seja, descritor de arquivo 0, e o coloca em um objeto de soquete python adequado, faz um accept() e pode ler / escrever nele: ~/bin/python/mysock.py

#!/usr/bin/python
# started from /home/meuh/.local/share/systemd/user/mysock.service
# with socket on stdin/stdout
import sys, time, socket, subprocess

def debug(msg):
#    time.sleep(3)
    subprocess.call(["/usr/bin/logger", msg])

debug("start\n")
s = socket.fromfd(sys.stdin.fileno(), socket.AF_INET, socket.SOCK_STREAM)
while True:
    conn, addr = s.accept()
    conn.send("hello\n")
    while True:
        try:
            data = conn.recv(100)
            debug("got "+data+"\n")
            if len(data)<=0: break
        except:
            break
    conn.close()

Após um systemctl --user daemon-reload , você deve ser capaz de executar o X com

systemctl --user start mysockdepend

e veja nos logs com journalctl que Y foi iniciado e a saída de depuração com a data.

Leia sobre ativação de sockets e 2nd do homem que a inventou.

    
por 01.11.2016 / 18:17
1

O systemd lida com esse caso com arquivos de soquete .

Um arquivo de unidade do systemd chamado some-socket.socket seria criado para representar o soquete.

Em seguida, o arquivo de serviço Service X pode incluir uma diretiva After= que faz referência ao soquete.

A documentação oficial do systemd em arquivos de soquete deve ser útil.

    
por 31.10.2016 / 01:24

Tags