Mulai proses N dengan satu file layanan systemd

36

Saya menemukan file layanan systemd ini untuk memulai autossh untuk menjaga terowongan 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

Apakah ada cara untuk mengkonfigurasi systemd untuk memulai beberapa terowongan dalam satu layanan.

Saya tidak ingin membuat file layanan sistem N, karena saya ingin menghindari copy + paste.

Semua file layanan akan identik kecuali "remote.example.com" akan diganti dengan nama host lainnya.

1,5 tahun kemudian ...

Saya menanyakan pertanyaan ini sekitar 1,5 tahun yang lalu.

Pikiranku telah sedikit berubah. Ya, itu menyenangkan, bahwa Anda dapat melakukan ini dengan systemd (saya masih menggunakannya), tetapi saya akan menggunakan manajemen konfigurasi di masa depan.

Mengapa systemd harus mengimplementasikan bahasa templat dan mengganti% h?

Beberapa bulan kemudian saya pikir loop dan template ini harus diselesaikan dengan alat yang mengotomatiskan konfigurasi. Saya menggunakan satu alat daftar ini di wikipedia sekarang.

guettli
sumber
Dengan kata lain, Anda mengatakan menggunakan sistem manajemen konfigurasi untuk menghasilkan beberapa file layanan yang hampir identik untuk menyelesaikan tugas ini? Hmmm, mungkin. Seperti kebanyakan hal seperti itu, tidak ada garis pemisah yang memisahkan ini.
pgoetz
@pgoetz manajemen konfigurasi masih baru bagi saya, tetapi memiliki manfaat jika Anda melihat topik pertanyaan ini: Jika Anda melihat hasil dari manajemen konfigurasi, semua orang yang mengetahui file layanan systemd akan memahaminya: file layanan sederhana dan sederhana . Saya pikir lebih masuk akal untuk belajar dan menggunakan sistem manajemen konfigurasi karena pengetahuan dapat digunakan untuk semua konfigurasi di / etc, bukan hanya systemd.
guettli

Jawaban:

47

Nah, dengan asumsi bahwa satu - satunya hal yang berubah per unit file adalah remote.example.combagian, Anda dapat menggunakan Layanan Instantiated .

Dari systemd.unithalaman manual:

Secara opsional, unit dapat dipakai dari file template saat runtime. Ini memungkinkan pembuatan beberapa unit dari satu file konfigurasi. Jika systemd mencari file konfigurasi unit, pertama-tama akan mencari nama unit literal dalam sistem file. Jika itu tidak menghasilkan keberhasilan dan nama unit berisi karakter "@", systemd akan mencari template unit yang berbagi nama yang sama tetapi dengan string instance (yaitu bagian antara karakter "@" dan akhiran) dihapus. Contoh: jika layanan [email protected] diminta dan tidak ada file dengan nama itu ditemukan, systemd akan mencari getty @ .service dan instantiate layanan dari file konfigurasi itu jika ditemukan.

Pada dasarnya, Anda membuat file unit tunggal, yang berisi variabel (biasanya %i) di mana perbedaan terjadi dan kemudian mereka ditautkan ketika Anda "mengaktifkan" layanan itu.

Misalnya, saya memiliki file unit bernama /etc/systemd/system/[email protected]yang terlihat seperti ini:

[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

Yang kemudian saya aktifkan

[user@anotherhost ~]$ sudo systemctl enable [email protected]
ln -s '/etc/systemd/system/[email protected]' '/etc/systemd/system/multi-user.target.wants/[email protected]'

Dan bisa berinteraksi dengan

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

Seperti yang Anda lihat, semua instance %idalam file unit bisa diganti somehost.example.com.

Ada banyak specifier yang bisa Anda gunakan dalam file unit, tapi saya menemukan %icara terbaik dalam kasus seperti ini.

GregL
sumber
Wow, systemd bagus.
guettli
Anda tidak menunjukkan cara memulai secara otomatis saat boot, termasuk yang memulai.
Craig Hicks
Dengan Systemd, enabletindakan itulah yang membuat unit / layanan mulai saat boot.
GregL
Bisakah saya secara mandiri mengaktifkan / menonaktifkan instans?
Soumya Kanti
Ya, itulah yang Anda lakukan ketika Anda mengaktifkan / menonaktifkannya.
GregL
15

Berikut adalah contoh python, yang adalah apa yang saya cari. Nama @file dalam layanan memungkinkan Anda memulai proses 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

Berbagai metode menyebutnya

Mengaktifkan berbagai penghitungan misalnya:

  • Aktifkan 30 pekerja:

    sudo systemctl enable my-worker\@{1..30}.service
    
  • Aktifkan 2 pekerja:

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

Maka pastikan untuk memuat ulang:

sudo systemctl daemon-reload

Sekarang Anda dapat memulai / berhenti kemudian dengan berbagai cara:

  • Mulai 1:

    sudo systemctl start [email protected]
    
  • Mulai Banyak:

    sudo systemctl start my-worker@{1..2}
    
  • Hentikan Beberapa:

    sudo systemctl stop my-worker@{1..2}
    
  • Periksa status:

    sudo systemctl status my-worker@1
    

UPDATE : Untuk mengelola instance sebagai satu layanan, Anda dapat melakukan sesuatu seperti ini:

/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

Dan sekarang Anda dapat mengelola semua instance dengan sudo systemctl some-worker (start|restart|stop)

Berikut ini beberapa boilerplate untuk Anda 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()
radtek
sumber
@radek: Dua hal yang saya tidak mengerti: Pertama,% i hanya digunakan dalam deskripsi file unit. Bagaimana perintah mulai tahu apa yang harus mulai? Kedua, bagaimana systemctl some-worker (start|restart|stop)tahu contoh mana yang harus dikerjakan?
U. Windl
% i adalah output dari @ atas nama file layanan. Bagian kedua sudah dijelaskan dalam jawabannya, lihat Now you can start/stop then in various ways.
radtek
Saya pikir jawabannya tidak lengkap tanpa skrip terlibat. Kebanyakan "sihir" dilakukan di dalam skrip yang hilang.
U. Windl
Sebenarnya saya telah memberikan solusi kerja lengkap. "Script" mana yang Anda maksud? /path/to/my/script.py dapat menjadi apa pun yang Anda inginkan, "hello world" jika Anda mau. Sesuatu yang akan tetap berjalan sampai menerima sinyal mematikan. Harap perhatikan bahwa pertanyaannya tidak spesifik untuk python.
radtek
Wow, ini memungkinkan Anda memulai kelipatan sekaligus? mind blown ...
rogerdpack
1

Jawaban GregL sangat membantu saya. Berikut adalah contoh templat unit yang saya gunakan dalam kode saya menggunakan contoh di atas untuk server pekerjaan tukang gigi. Saya membuat skrip shell yang memungkinkan saya membuat jumlah X "pekerja" menggunakan templat yang satu ini.

[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
Kyle Anderson
sumber