N işlemlerini bir sistemd servis dosyasıyla başlat


36

Bu sistemd servis dosyasını ssh tünelini takip etmek için autossh'ı başlatmak için buldum: 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'yi tek bir servisteki birkaç tüneli başlatacak şekilde yapılandırmanın bir yolu var mı ?

Kopyala + yapıştır işleminden kaçınmak istediğim için N sistem hizmeti dosyaları oluşturmak istemiyorum.

"Remote.example.com" un diğer ana bilgisayar adları ile değiştirilmesi dışında tüm servis dosyaları aynı olacaktır.

1.5 yıl sonra ...

Bu soruyu yaklaşık 1,5 yıl önce sordum.

Aklım biraz değişti. Evet, güzel, bunu systemd ile yapabilirsiniz (hala kullanıyorum), ancak gelecekte yapılandırma yönetimini kullanacağım.

Systemd neden bir şablon dili uygulamalı ve% h yerine geçmeli?

Birkaç ay sonra bu döngünün ve şablonlamanın yapılandırmayı otomatikleştiren bir araçla çözülmesi gerektiğini düşünüyorum. Şimdi bu listenin bir aracını wikipedia'da kullanıyorum .


Başka bir deyişle, bu görevi gerçekleştirmek için birden fazla neredeyse aynı servis dosyası oluşturmak için bir yapılandırma yönetimi sistemi kullandığınızı mı söylüyorsunuz? Hmmm belki. Bu tür konuların çoğunda olduğu gibi, bunları ayıran net bir bölme çizgisi yoktur.
pgoetz

@pgoetz config yönetimi hala benim için yeni, ancak bu sorunun konusuna bakarsanız bir faydası var: config yönetimi sonucuna bakarsanız, systemd servis dosyalarını bilen herkes bunu anlayacaktır: sade ve basit servis dosyaları . Bir config yönetim sistemi öğrenmenin ve kullanmanın daha anlamlı olacağını düşünüyorum çünkü bilgi sadece systemd'de değil / etc içindeki tüm config için de kullanılabilir.
guettli

Yanıtlar:


47

Birim dosya başına değişen tek şeyin parça olduğunu varsayarak, Anlatılmış Bir Servisremote.example.com kullanabilirsiniz .

Gönderen systemd.unitadam sayfası:

İsteğe bağlı olarak, birimler çalışma zamanında bir şablon dosyasından başlatılabilir. Bu, tek bir yapılandırma dosyasından birden fazla ünite oluşturulmasını sağlar. Systemd bir birim yapılandırma dosyası ararsa, ilk önce dosya sistemindeki değişmez birimin adını arayacaktır. Bu başarı vermezse ve ünite adı bir "@" karakteri içeriyorsa, systemd, aynı ismi paylaşan ancak kaldırılan örnek dizesiyle (yani, "@" karakteri ile sonek arasındaki bölüm) bir birim şablonunu arayacaktır. Örnek: eğer bir hizmet getty@tty3.service talep edilirse ve bu isimde bir dosya bulunmazsa, systemd, getty @ .service işlevini arar ve bulunursa, bu yapılandırma dosyasından bir hizmeti başlatır.

Temel olarak, %ifarklılıkların gerçekleştiği bir değişken (genellikle ) içeren tek bir birim dosyası yaratırsınız ve bu servisi "etkinleştirdiğinizde" bağlanırlar.

Örneğin, buna /etc/systemd/system/autossh@.servicebenzeyen bir birim dosyasına sahibim :

[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

Daha sonra etkinleştirdim

[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'

Ve ile etkileşime girebilir

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

Gördüğünüz gibi %i, birim dosyasındaki tüm örnekler ile değiştirilir somehost.example.com.

Bununla birlikte, bir birim dosyasında kullanabileceğiniz bir sürü belirtici var, ancak bunun %igibi durumlarda en iyi sonucu buluyorum .


Vay, sistem harika.
guettli,

Başlamak için olanlar da dahil olmak üzere, açılışta otomatik olarak nasıl başlayacağınızı göstermezsiniz.
Craig Hicks,

Systemd ile enableeylem, bir birimi / hizmeti önyüklemede başlatır.
GregL

Örnekleri bağımsız olarak etkinleştirebilir / devre dışı bırakabilir miyim?
Soumya Kanti

Evet, onları etkinleştirdiğinizde / devre dışı bıraktığınızda yaptığınız şey budur.
GregL

15

İşte aradığım şey bir python örneği. @Servis dosya adında sen N süreçleri başlatmak sağlar:

$ 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

Bunu çağırmak için çeşitli yöntemler

Örneğin çeşitli sayıları etkinleştirme:

  • 30 çalışanı etkinleştir:

    sudo systemctl enable my-worker\@{1..30}.service
    
  • 2 işçiyi etkinleştir:

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

Sonra yeniden yüklediğinizden emin olun:

sudo systemctl daemon-reload

Şimdi çeşitli şekillerde başlatıp / durdurabilirsiniz:

  • 1 başlat:

    sudo systemctl start my-worker@2.service
    
  • Birden Başla:

    sudo systemctl start my-worker@{1..2}
    
  • Birden Çok Durdur:

    sudo systemctl stop my-worker@{1..2}
    
  • Durumu kontrol et:

    sudo systemctl status my-worker@1
    

GÜNCELLEME : Örnekleri bir servis olarak yönetmek için şöyle bir şey yapabilirsiniz:

/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

Ve şimdi tüm örnekleri ile yönetebilirsiniz sudo systemctl some-worker (start|restart|stop)

İşte sizin için bazı kazanlar 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: Anlamadığım iki şey: İlk olarak,% i yalnızca birim dosyasının tanımında kullanılır. Start komutu neyin başlayacağını nasıl biliyor? İkincisi, systemctl some-worker (start|restart|stop)hangi örnekler üzerinde çalışılacağını nasıl bilebilir?
U. Windl

% i, servis dosyası adına göre @ çıkışını gösterir. İkinci kısım cevapta zaten açıklanmış, bkz Now you can start/stop then in various ways.
radtek

Bence senaryolar dahil olmadan cevabı eksik. Çoğu "sihir" eksik olan senaryoların içinde yapılır.
U. Windl

Aslında tam bir çalışma çözümü sağladım. Hangi "betikleri" kastediyorsunuz? /path/to/my/script.py istediğiniz ne olabilir, isterseniz "merhaba dünyası" olabilir. Öldürme sinyali alana kadar çalışmaya devam edecek bir şey. Lütfen sorunun python'a özgü olmadığını unutmayın.
radtek

Vay, bir seferde katları başlatmanıza izin veriyor? zihin şişmiş ...
rogerdpack

1

GregL'in cevabı bana çok yardımcı oldu. Burada, bir tüccar işi sunucusu için yukarıdaki örneği kullanarak kodumda kullandığım bir birim şablonuna bir örnek. Bu şablonu kullanarak X miktarını "işçi" olarak oluşturmama izin veren bir kabuk betiği hazırladım.

[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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.