Question Comment définir la variable d'environnement dans le service systemd?


j'ai un Système Arch Linux avec systemd et j'ai créé mon propre service. Le service de configuration chez /etc/systemd/system/myservice.service ressemble à ça:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Maintenant, je veux avoir une variable d'environnement définie pour le /bin/myforegroundcmd. Comment je fais ça?


119
2017-08-01 19:43


origine




Réponses:


Les temps changent, tout comme les meilleures pratiques.

le actuel La meilleure façon de faire est de courir systemctl edit myservice, ce qui créera un fichier de remplacement pour vous ou vous permettra d’éditer un fichier existant.

Dans les installations normales, cela créera un répertoire /etc/systemd/system/myservice.service.det dans ce répertoire, créez un fichier dont le nom se termine par .conf (typiquement, override.conf), et dans ce fichier, vous pouvez ajouter ou remplacer toute partie de l’unité livrée par la distribution.

Par exemple, dans un fichier /etc/systemd/system/myservice.service.d/myenv.conf:

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"

Notez également que si le répertoire existe et est vide, votre service sera désactivé! Si vous n'avez pas l'intention de mettre quelque chose dans le répertoire, assurez-vous qu'il n'existe pas.


Pour référence, l'ancienne manière était:

La manière recommandée faire ceci est de créer un fichier /etc/sysconfig/myservice qui contient vos variables, puis chargez-les avec EnvironmentFile.

Pour plus de détails, voir la documentation de Fedora sur comment écrire un script systemd.


143
2017-08-01 20:07



Je suppose que le sysconfig chemin est spécifique à Fedora mais la question concerne Arch Linux. La réponse de paluh est plus intéressante je pense - Ludovic Kuty
/etc/sysconfig est spécifique à Fedora. AFAIR Arch Linux insistait pour que les fichiers de configuration soient spécifiques à un paquet plutôt que dans /etc plutôt que cet emplacement spécifique à Fedora. Comme /etc/myservice.conf, bien qu'utiliser un fichier supplémentaire ne semble pas être la bonne solution ici - Michał Górny
Non non Non. / etc / sysconfig n'est pas recommandé. Il est déconseillé, de même que / etc / default / * de debian, car ils sont inutiles et les noms n’ont pas de sens et n’ont de sens que pour des raisons de compatibilité avec les versions antérieures (tout / etc concerne la configuration du système, pas seulement / etc / sysconfig, et / etc / defaults est destiné aux substitutions, pas aux valeurs par défaut). Il suffit de placer les définitions directement dans le fichier unité, ou si cela n’est pas possible, dans un fichier d’environnement contenant un emplacement spécifique au paquet (comme le suggère le commentaire de Michał). - zbyszek
@FrederickNord C'est juste des paires variable = valeur, telles que DJANGO_SETTINGS_MODULE=project.settings, un par ligne. - Michael Hampton♦
@ MichaelHampton Pourriez-vous s'il vous plaît ajouter un lien de documentation pour "meilleure façon actuelle"? - jb.


La réponse dépend de si la variable est supposée être constante (c'est-à-dire, non censée être modifiée par l'utilisateur obtenant l'unité) ou variable (supposée être définie par l'utilisateur).

Puisqu'il s'agit de votre unité locale, la limite est assez floue et de toute façon, cela fonctionnerait. Cependant, si vous commenciez à le distribuer et que cela finirait par /usr/lib/systemd/system, cela deviendrait important.

Valeur constante

Si la valeur n'a pas besoin de changer par instance, la méthode recommandée consiste à la placer comme suit. Environment=, directement dans le fichier unité:

[Unit]
Description=My Daemon

[Service]
Environment="FOO=bar baz"
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

L'avantage de cela est que la variable est conservée dans un seul fichier avec l'unité. Par conséquent, le fichier d'unité est plus facile à déplacer entre les systèmes.

Valeur variable

Cependant, la solution ci-dessus ne fonctionne pas bien lorsque sysadmin est supposé changer la valeur de la variable d'environnement localement. Plus spécifiquement, la nouvelle valeur devra être définie chaque fois que le fichier d'unité est mis à jour.

Dans ce cas, un fichier supplémentaire doit être utilisé. Comment - dépend généralement de la politique de distribution.

