407 votes

Comment définir une 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 à /etc/systemd/system/myservice.service ressemble à ça :

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Maintenant, je veux qu'une variable d'environnement soit définie pour l'adresse de l'utilisateur. /bin/myforegroundcmd . Comment je fais ça ?

535voto

Michael Hampton Points 232226

Les temps changent et les meilleures pratiques aussi.

Le site actuel Le meilleur moyen de le faire est de lancer systemctl edit myservice qui créera un fichier de remplacement pour vous ou vous permettra de modifier un fichier existant.

Dans les installations normales, cela créera un répertoire /etc/systemd/system/myservice.service.d et 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é fournie 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 méthode était :

La méthode recommandée pour faire cela est de créer un fichier /etc/sysconfig/myservice qui contient vos variables, et ensuite les charger avec EnvironmentFile .

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

141voto

Michał Górny Points 1370

La réponse dépend du fait que la variable est censée être constante (c'est-à-dire qu'elle n'est pas censée être modifiée par l'utilisateur qui obtient l'unité) ou variable (censée être définie par l'utilisateur).

Étant donné qu'il s'agit de votre unité locale, la frontière est assez floue et l'une ou l'autre solution pourrait fonctionner. Cependant, si vous commenciez à le distribuer et qu'il finissait en /usr/lib/systemd/system cela deviendrait important.

Valeur constante

Si la valeur n'a pas besoin de changer par instance, il est préférable de la placer en tant que Environment= directement dans le fichier de l'unité :

[Unit]
Description=My Daemon

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

[Install]
WantedBy=multi-user.target

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

Valeur de la variable

Cependant, la solution ci-dessus ne fonctionne pas bien lorsque l'administrateur système est censé modifier la valeur de la variable d'environnement localement. Plus précisément, la nouvelle valeur devrait être définie à chaque fois que le fichier d'unité est mis à jour.

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

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

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

[Service]
Environment="FOO=bar baz"

Ensuite, systemd fusionne les deux fichiers lors du démarrage du service (rappelez-vous de systemctl daemon-reload après avoir changé l'un ou l'autre). Et puisque ce chemin est utilisé directement par systemd, vous ne devez pas utiliser EnvironmentFile= pour ça.

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

82voto

Quibblesome Points 14441

Les réponses de Michael y Micha sont utiles et répondent à la question initiale de savoir comment définir une variable d'environnement pour un service systemd. Cependant, une utilisation commune pour les variables d'environnement est de configurer des données sensibles comme les mots de passe à un endroit qui ne sera pas accidentellement transmis au contrôle de la source avec le code de votre application.

Si c'est la raison pour laquelle vous voulez passer une variable d'environnement à votre service, ne pas utiliser Environment= dans le fichier de configuration de l'unité. Utilisez EnvironmentFile= et le faire pointer vers un autre fichier de configuration qui n'est lisible que 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 pour tout utilisateur avec cette commande :

systemctl show my_service

J'ai placé un fichier de configuration à /etc/my_service/my_service.conf et mettre mes secrets là-dedans :

MY_SECRET=correcthorsebatterystaple

Ensuite, 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é que 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.

64voto

paluh Points 631

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

Environment=

et

EnvironmentFile=

11voto

user1830432 Points 243

Michael a donné une solution propre mais je voulais obtenir la variable env mise à jour à partir de script. Malheureusement, l'exécution de commandes bash n'est pas possible dans le fichier d'unité systemd. Heureusement, vous pouvez déclencher bash à l'intérieur de 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 les lignes de commande Shell doivent être utilisées, elles doivent être passées explicitement à une implémentation Shell de quelque sorte.

L'exemple dans notre cas est alors :

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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X