Inicia N processos com um arquivo de serviço systemd

27

Eu encontrei este arquivo de serviço systemd para iniciar o autossh para manter um túnel ssh: link

[Unit]
Description=Keeps a tunnel to 'remote.example.com' open
After=network.target

[Service]
User=autossh
# -p [PORT]
# -l [user]
# -M 0 --> no monitoring
# -N Just open the connection and do nothing (not interactive)
# LOCALPORT:IP_ON_EXAMPLE_COM:PORT_ON_EXAMPLE_COM
ExecStart=/usr/bin/autossh -M 0 -N -q -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -p 22 -l autossh remote.example.com -L 7474:127.0.0.1:7474 -i /home/autossh/.ssh/id_rsa

[Install]
WantedBy=multi-user.target

Existe uma maneira de configurar o systemd para iniciar vários túneis no serviço one .

Eu não quero criar arquivos de serviço do sistema N, já que eu quero evitar copiar + colar.

Todos os arquivos de serviço seriam idênticos, exceto que "remote.example.com" seria substituído por outros nomes de host.

1,5 ano depois ...

Eu fiz esta pergunta aproximadamente há 1.5 anos.

Minha mente mudou um pouco. Sim, é legal, você pode fazer isso com o systemd (eu ainda o uso), mas usarei o gerenciamento de configurações no futuro.

Por que o systemd deve implementar uma linguagem de template e substituir% h?

Vários meses depois, acho que esse loop e o modelo devem ser resolvidos com uma ferramenta que automatiza a configuração. Eu uso uma ferramenta desta lista na wikipedia agora.

    
por guettli 20.10.2015 / 16:13

3 respostas

38

Bem, supondo que a coisa somente que muda por arquivo de unidade seja a parte remote.example.com , você pode usar um Instanciado Serviço .

Na página systemd.unit man:

Optionally, units may be instantiated from a template file at runtime. This allows creation of multiple units from a single configuration file. If systemd looks for a unit configuration file, it will first search for the literal unit name in the file system. If that yields no success and the unit name contains an "@" character, systemd will look for a unit template that shares the same name but with the instance string (i.e. the part between the "@" character and the suffix) removed. Example: if a service [email protected] is requested and no file by that name is found, systemd will look for [email protected] and instantiate a service from that configuration file if it is found.

Basicamente, você cria um único arquivo de unidade, que contém uma variável (geralmente %i ) onde as diferenças ocorrem e, em seguida, elas são vinculadas quando você "ativa" esse serviço.

Por exemplo, eu tenho um arquivo de unidade chamado /etc/systemd/system/[email protected] que se parece com isso:

[Unit]
Description=AutoSSH service for ServiceABC on %i
After=network.target

[Service]
Environment=AUTOSSH_GATETIME=30 AUTOSSH_LOGFILE=/var/log/autossh/%i.log AUTOSSH_PIDFILE=/var/run/autossh.%i.pid
PIDFile=/var/run/autossh.%i.pid
#Type=forking
ExecStart=/usr/bin/autossh -M 40000 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC %i

[Install]
WantedBy=multi-user.target

Que eu então habilitei

[user@anotherhost ~]$ sudo systemctl enable [email protected]
ln -s '/etc/systemd/system/[email protected]' '/etc/systemd/system/multi-user.target.wants/[email protected]'

E pode interagir com

[user@anotherhost ~]$ sudo systemctl start [email protected]
[user@anotherhost ~]$ sudo systemctl status [email protected]
[email protected] - AutoSSH service for ServiceABC on somehost.example
   Loaded: loaded (/etc/systemd/system/[email protected]; enabled)
   Active: active (running) since Tue 2015-10-20 13:19:01 EDT; 17s ago
 Main PID: 32524 (autossh)
   CGroup: /system.slice/system-autossh.slice/[email protected]
           ├─32524 /usr/bin/autossh -M 40000 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC somehost.example.com
           └─32525 /usr/bin/ssh -L 40000:127.0.0.1:40000 -R 40000:127.0.0.1:40001 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC somehost.example.com

