web-dev-qa-db-ja.com

1つのsystemdサービスファイルでNプロセスを開始する

Sshトンネルを維持するためにautosshを開始するこのsystemdサービスファイルが見つかりました: 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

oneサービスで複数のトンネルを開始するようにsystemdを設定する方法はありますか?.

コピーと貼り付けを避けたいので、N個のシステムサービスファイルを作成したくありません。

「remote.example.com」が他のホスト名で置き換えられることを除いて、すべてのサービスファイルは同一です。

1。5年後...

約1.5年前にこの質問をしました。

私の心は変わった。はい、それはいいです。systemdでこれを行うことができますが、将来は構成管理を使用します。

Systemdがテンプレート言語を実装して%hを置き換える必要があるのはなぜですか? ..それは意味がないと思います。

数か月後、このループとテンプレート化は別のレベルで解決する必要があると思います。今は、AnsibleまたはTerraFormを使用します。

39
guettli

まあ、only単位ファイルごとに変化するものが_remote.example.com_の部分であると仮定すると、 Instantiated を使用できます サービス

_systemd.unit_ manページから:

オプションで、実行時にテンプレートファイルからユニットをインスタンス化できます。これにより、単一の構成ファイルから複数のユニットを作成できます。 systemdがユニット構成ファイルを検索する場合、最初にファイルシステムでリテラルユニット名を検索します。それが成功せず、ユニット名に「@」文字が含まれている場合、systemdは同じ名前を共有するが、インスタンス文字列(つまり、「@」文字とサフィックスの間の部分)が削除されたユニットテンプレートを探します。例:サービス[email protected]が要求され、その名前のファイルが見つからない場合、systemdはgetty @ .serviceを探し、見つかった場合はその構成ファイルからサービスをインスタンス化します。

基本的に、変数が含まれる単一のユニットファイルを作成します。通常は_%i_)で違いが発生し、そのサービスを「有効」にするとリンクされます。

たとえば、次のような_/etc/systemd/system/[email protected]_というユニットファイルがあります。

_[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 [email protected]
ln -s '/etc/systemd/system/[email protected]' '/etc/systemd/system/multi-user.target.wants/[email protected]'
_

そしてと相互作用することができます

_[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.
_

ご覧のとおり、ユニットファイル内の_%i_のすべてのインスタンスは_somehost.example.com_に置き換えられます。

ユニットファイルで使用できる specifiers が他にもたくさんありますが、このような場合に_%i_が最適に機能することがわかりました。

50
GregL

ここにpythonの例があります。これは私が探していたものです。サービスファイル名の_@_を使用すると、Nプロセスを開始できます。

_$ 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
_

それを呼び出すためのさまざまなメソッド

たとえば、さまざまなカウントを有効にします。

  • 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 [email protected]
    _
  • 複数開始:

    _Sudo systemctl start my-worker@{1..2}
    _
  • 複数停止:

    _Sudo systemctl stop my-worker@{1..2}
    _
  • ステータスを確認:

    _Sudo systemctl status my-worker@1
    _

[〜#〜] update [〜#〜]:インスタンスを1つのサービスとして管理するには、次のようにします。

/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
_

そして今、あなたは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()
_
19
radtek

GregLの答えは私を大いに助けました。上記のギアマンジョブサーバーの例を使用してコードで使用したユニットテンプレートの例を次に示します。この1つのテンプレートを使用して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
1
Kyle Anderson

私は同様のタスクの解決策を検索し、実際に1つ見つけました。それは達成する方が簡単だと思いますが、 hacky であるはずです。 (ここでは言及されていません)

VPNがトンネルを作成した後に複数のssh接続を作成する必要があったので、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 [email protected] -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 [email protected] -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 [email protected] -p 9999 -L :3690:svn.newbox.ru:3690 -L :8888:10.1.20.55:80 ->
             └─168 ssh -i /home/user/.ssh/id_rsa -f [email protected] -p 9999 -L :587:mail.newbox.ru:5>
...

しかし、私はまだ確認していません、それがどのようにvpnの再起動に耐えられるかを確認していませんが、それは別のトピックです。

0
diabolusss