Bắt đầu N quy trình với một tệp dịch vụ systemd


36

Tôi tìm thấy tệp dịch vụ systemd này để bắt đầu autossh để theo kịp đường hầm 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

Có cách nào để cấu hình systemd để bắt đầu một số đường hầm trong một dịch vụ.

Tôi không muốn tạo N tệp dịch vụ hệ thống, vì tôi muốn tránh sao chép + dán.

Tất cả các tệp dịch vụ sẽ giống hệt nhau ngoại trừ "remote.example.com" sẽ được thay thế bằng các tên máy chủ khác.

1,5 năm sau ...

Tôi đã hỏi câu hỏi này khoảng 1,5 năm trước.

Tâm trí tôi đã thay đổi một chút. Vâng, thật tuyệt, bạn có thể làm điều này với systemd (tôi vẫn sử dụng nó), nhưng tôi sẽ sử dụng quản lý cấu hình trong tương lai.

Tại sao systemd nên triển khai ngôn ngữ mẫu và thay thế% h?

Vài tháng sau tôi nghĩ rằng vòng lặp và khuôn mẫu này sẽ được giải quyết bằng một công cụ tự động hóa cấu hình. Tôi sử dụng một công cụ của danh sách này tại wikipedia bây giờ.


Nói cách khác, bạn đang nói sử dụng một hệ thống quản lý cấu hình để tạo nhiều tệp dịch vụ gần như giống hệt nhau để thực hiện nhiệm vụ này? Hmmm có thể. Như với hầu hết các vấn đề như vậy, không có một đường phân chia rõ ràng ngăn cách những điều này.
pgoetz

Quản lý cấu hình @pgoetz vẫn còn mới đối với tôi, nhưng nó có lợi nếu bạn nhìn vào chủ đề của câu hỏi này: Nếu bạn nhìn vào kết quả của việc quản lý cấu hình, mọi người biết tệp dịch vụ systemd sẽ hiểu nó: tệp dịch vụ đơn giản và đơn giản . Tôi nghĩ sẽ có ý nghĩa hơn khi tìm hiểu và sử dụng hệ thống quản lý cấu hình vì kiến ​​thức có thể được sử dụng cho tất cả cấu hình trong / etc, không chỉ systemd.
guettli

Câu trả lời:


47

Vâng, giả định rằng chỉ điều thay đổi cho mỗi tập tin đơn vị là remote.example.commột phần, bạn có thể sử dụng một khởi tạo dịch vụ .

Từ systemd.unittrang người đàn ông:

Tùy chọn, các đơn vị có thể được khởi tạo từ một tệp mẫu khi chạy. Điều này cho phép tạo nhiều đơn vị từ một tệp cấu hình duy nhất. Nếu systemd tìm tệp cấu hình đơn vị, trước tiên nó sẽ tìm kiếm tên đơn vị bằng chữ trong hệ thống tệp. Nếu điều đó không mang lại thành công và tên đơn vị chứa ký tự "@", systemd sẽ tìm một mẫu đơn vị có cùng tên nhưng với chuỗi thể hiện (nghĩa là phần giữa ký tự "@" và hậu tố) bị xóa. Ví dụ: nếu một dịch vụ getty@tty3.service được yêu cầu và không tìm thấy tệp nào có tên đó, systemd sẽ tìm getty @ .service và khởi tạo một dịch vụ từ tệp cấu hình đó nếu tìm thấy.

Về cơ bản, bạn tạo một tệp đơn vị chứa một biến (thường là %i) trong đó sự khác biệt xảy ra và sau đó chúng được liên kết khi bạn "bật" dịch vụ đó.

Ví dụ: tôi có một tệp đơn vị được gọi là /etc/systemd/system/autossh@.servicenhư thế này:

