Tengo un systemd
servicio ejecutándose bajo un usuario específico.
Supuse erróneamente que el servicio tendría acceso a las variables de entorno que todos los usuarios heredan de los scripts/exportaciones en/etc/profile.d
¿Hay alguna manera de lograr esto sin tener que copiar manualmente las variables en systemd
la definición del archivo unitario?
Por ejemplo, tengo lo siguiente
$ cat /etc/profile.d/somexports
export VAR1=VALUE1
export VAR2=VALUE2
¿Se puede pasar/exportar esto a un systemd
servicio?
Respuesta1
Hay algunas posibles fuentes de medio ambiente:
- Usando
Environment=
el cual te permite establecer variables - Usar
EnvironmentFile=
el cual te permite cargar valores desde un archivo - Su uso
PassEnvironment=
le permite definir variables que deben pasarse desde PID1. - Configuración estática (p. ej
$USER
.)
Puede parecer que EnvironmentFile=/etc/profile.d/someexports
es lo que quieres, pero no es así. /etc/profile.d/*
a menudo proviene de su shell y puede ser analizado por su shell. systemd
es independiente del shell y, por lo tanto, no dependerá de la sintaxis de bash. Debe EnvironmentFile
contener asignaciones de variables separadas por nuevas líneas, lo cual es mucho más estricto.
systemd
El diseño desalienta el cambio dinámico de unidades o sus entornos. Incluso la opción se añadió sólo como resultado de la presión y luego los desarrolladores EnvironmentFile=
la consideraron un error . systemd
Un ejemplo de este diseño es que $PATH
no afecta qué binarios se utilizan. Esto hace que las cosas sean más deterministas, ya que cuando defines una unidad, estás definiendo todo acerca de cómo debe funcionar esa unidad sin preocuparte por la influencia externa.
La respuesta corta es: No. No puedes cargar /etc/profile.d/*
y systemd
eso es intencional.
Pero la respuesta que probablemente quieras es: sí, puedes cargarlo. Sólo necesita ejecutar su aplicación a través de un shell.
Puedes hacerlo cambiando:
ExecStart=/usr/bin/myservice
A
ExecStart=/usr/bin/bash -lc myservice
Eso hará bash
que sea el proceso padre, el que carga /etc/profile.d/
y reenvía ese entorno a su hijo. También tenga en cuenta que no especificé una ruta absoluta completa a myservice
. En este caso, myservice
se basará en $PATH
y eso puede ser o no /usr/bin/myservice
. Puede ver cómo esto puede hacer que las cosas sean más difíciles de solucionar y esa es la desventaja de seguir este camino.
Respuesta2
Creo que esto se aborda de la siguiente manera.
ExecStart=/bin/sh -lc /path/to/binary
La -l
bandera convierte la invocación del shell en un shell de inicio de sesión. Necesitamos esto porque solo los shells de inicio de sesión generan scripts de perfil.
$ bash --help | grep -- -l
GNU bash, version 4.4.12(1)-release-(x86_64-pc-linux-gnu)
--login