Une solution particulièrement intéressante consiste à utiliser /etc/systemd/system/myservice.service.d annuaire. Contrairement à d'autres solutions, ce répertoire est pris en charge par systemd lui-même et ne comporte donc aucun chemin spécifique à la distribution.

Dans ce cas, vous placez un fichier comme /etc/systemd/system/myservice.service.d/local.conf qui ajoute les parties manquantes du fichier unité:

[Service]
Environment="FOO=bar baz"

Systemd fusionne ensuite les deux fichiers lors du démarrage du service (n'oubliez pas de systemctl daemon-reload après avoir changé l’un d’eux). Et puisque ce chemin est utilisé directement par systemd, vous n’utilisez pas EnvironmentFile= pour ça.

Si la valeur n'est supposée être modifiée que sur certains des systèmes affectés, vous pouvez combiner les deux solutions, en fournissant une valeur par défaut directement dans l'unité et une substitution locale dans l'autre fichier.


66
2018-04-23 07:48



systemctl daemon-reload est la commande pour recharger systemd - Dmitry Buzolin
EnvironmentFile= C'est mieux quand les valeurs sont des secrets comme les mots de passe. Voir ma réponse pour plus de détails. - Don Kirkby


http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= - vous avez deux options (une déjà indiquée par Michael):

Environment=

et

EnvironmentFile=

34
2017-10-16 13:55





Michael a donné une solution propre mais je voulais obtenir une variable env mise à jour à partir d'un script. Malheureusement, l’exécution de commandes bash n’est pas possible dans le fichier d’unité systemd. Heureusement, vous pouvez déclencher bash dans ExecStart:

http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=systemd.service&ampsect=5

Notez que ce paramètre ne prend pas directement en charge les lignes de commande shell. Si des lignes de commande shell doivent être utilisées, elles doivent être explicitement passées à une implémentation shell quelconque.

Exemple dans notre cas est alors:

[Service]
ExecStart=/bin/bash -c "ENV=`script`; /bin/myforegroundcmd"

6
2017-07-23 13:31



Cela ne fonctionnera pas pour plusieurs raisons (à moins que ce soit un service "one-shot", ce qui est plutôt inutile). J'ai réussi à faire fonctionner ce qui suit: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. le -a garantit que l'environnement est exporté vers le sous-processus (à moins que vous ne préfixiez toutes les variables de whatever avec export ) - Otheus
pourquoi ça ne marche pas? Cela devrait toujours déclencher toute la commande qui inclut l'exécution du script, n'est-ce pas? - user1830432
Peut être ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd est un peu meilleure solution dans ce cas. - kstep
@Otheus: Excellente réponse, enregistrée le jour où j'ai dû créer un fichier Tomcat 8 Unit. - Daniel
Il existe un moyen d'exécuter une commande bash "dans" un fichier de service systemd. Voir ce lien: coreos.com/os/docs/latest/… - Mark Lakata


Les réponses par Michael et Michał sont utiles et répondent à la question initiale de savoir comment définir une variable d'environnement pour un service systemd. Cependant, un usage commun Par exemple, les variables d’environnement consistent à configurer des données sensibles telles que des mots de passe dans un endroit qui ne sera pas accidentellement engagé dans le contrôle de source avec le code de votre application.

Si c'est la raison pour laquelle vous souhaitez transmettre une variable d'environnement à votre service, ne pas utilisation Environment= dans le fichier de configuration de l'unité. Utilisation EnvironmentFile= et pointez-le vers un autre fichier de configuration qui est uniquement lisible par le compte de service (et les utilisateurs ayant un accès root).

Les détails du fichier de configuration de l'unité sont visibles par tout utilisateur à l'aide de cette commande:

systemctl show my_service

Je mets un fichier de configuration à /etc/my_service/my_service.conf et mettre mes secrets là-dedans:

MY_SECRET=correcthorsebatterystaple

Puis dans mon fichier d'unité de service, j'ai utilisé EnvironmentFile=:

[Unit]
Description=my_service

[Service]
ExecStart=/usr/bin/python /path/to/my_service.py
EnvironmentFile=/etc/my_service/my_service.conf
User=myservice

[Install]
WantedBy=multi-user.target

J'ai vérifié ça ps auxe ne peut pas voir ces variables d'environnement, et les autres utilisateurs n'ont pas accès à /proc/*/environ. Vérifiez sur votre propre système, bien sûr.


6
2018-05-04 00:29