Запустіть 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.