Oct 20 13:19:01 anotherhost.example.com systemd[1]: Started AutoSSH service for ServiceABC on somehost.example.com.
[user@anotherhost ~]$ sudo systemctl status [email protected]
[user@anotherhost ~]$ sudo systemctl status [email protected]
[email protected] - AutoSSH service for ServiceABC on somehost.example.com
   Loaded: loaded (/etc/systemd/system/[email protected]; enabled)
   Active: inactive (dead) since Tue 2015-10-20 13:24:10 EDT; 2s ago
  Process: 32524 ExecStart=/usr/bin/autossh -M 40000 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC %i (code=exited, status=0/SUCCESS)
 Main PID: 32524 (code=exited, status=0/SUCCESS)

Oct 20 13:19:01 anotherhost.example.com systemd[1]: Started AutoSSH service for ServiceABC on somehost.example.com.
Oct 20 13:24:10 anotherhost.example.com systemd[1]: Stopping AutoSSH service for ServiceABC on somehost.example.com...
Oct 20 13:24:10 anotherhost.example.com systemd[1]: Stopped AutoSSH service for ServiceABC on somehost.example.com.

Como você pode ver, todas as instâncias de %i no arquivo de unidade são substituídas por somehost.example.com .

Há um monte de especificadores que você pode usar em um arquivo de unidade no entanto, acho que %i funciona melhor em casos como este.

    
por 20.10.2015 / 19:36
9

Aqui está um exemplo de python, que era o que eu procurava:

$ cat /etc/systemd/system/[email protected]

[Unit]
Description=manages my worker service, instance %i
After=multi-user.target

[Service]
PermissionsStartOnly=true
Type=idle
User=root
ExecStart=/usr/local/virtualenvs/bin/python /path/to/my/script.py
Restart=always
TimeoutStartSec=10
RestartSec=10

Vários métodos para chamá-lo

Ativando várias contagens, por exemplo:

  • Ativar 30 trabalhadores:

    sudo systemctl enable my-worker\@{1..30}.service
    
  • Ativar 2 trabalhadores:

    sudo systemctl enable my-worker\@{1..2}.service
    

Em seguida, não se esqueça de recarregar:

sudo systemctl daemon-reload

Agora você pode começar / parar de várias maneiras:

  • Iniciar 1:

    sudo systemctl start [email protected]
    
  • Iniciar vários:

    sudo systemctl start my-worker@{1..2}
    
  • Pare de vários:

    sudo systemctl stop my-worker@{1..2}
    
  • Verifique o status:

    sudo systemctl status my-worker@1
    

UPDATE : para gerenciar instâncias como um serviço, você pode fazer algo assim:

/etc/systemd/system/[email protected]:

[Unit]
Description=manage worker instances as a service, instance %i
Requires=some-worker.service
Before=some-worker.service
BindsTo=some-worker.service

[Service]
PermissionsStartOnly=true
Type=idle
User=root
#EnvironmentFile=/etc/profile.d/optional_envvars.sh
ExecStart=/usr/local/virtualenvs/bin/python /path/to/my/script.py
TimeoutStartSec=10
RestartSec=10

[Install]
WantedBy=some-worker.service

/usr/bin/some-worker-start.sh:

#!/bin/bash
systemctl start some-worker@{1..10}

/etc/systemd/system/some-worker.service:

[Unit]
Description=manages some worker instances as a service, instance

[Service]
Type=oneshot
ExecStart=/usr/bin/sh /usr/bin/some-worker-start.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

E agora você pode gerenciar todas as instâncias com sudo systemctl some-worker (start|restart|stop)

    
por 13.10.2017 / 21:46
1

A resposta de GregL me ajudou muito. Aqui está um exemplo de um modelo de unidade que usei no meu código usando o exemplo acima para um servidor de trabalho gearman. Fiz um script de shell que me permite criar uma quantidade X de "trabalhadores" usando esse modelo.

[Unit]
Description=az gearman worker
After=gearman-job-server.service

[Service]
PIDFile=/var/run/gearman_worker_az%i.pid
Type=simple
User=www-data
WorkingDirectory=/var/www/mysite.com/jobs/
ExecStart=/usr/bin/php -f gearman_worker_az.php > /dev/null 2>&1
Restart=on-success
KillMode=process

[Install]
WantedBy=multi-user.target
    
por 23.03.2017 / 06:21