Запустіть N процесів з одного системного файлу обслуговування


36

Я знайшов цей системний файл сервісу для запуску автоматичного пошуку, щоб не підтримувати ssh-тунель: https://gist.github.com/thomasfr/9707568

[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

Чи є спосіб налаштувати systemd для запуску декількох тунелів в одній службі.

Я не хочу створювати N системних службових файлів, оскільки хочу уникати копіювання + вставлення.

Усі сервісні файли були б ідентичними, за винятком того, що "remote.example.com" буде замінено іншими іменами хостів.

Через 1,5 року ...

Я задав це питання приблизно 1,5 року тому.

Моя думка трохи змінилася. Так, приємно, що ви можете це зробити з systemd (я все ще використовую його), але я буду використовувати конфігураційне управління в майбутньому.

Чому systemd повинен реалізовувати мову шаблону та замінювати% h?

Через кілька місяців я думаю, що цю петлю та шаблони слід вирішити інструментом, який автоматизує конфігурацію. Зараз я користуюся одним інструментом цього списку у Вікіпедії .


Іншими словами, ви говорите про використання системи управління конфігурацією для створення декількох майже однакових службових файлів для виконання цього завдання? Гммм, можливо. Як і у більшості таких питань, немає чіткої розділової лінії, що розділяє їх.
pgoetz

Управління конфігурацією @pgoetz для мене все ще нове, але це має користь, якщо ви подивитесь на тему цього питання: Якщо ви подивитесь на результат управління конфігурацією, це зрозуміють усі, хто знає системні сервісні файли: звичайні та прості сервісні файли . Я думаю, що має сенс вивчати та використовувати систему управління конфігурацією, оскільки знання можуть використовуватися для всіх конфігурацій у / etc, а не лише для системних.
guettli

Відповіді:


47

Добре, якщо припустити, що єдине, що змінюється на одиничний файл, - це remote.example.comчастина, ви можете скористатися службою миттєвого пошуку .

На systemd.unitчоловіковій сторінці:

За бажанням, одиниці можуть бути екземплярами з файлу шаблонів під час виконання. Це дозволяє створити кілька одиниць з одного файлу конфігурації. Якщо systemd шукає файл конфігурації одиниці, він спочатку шукатиме буквальне ім'я одиниці у файловій системі. Якщо це не приносить успіху, а ім'я одиниці містить символ "@", systemd шукатиме шаблон одиниці, який має те саме ім'я, але з видаленою рядком екземпляра (тобто частиною між символом "@" та суфіксом). Приклад: якщо запитується служба getty@tty3.service і не знайдено жодного файлу з цим іменем, systemd шукатиме getty @ .service та інстанціює службу з цього файлу конфігурації, якщо він знайдений.

В основному, ви створюєте єдиний файл, який містить змінну (зазвичай %i), де виникають відмінності, а потім вони зв'язуються, коли ви "вмикаєте" цю послугу.

Наприклад, у мене є одиничний файл, який називається /etc/systemd/system/autossh@.serviceтак:

[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

Що я тоді ввімкнув

[user@anotherhost ~]$ sudo systemctl enable autossh@somehost.example.com
ln -s '/etc/systemd/system/autossh@.service' '/etc/systemd/system/multi-user.target.wants/autossh@somehost.example.com.service'

І може взаємодіяти з

[user@anotherhost ~]$ sudo systemctl start autossh@somehost.example.com
[user@anotherhost ~]$ sudo systemctl status autossh@somehost.example.com
autossh@somehost.example.service - AutoSSH service for ServiceABC on somehost.example
   Loaded: loaded (/etc/systemd/system/autossh@.service; 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/autossh@somehost.example.com.service
           ├─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 autossh@somehost.example.com
[user@anotherhost ~]$ sudo systemctl status autossh@somehost.example.com
autossh@somehost.example.com.service - AutoSSH service for ServiceABC on somehost.example.com
   Loaded: loaded (/etc/systemd/system/autossh@.service; 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.

Як бачите, всі екземпляри %iфайлу одиниці замінюються наsomehost.example.com .

Є ще багато специфікаторів, які ви можете використовувати в файлі одиниці, але я вважаю, %iщо найкраще працювати у таких випадках.


Нічого собі, systemd це чудово.
guettli

Ви не показуєте, як запускатись автоматично під час завантаження, в тому числі з того, який слід запустити.
Крейг Хікс

З Systemd, enableце те, що змушує блок / послугу починатися під час завантаження.
GregL

Чи можу я самостійно вмикати / відключати екземпляри?
Soumya Kanti

Так, саме це ви робите, коли ви їх вмикаєте / вимикаєте.
GregL

15

Ось приклад пітона, який я шукав. Ім'я @файлу служби дозволяє запустити N процесів:

$ cat /etc/systemd/system/my-worker@.service

[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

Різні методи його виклику

Увімкнення різних підрахунків, наприклад:

  • Увімкнути 30 працівників:

    sudo systemctl enable my-worker\@{1..30}.service
    
  • Увімкнути 2 працівників:

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

Тоді обов’язково перезавантажте:

sudo systemctl daemon-reload

Тепер ви можете запустити / зупинити потім різними способами:

  • Початок 1:

    sudo systemctl start my-worker@2.service
    
  • Почати кілька:

    sudo systemctl start my-worker@{1..2}
    
  • Зупинити кілька разів:

    sudo systemctl stop my-worker@{1..2}
    
  • Перевірити статус:

    sudo systemctl status my-worker@1
    

ОНОВЛЕННЯ : Щоб керувати екземплярами як однією службою, ви можете зробити щось подібне:

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

[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

А тепер ви можете керувати всіма примірниками за допомогою sudo systemctl some-worker (start|restart|stop)

Ось декілька котлів для вашого script.py:

#!/usr/bin/env python

import logging


def worker_loop():
    shutdown = False
    while True:

        try:
            if shutdown:
                break

            # Your execution logic here.
            # Common logic - i.e. consume from a queue, perform some work, ack message
            print("hello world")

        except (IOError, KeyboardInterrupt):
            shutdown = True
            logging.info("shutdown received - processing will halt when jobs complete")
        except Exception as e:
            logging.exception("unhandled exception on shutdown. {}".format(e))


if __name__ == '__main__':
    worker_loop()

@radek: Дві речі, яких я не розумію: По-перше,% i використовується лише в описі файлу одиниці. Як команда start знає, що почати? По-друге, як systemctl some-worker (start|restart|stop)знати, над якими екземплярами працювати?
U. Windl

% i - вихід з @ в імені сервісного файлу. Друга частина вже пояснена у відповіді, див Now you can start/stop then in various ways.
radtek

Я вважаю, що його відповідь неповна без участі сценаріїв. Більшість "магії" робиться всередині скриптів, яких немає.
У. Віндл

Я фактично запропонував повне робоче рішення. На які «сценарії» ви посилаєтесь? /path/to/my/script.py може бути яким завгодно, "привіт світом", якщо ви хочете. Щось буде працювати, поки не отримає сигнал вбивства. Зверніть увагу, що питання не стосується python.
radtek

Ух, це дозволяє вам починати кратні одночасно? розум здутий ...
rogerdpack

1

Відповідь GregL мені дуже допомогла. Ось приклад шаблону підрозділу, який я використовував у своєму коді, використовуючи приклад, наведений вище для сервера завдань коробки передач. Я створив скрипт оболонки, який дозволяє мені створити X кількість "робітників" за допомогою цього одного шаблону.

[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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.