[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

Mà tôi đã kích hoạt

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

Và có thể can thiệp với

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

Như bạn có thể thấy, tất cả các phiên bản của %itệp đơn vị được thay thế bằng somehost.example.com.

Có rất nhiều công cụ xác định mà bạn có thể sử dụng trong một tệp đơn vị, nhưng tôi thấy %ihoạt động tốt nhất trong các trường hợp như thế này.


Wow, systemd thật tuyệt
guettli

Bạn không chỉ ra cách bắt đầu tự động khi khởi động, bao gồm cả những cái để bắt đầu.
Craig Hicks

Với Systemd, enablehành động là thứ khiến cho một đơn vị / dịch vụ bắt đầu khi khởi động.
GregL

Tôi có thể độc lập kích hoạt / vô hiệu hóa các thể hiện không?
Soumya Kanti

Vâng, đó là những gì bạn đang làm khi bạn bật / tắt chúng.
GregL

15

Đây là một ví dụ về con trăn, đó là những gì tôi đang tìm kiếm. Tên @tệp dịch vụ cho phép bạn bắt đầu N quy trình:

$ 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

Phương pháp khác nhau để gọi nó

Kích hoạt số lượng khác nhau, ví dụ:

  • Cho phép 30 công nhân:

    sudo systemctl enable my-worker\@{1..30}.service
    
  • Cho phép 2 công nhân:

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

Sau đó hãy chắc chắn để tải lại:

sudo systemctl daemon-reload

Bây giờ bạn có thể bắt đầu / dừng sau đó theo nhiều cách khác nhau:

  • Bắt đầu 1:

    sudo systemctl start my-worker@2.service
    
  • Bắt đầu nhiều:

    sudo systemctl start my-worker@{1..2}
    
  • Dừng nhiều:

    sudo systemctl stop my-worker@{1..2}
    
  • Kiểm tra trạng thái:

    sudo systemctl status my-worker@1
    

CẬP NHẬT : Để quản lý các phiên bản dưới dạng một dịch vụ, bạn có thể làm một cái gì đó như thế này:

/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

Và bây giờ bạn có thể quản lý tất cả các trường hợp với sudo systemctl some-worker (start|restart|stop)

Đây là một số mẫu cho bạn 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: Hai điều tôi không hiểu: Thứ nhất,% i chỉ được sử dụng trong phần mô tả của tệp đơn vị. Làm thế nào để lệnh bắt đầu biết những gì để bắt đầu? Thứ hai, làm thế nào để systemctl some-worker (start|restart|stop)biết trường hợp nào để làm việc trên?
U. Windl

% i là đầu ra từ @ trong tên của tệp dịch vụ. Phần thứ hai đã được giải thích trong câu trả lời, xem Now you can start/stop then in various ways.
radtek

Tôi nghĩ rằng câu trả lời của anh ấy là không đầy đủ mà không có kịch bản được tham gia. Hầu hết "phép thuật" được thực hiện bên trong các tập lệnh bị thiếu.
U. Windl

Tôi đã cung cấp một giải pháp làm việc đầy đủ ở đây thực sự. Những "kịch bản" mà bạn đang đề cập đến? /path/to/my/script.py có thể là bất cứ điều gì bạn muốn, một "thế giới xin chào" nếu bạn muốn. Một cái gì đó sẽ tiếp tục chạy cho đến khi nhận được tín hiệu tiêu diệt. Xin lưu ý câu hỏi không dành riêng cho trăn.
radtek

Wow nó cho phép bạn bắt đầu bội số cùng một lúc? tâm trí bị thổi bay ...
rogerdpack

1

Câu trả lời của GregL đã giúp tôi rất nhiều. Dưới đây là một ví dụ về một mẫu đơn vị tôi đã sử dụng trong mã của mình bằng cách sử dụng ví dụ trên cho một máy chủ công việc gearman. Tôi đã tạo một tập lệnh shell cho phép tôi tạo X lượng "công nhân" bằng cách sử dụng một mẫu này.

[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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.