web-dev-qa-db-fra.com

Variables dynamiques dans les fichiers d'unité de service systemd

Existe-t-il un moyen d'affecter dynamiquement des variables d'environnement dans un fichier d'unité de service systemd?

Nous avons une machine qui a 4 GPU et nous voulons faire tourner plusieurs instances d'un certain service par GPU. Par exemple.:

  • 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
  • à satiété

Ainsi, les 1: 1, 2: 1, etc. sont effectivement le% i dans le fichier d'unité de service.

Pour que le service se lie à un GPU particulier, l'exécutable du service vérifie une certaine variable d'environnement, par exemple:

USE_GPU=4

Existe-t-il un moyen de prendre% i dans le fichier d'unité de service et de l'exécuter via une fonction (Shell) pour dériver le numéro de GPU, puis je peux définir la variable d'environnement USE_GPU en conséquence?

Plus important encore, je ne veux pas les tracas de l'écriture de plusieurs /etc/systemd/system/gpu_service@x:y.service/local.conf fichiers juste pour que je puisse faire tourner plus d'instances.

15
Kal

Si vous faites attention, vous pouvez incorporer une petite séquence de script bash en tant que commande exec dans le fichier de service d'instance. Par exemple

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

Le $$ dans la chaîne deviendra un simple $ dans le résultat passé à bash, mais surtout arrêtera ${...} d'être interpolé par systemd. (Les versions antérieures de systemd ne documentaient pas l'utilisation de $$, donc je ne sais pas si c'était supporté alors).

11
meuh

Pas de manière intégrée. Vous devez effectuer ces opérations avant le début de votre service. Une façon serait de le placer dans un fichier d'environnement.

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

Il semble que vous puissiez en effet définir des variables d'environnement dans un fichier d'unité systemd ...

Selon les suggestions des commentateurs, voici la solution:

Utilisation de variables d'environnement dans les unités systemd

Directive environnement

systemd a une directive Environnement qui définit les variables d'environnement pour les processus exécutés. Il prend une liste des affectations de variables séparées par des espaces. Cette option peut être spécifiée plusieurs fois, auquel cas toutes les variables répertoriées seront définies. Si la même variable est définie deux fois, le paramètre le plus récent remplacera le paramètre précédent. Si la chaîne vide est affectée à cette option, la liste des variables d'environnement est réinitialisée, toutes les affectations antérieures n'ont aucun effet. Les directives d'environnements sont utilisées dans les unités Systemd Container Linux intégrées, par exemple dans etcd2 et flannel.

Avec l'exemple ci-dessous, vous pouvez configurer votre démon etcd2 pour utiliser le chiffrement. Créez simplement /etc/systemd/system/etcd2.service.d/30-certificates.conf drop-in pour 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

Exécutez ensuite Sudo systemctl daemon-reload et Sudo systemctl restart etcd2.service pour appliquer de nouveaux environnements au démon etcd2.

Texte cité à partir de l'URL suivante: https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html

3
CyberK

C'est moche et pas tout à fait ce que vous avez demandé, ni autoriser le démarrage automatique, mais pour les adeptes, il est possible de faire quelque chose en utilisant le systemctl environnement :

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

J'essaie juste d'énumérer toutes les façons possibles :)

0
rogerdpack