Como iniciar um serviço após um tempo especificado no SystemD?

2

Estou tentando converter um script de init do SysV para systemd. A configuração do SysV está gerando diferentes processos de tal maneira:

su -l $USER_A -c "$CMD_A &"
usleep 600000
su -l $USER_B -c "$CMD_B &"
usleep 100000
su -l $USER_C -c "$CMD_C &"
usleep 300000

Como todos os processos de spawn estão usando um usuário diferente, criei uma unidade de serviço systemd para cada um deles. Nesta unidade de serviço, eu especifiquei a dependência (usando o comando Requires + After). Por exemplo. de uma dessas unidades de serviço:

[Unit]
Description=CMD_B
Requires=CMD_A
After=CMD_A

[Service]
User=USER_B
Type=simple
ExecStart=/FULLPATH/CMD_B

[Install]
WantedBy=multi-user.target

O problema é que os diferentes processos são comunicação via filas POSIX e as filas não são criadas instantaneamente, então elas precisam de um período de tempo entre cada inicialização porque elas não são robustas o suficiente para esperar que as filas POSIX sejam criadas. apenas falhou: - (

Não é possível alterar esses processos, por isso, estou adicionando esse tempo decorrido entre o lançamento de cada serviço.

Como posso "limpar" dizer que deve considerar um período de tempo específico entre cada ativação de serviço?

Nota: Embora o systemd respeite a dependência "After", como acho que considera esses comandos como imediatamente ativos, eles são gerados quase ao mesmo tempo (dentro de algumas ms). Se eu tentar adicionar um ExecStartPost=/usr/bin/usleep 600000 , parece que eles também são gerados em algumas ms, porque o tipo de serviço é simples, eu acho que ExecStartPost nunca é acionado. Então eu tentei ExecStartPre=/usr/bin/usleep 600000 (para CMD_B, e mudei para 100000 para CMD_C) mas parece que a ordem agora não é mais respeitada, CMD_A foi iniciada pela primeira vez, depois CMD_C após 100ms e finalmente CMD_B após 600ms. Então CMD_C falhou porque foi iniciado antes de CMD_B. Agora eu usei esse truque ExecStartPre= , mas eu escolhi 600ms para CMD_B, 700ms para CMD_C, etc. Funciona, mas achei terrivelmente horrível.

    
por Huygens 09.11.2015 / 15:29

1 resposta

2

Eu gostaria de propor um método que não use timeouts, mas que dependa do mecanismo do systemd para aguardar um arquivo existir antes de iniciar um programa.

Como você sabe, o Linux pode expor filas de mensagens posix como arquivos. No meu sistema Fedora, ele faz isso por padrão em /dev/mqueue/ , mas você pode criar o diretório e mount -t mqueue none /dev/mqueue se não tiver.

Então você pode usar (veja man systemd.path ) uma unidade simples myqueueb.path assim:

[Path]
PathExists=/dev/mqueue/queueb
[Install]
WantedBy=multi-user.target

e outro myqueueb.service do mesmo nome (ou defina Unit= no acima) com

[Unit]
Description=CMD_B
[Service]
User=USER_B
Type=simple
ExecStart=/FULLPATH/CMD_B

para fazer o que quiser. Não NÃO habilite a segunda unidade , mas use systemctl enable myqueueb.path e systemctl start myqueueb.path . Isso configura um inotifywait no arquivo /dev/mqueue/queueb .

Quando o seu primeiro programa criar a fila de mensagens queueb , esse arquivo aparecerá e o systemd iniciará automaticamente myqueueb.service e executará seu programa CMD_B . Obviamente, você precisa alterar esses nomes para corresponder também aos seus nomes de filas e relacionamentos para o CMD_C.

    
por 09.11.2015 / 17:15

Tags