Я нашел этот служебный файл systemd для запуска autossh, чтобы поддерживать туннель 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 года назад.
Мое мнение изменилось. Да, это хорошо, что вы можете сделать это с помощью systemd, но в будущем я буду использовать управление конфигурацией.
Почему systemd должен реализовывать язык шаблонов и заменять% h? .. Думаю, в этом нет смысла.
Несколько месяцев спустя я думаю, что этот цикл и шаблоны должны быть решены на другом уровне. Я бы сейчас использовал для этого Ansible или TerraForm.
Ну, если предположить, что только то, что меняется на единицу файла, - это 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
лучше всего работать в таких случаях.
Вот пример Python, который я искал. В @
в имени файла службы позволяет запускать 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()
Ответ GregL мне очень помог. Вот пример шаблона модуля, который я использовал в своем коде, используя приведенный выше пример для сервера заданий gearman. Я сделал сценарий оболочки, который позволяет мне создать 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
Я искал решение аналогичной задачи и на самом деле нашел одно, которое, как мне кажется, легче выполнить, но должно быть хакерский. (и здесь не упоминается)
Мне нужно было создать несколько ssh-соединений после того, как vpn создаст туннель, поэтому я создал службу, которая зависит от устройства tun и вызывает сценарий оболочки с соответствующими командами.
Сервис /etc/systemd/system/ssh_tunnel.service:
[Unit]
Description=Reverse SSH Service to access hidden services
ConditionPathExists=|/usr/bin
Wants=sys-devices-virtual-net-tun0.device
After=network.target sys-devices-virtual-net-tun0.device
[Service]
Type=forking
ExecStart=/bin/sh /etc/openvpn/ssh_tunnels.sh
RemainAfterExit=yes
TimeoutSec=0
GuessMainPID=no
[Install]
WantedBy=multi-user.target
/etc/openvpn/ssh_tunnels.sh:
!/bin/bash
#sleep 15
echo 'Tunelling some ports'
killall -HUP ssh
su - user -c 'ssh -f admin@172.171.1.1 -p 9999 -L :3690:svn.newbox.ru:3690 -L :8888:10.1.20.55:80 -L :8181:10.1.10.10:80 -N -vvv'
ssh -i /home/user/.ssh/id_rsa -f admin@172.171.1.1 -p 9999 -L :587:mail.domain.ru:587 -L :995:mail.newbox.ru:995 -L :22:10.1.2.1:22 -N -vvv &
exit 0
Результат:
# systemctl status ssh_tunnel.service
● ssh_smartex.service - Reverse SSH Service to access hidden services
Loaded: loaded (/etc/systemd/system/ssh_tunnel.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2020-03-20 16:01:07 UTC; 22min ago
Process: 156 ExecStart=/bin/sh /etc/openvpn/ssh_tunnel.sh (code=exited, status=0/SUC>
Tasks: 2 (limit: 4915)
Memory: 3.8M
CGroup: /system.slice/ssh_tunnel.service
├─166 ssh -f admin@172.171.1.1 -p 9999 -L :3690:svn.newbox.ru:3690 -L :8888:10.1.20.55:80 ->
└─168 ssh -i /home/user/.ssh/id_rsa -f admin@172.171.1.1 -p 9999 -L :587:mail.newbox.ru:5>
...
Однако я еще не проверял, как он выживает после перезапуска vpn, но это уже другая тема.