Biến động trong tệp đơn vị dịch vụ systemd


14

Có cách nào để tự động gán các biến môi trường trong tệp đơn vị dịch vụ systemd không?

Chúng tôi có một máy có 4 GPU và chúng tôi muốn tạo ra nhiều phiên bản của một dịch vụ nhất định cho mỗi GPU. Ví dụ:

  • gpu_service @ 1: 1. dịch vụ
  • gpu_service @ 2: 1. dịch vụ
  • gpu_service @ 3: 1. dịch vụ
  • gpu_service @ 4: 1. dịch vụ
  • gpu_service @ 1: 2. dịch vụ
  • gpu_service @ 2: 2. dịch vụ
  • gpu_service @ 3: 2. dịch vụ
  • gpu_service @ 4: 2. dịch vụ
  • quảng cáo

Vì vậy, 1: 1, 2: 1, v.v ... thực sự là% i trong tệp đơn vị dịch vụ.

Để dịch vụ liên kết với một GPU cụ thể, bộ thực thi dịch vụ sẽ kiểm tra một biến môi trường nhất định, ví dụ:

USE_GPU=4

Có cách nào để tôi có thể lấy% i trong tệp đơn vị dịch vụ và chạy nó thông qua một số chức năng (shell) để lấy số GPU, và sau đó tôi có thể đặt biến môi trường USE_GPU tương ứng không?

Quan trọng nhất, tôi không muốn rắc rối khi viết nhiều /etc/systemd/system/gpu_service@x:y.service/local.conftệp chỉ để tôi có thể tạo ra nhiều phiên bản hơn.

Câu trả lời:


10

Nếu bạn cẩn thận, bạn có thể kết hợp một chuỗi tập lệnh bash nhỏ làm lệnh exec của bạn trong tệp dịch vụ cá thể. Ví dụ

ExecStart=/bin/bash -c 'v=%i; USE_GPU=$${v%:*} exec /bin/mycommand'

Chuỗi $$trong sẽ trở thành một đơn $trong kết quả được chuyển sang bash, nhưng quan trọng hơn là sẽ không ${...}bị nội suy bởi systemd. (Các phiên bản trước của systemd không ghi lại việc sử dụng $$, vì vậy tôi không biết liệu nó có được hỗ trợ không).


Tôi cuối cùng đã làm một cái gì đó như thế. :)
Kal

1
Gọi a bash -cđể bắt đầu một chương trình từ tập tin đơn vị? Gọi exec? Điều này giống như sử dụng xe nâng trên đầu xe nâng (có thể có xe nâng khác ở trên) vì xe nâng đầu tiên gặp sự cố thực sự là xe nâng.
David Tonhofer

Thật không may, bạn không thể sử dụng ExecStartPre để viết tệp env, sau đó sử dụng nó, rõ ràng nó phải được viết trước, vì vậy một cái gì đó như thế này sẽ hoạt động. Hoặc một tập lệnh bao bọc để thực hiện việc chia tách :) Tùy chọn kỳ lạ khác sẽ là tạo một dịch vụ khác để thiết lập env. tệp, không chắc cách thức hoạt động với các mẫu tho: stackoverflow.com/a/42841480/32453
rogerdpack

8

Không được xây dựng theo cách. Bạn cần làm những điều này trước khi dịch vụ của bạn bắt đầu. Một cách sẽ được đặt nó vào một tập tin môi trường.

[Service]
# Note you need to escape percentage sign
ExecStartPre=/bin/sh -c "my_awesome_parser %%i > /run/gpu_service_%i"
EnvironmentFile=/run/gpu_service_%i
ExecStart=...

4

Có vẻ như bạn thực sự có thể đặt các biến môi trường bên trong tệp đơn vị systemd ...

Theo đề xuất từ ​​các bình luận viên, đây là giải pháp:

Sử dụng các biến môi trường trong các đơn vị systemd

Chỉ thị môi trường

systemd có một lệnh môi trường đặt các biến môi trường cho các quy trình được thực hiện. Nó có một danh sách phân tách không gian của các bài tập biến. Tùy chọn này có thể được chỉ định nhiều lần trong trường hợp tất cả các biến được liệt kê sẽ được đặt. Nếu cùng một biến được đặt hai lần, cài đặt sau sẽ ghi đè cài đặt trước đó. Nếu chuỗi rỗng được gán cho tùy chọn này, danh sách các biến môi trường được đặt lại, tất cả các phép gán trước không có hiệu lực. Các chỉ thị môi trường được sử dụng trong các đơn vị hệ thống Container Linux tích hợp, ví dụ như trong etcd2 và flannel.

Với ví dụ dưới đây, bạn có thể định cấu hình trình nền etcd2 của mình để sử dụng mã hóa. Chỉ cần tạo /etc/systemd/system/etcd2.service.d/30-certificates.conftrình đơn cho etcd2.service:

[Service]
# Client Env Vars
Environment=ETCD_CA_FILE=/path/to/CA.pem
Environment=ETCD_CERT_FILE=/path/to/server.crt
Environment=ETCD_KEY_FILE=/path/to/server.key
# Peer Env Vars
Environment=ETCD_PEER_CA_FILE=/path/to/CA.pem
Environment=ETCD_PEER_CERT_FILE=/path/to/peers.crt
Environment=ETCD_PEER_KEY_FILE=/path/to/peers.key

Sau đó chạy sudo systemctl daemon-reloadsudo systemctl restart etcd2.serviceáp dụng các môi trường mới cho vvd2 daemon.

Văn bản trích dẫn được lấy từ URL sau: https://coreos.com/os/docs/latest/USE-en môi-biến-in-systemd-units.html


2
Mặc dù điều này về mặt lý thuyết có thể trả lời câu hỏi, tốt hơnnên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo.
Stephen Rauch

1
Mặc dù bình luận của bạn về mặt lý thuyết có thể cải thiện các phản hồi trong tương lai của tôi trong stackexchange, nhưng tốt hơn hết là bạn nên đưa các phần thiết yếu của câu trả lời vào bình luận của mình thay vì chỉ bình luận để chỉ ra ai đó không đủ năng lực :)
CyberK

1
Chào mừng bạn đến với Sàn giao dịch Stack! Cảm ơn vì nhận xét, bạn đã làm tôi mỉm cười. Cũng cảm ơn vì đã dành thời gian để chỉnh sửa câu trả lời của bạn. Chúng tôi đang cố gắng xây dựng một cái gì đó sẽ có giá trị theo thời gian và chỉ liên kết các câu trả lời không đủ tuổi.
Stephen Rauch

Nếu bạn thêm Environment=ABC=%inó sẽ đặt env. biến "thành toàn bộ% i". Tôi đoán bạn có thể tạo một trình bao bọc để loại bỏ "nội dung nằm ngoài trích dẫn" mà bạn không muốn và nó gọi là thực thi thực sự. Nhưng nếu bạn đang tạo một trình bao bọc, bạn thậm chí có thể chuyển qua %ilàm đối số cho nó, ví dụ:ExecStart=my_wrapper %i
rogerdpack

0

Nó xấu và không hoàn toàn như những gì bạn yêu cầu, cũng không cho phép tự động khởi động, nhưng đối với những người theo dõi có thể làm điều gì đó bằng môi trường systemctl :

$ sudo systemctl set-environment USE_GPU=4 # add it to the env. variables for future services
$ sudo systemctl start gpu_service@4:2.service

Chỉ cần cố gắng liệt kê tất cả các cách có thể :)

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.