Variabel dinamis dalam file unit layanan systemd

14

Apakah ada cara untuk secara dinamis menetapkan variabel lingkungan dalam file unit layanan systemd?

Kami memiliki mesin yang memiliki 4 GPU, dan kami ingin menambah beberapa instance layanan tertentu per GPU. Misalnya:

  • gpu_service @ 1: 1.service
  • gpu_service @ 2: 1.service
  • gpu_service @ 3: 1.service
  • gpu_service @ 4: 1.service
  • gpu_service @ 1: 2.service
  • gpu_service @ 2: 2.service
  • gpu_service @ 3: 2.service
  • gpu_service @ 4: 2.service
  • ad mual

Jadi 1: 1, 2: 1, dll. Secara efektif adalah% i dalam file unit layanan.

Agar layanan dapat mengikat GPU tertentu, layanan yang dapat dieksekusi memeriksa variabel lingkungan tertentu, misalnya:

USE_GPU=4

Apakah ada cara saya dapat mengambil% i di dalam file unit layanan dan menjalankannya melalui beberapa fungsi (shell) untuk mendapatkan nomor GPU, dan kemudian saya dapat mengatur variabel lingkungan USE_GPU sesuai?

Yang paling penting, saya tidak ingin repot menulis banyak /etc/systemd/system/gpu_service@x:y.service/local.conffile hanya supaya saya dapat memutar lebih banyak instance.

Kal
sumber

Jawaban:

10

Jika Anda berhati-hati, Anda dapat memasukkan urutan skrip bash kecil sebagai perintah exec Anda dalam file layanan contoh. Misalnya

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

Di $$dalam string akan menjadi tunggal $dalam hasil dilewatkan ke bash, tetapi yang lebih penting akan berhenti ${...}dari diinterpolasi oleh systemd. (Versi sebelumnya dari systemd tidak mendokumentasikan penggunaan $$, jadi saya tidak tahu apakah itu didukung kemudian).

meuh
sumber
Saya akhirnya melakukan sesuatu seperti itu. :)
Kal
1
Panggil a bash -cuntuk memulai program dari file unit? Telepon exec? Ini seperti menggunakan forklift di atas forklift (mungkin dengan forklift lain di atas) karena forklift pertama memiliki masalah sebenarnya forklifting.
David Tonhofer
Sayangnya Anda tidak dapat menggunakan ExecStartPre untuk menulis file env, kemudian menggunakannya, rupanya itu harus ditulis terlebih dahulu, jadi sesuatu seperti ini akan berhasil. Atau skrip wrapper untuk melakukan pemisahan :) Pilihan aneh lainnya adalah membuat layanan lain untuk mengatur env. file, tidak yakin bagaimana itu akan bekerja dengan template tho: stackoverflow.com/a/42841480/32453
rogerdpack
8

Tidak dibangun di jalan. Anda perlu melakukan hal-hal ini sebelum layanan Anda dimulai. Salah satu caranya adalah dengan meletakkannya di file lingkungan.

[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=...
Umut
sumber
4

Sepertinya Anda memang dapat mengatur variabel lingkungan di dalam file unit systemd ...

Per saran dari komentator, inilah solusinya:

Menggunakan variabel lingkungan dalam unit systemd

Arahan lingkungan

systemd memiliki arahan Lingkungan yang menetapkan variabel lingkungan untuk proses yang dieksekusi. Dibutuhkan daftar tugas variabel yang dipisahkan oleh ruang. Opsi ini dapat ditentukan lebih dari satu kali dalam hal ini semua variabel yang terdaftar akan ditetapkan. Jika variabel yang sama diatur dua kali, pengaturan kemudian akan menimpa pengaturan sebelumnya. Jika string kosong ditetapkan ke opsi ini, daftar variabel lingkungan disetel ulang, semua tugas sebelumnya tidak berpengaruh. Arahan lingkungan digunakan dalam unit systemd Container Linux bawaan, misalnya dalam etcd2 dan flanel.

Dengan contoh di bawah ini, Anda dapat mengkonfigurasi daemon etcd2 Anda untuk menggunakan enkripsi. Cukup buat /etc/systemd/system/etcd2.service.d/30-certificates.confdrop-in untuk 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

Kemudian jalankan sudo systemctl daemon-reloaddan sudo systemctl restart etcd2.serviceuntuk menerapkan lingkungan baru ke daemon etcd2.

Teks yang dikutip diambil dari URL berikut: https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html

CyberK
sumber
2
Meskipun ini secara teoritis dapat menjawab pertanyaan, akan lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
Stephen Rauch
1
Sementara komentar Anda secara teoritis dapat meningkatkan respons masa depan saya di stackexchange, akan lebih baik bagi Anda untuk memasukkan bagian-bagian penting dari jawaban dalam komentar Anda alih-alih hanya berkomentar untuk menunjukkan betapa tidak kompetennya seseorang :)
CyberK
1
Selamat Datang di Stack Exchange! Terima kasih atas komentarnya, Anda membuat saya tersenyum. Juga terima kasih telah meluangkan waktu untuk mengedit jawaban Anda. Kami mencoba membangun sesuatu yang akan memiliki nilai dari waktu ke waktu, dan menautkan hanya jawaban saja yang tidak menua dengan baik.
Stephen Rauch
Jika Anda menambahkannya Environment=ABC=%itidak mengatur env itu. variabel "hingga keseluruhan% i". Saya kira Anda bisa membuat pembungkus untuk menanggalkan "hal-hal di luar kutipan" yang tidak Anda inginkan, dan itu disebut executable nyata. Tetapi jika Anda membuat pembungkus, Anda bahkan bisa lewat %isebagai argumen untuk itu ex:ExecStart=my_wrapper %i
rogerdpack
0

Ini jelek dan tidak sesuai dengan yang Anda minta, juga tidak memungkinkan untuk memulai otomatis, tetapi untuk pengikut dimungkinkan untuk melakukan sesuatu menggunakan lingkungan 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

Hanya mencoba daftar semua cara yang mungkin :)

rogerdpack
sumber