Pregunta ¿Cómo configurar la variable de entorno en el servicio systemd?


Yo tengo un Arch Linux system con systemd Y he creado mi propio servicio. El servicio de configuración en /etc/systemd/system/myservice.service Se ve como esto:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Ahora quiero tener un conjunto de variables de entorno para el /bin/myforegroundcmd. ¿Cómo puedo hacer eso?


119
2017-08-01 19:43


origen




Respuestas:


Los tiempos cambian y también las mejores prácticas.

los corriente La mejor manera de hacer esto es correr. systemctl edit myservice, que creará un archivo de reemplazo para usted o le permitirá editar uno existente.

En instalaciones normales esto creará un directorio. /etc/systemd/system/myservice.service.d, y dentro de ese directorio crea un archivo cuyo nombre termina en .conf (típicamente, override.conf), y en este archivo puede agregar o anular cualquier parte de la unidad enviada por la distribución.

Por ejemplo, en un archivo. /etc/systemd/system/myservice.service.d/myenv.conf:

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

También tenga en cuenta que si el directorio existe y está vacío, su servicio se desactivará. Si no tiene intención de poner algo en el directorio, asegúrese de que no exista.


Para referencia, la forma antigua era:

La forma recomendada hacer esto es crear un archivo /etc/sysconfig/myservice que contiene tus variables, y luego cargarlas con EnvironmentFile.

Para detalles completos, vea la documentación de Fedora en cómo escribir un script systemd.


143
2017-08-01 20:07



Supongo que el sysconfig La ruta es específica para Fedora, pero la pregunta es sobre Arch Linux. La respuesta de paluh es más interesante, creo. - Ludovic Kuty
/etc/sysconfig es específico de fedora AFAIR Arch Linux estaba presionando para tener los archivos de configuración en algún lugar específicos del paquete en lugar de /etc en lugar de esa ubicación específica de Fedora. Me gusta /etc/myservice.conf, aunque usar un archivo extra no parece el camino correcto aquí. - Michał Górny
No no no. / etc / sysconfig no se recomienda. Se desaconseja, junto con / etc / default / * de debian, porque no tienen sentido, y los nombres no tienen sentido y tienen sentido solo por razones de compatibilidad con versiones anteriores (todo / etc es sobre la configuración del sistema, no solo / etc / sysconfig, y / etc / defaults es para reemplazos, no para los predeterminados). Simplemente coloque las definiciones directamente en el archivo de la unidad, o si no es posible, en un archivo de entorno que tenga una ubicación específica del paquete (como sugiere el comentario de Michał). - zbyszek
@FrederickNord Es solo una variable = pares de valores, como por ejemplo DJANGO_SETTINGS_MODULE=project.settings, una por línea. - Michael Hampton♦
@MichaelHampton ¿Podría agregar el enlace de documentación para "la mejor manera actual"? - jb.


La respuesta depende de si se supone que la variable es constante (es decir, no debe ser modificada por el usuario que obtiene la unidad) o variable (se supone que debe ser establecida por el usuario).

Ya que es su unidad local, el límite es bastante borroso y de cualquier manera funcionaría. Sin embargo, si empezaste a distribuirlo y terminaría en /usr/lib/systemd/system, esto se volvería importante.

Valor constante

Si el valor no necesita cambiarse por instancia, la forma preferida sería colocarlo como Environment=, directamente en el archivo de la unidad:

[Unit]
Description=My Daemon

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

[Install]
WantedBy=multi-user.target

La ventaja de esto es que la variable se mantiene en un solo archivo con la unidad. Por lo tanto, el archivo de la unidad es más fácil de mover entre sistemas.

Valor variable

Sin embargo, la solución anterior no funciona bien cuando se supone que sysadmin cambia el valor de la variable de entorno localmente. Más específicamente, el nuevo valor debería establecerse cada vez que se actualice el archivo de la unidad.

Para este caso, se utilizará un archivo extra. Cómo - por lo general depende de la política de distribución.

Una solución particularmente interesante es usar /etc/systemd/system/myservice.service.d directorio. A diferencia de otras soluciones, este directorio es compatible con systemd y, por lo tanto, no tiene rutas de distribución específicas.

En este caso, colocas un archivo como /etc/systemd/system/myservice.service.d/local.conf que agrega las partes faltantes del archivo de unidad:

[Service]
Environment="FOO=bar baz"

Luego, systemd fusiona los dos archivos al iniciar el servicio (recuerde systemctl daemon-reload después de cambiar cualquiera de ellos). Y ya que esta ruta es utilizada directamente por systemd, usted no usa EnvironmentFile= para esto.

Si se supone que el valor solo se modificará en algunos de los sistemas afectados, puede combinar ambas soluciones, proporcionando un valor predeterminado directamente en la unidad y una anulación local en el otro archivo.


66
2018-04-23 07:48



systemctl daemon-reload es el comando para recargar systemd - Dmitry Buzolin
EnvironmentFile= Es mejor cuando los valores son secretos como las contraseñas. Ver mi respuesta para detalles. - Don Kirkby


http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= - Tienes dos opciones (una ya señalada por Michael):

Environment=

y

EnvironmentFile=

34
2017-10-16 13:55





Michael dio una solución limpia, pero quería actualizar la variable env desde el script. Desafortunadamente, ejecutar comandos bash no es posible en el archivo de unidad systemd. Afortunadamente, puedes disparar bash dentro de ExecStart:

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

Tenga en cuenta que esta configuración no admite directamente las líneas de comando de shell. Si se van a usar líneas de comando de shell, deben pasarse explícitamente a una implementación de shell de algún tipo.

Ejemplo en nuestro caso es entonces:

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

6
2017-07-23 13:31



Esto no funcionará por varias razones (a menos que sea un servicio "de un solo disparo", que es bastante inútil). Logré que funcionara lo siguiente: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. los -a garantiza que el entorno se exporte al subproceso (a menos que desee prefijar todas las variables en whatever con export ) - Otheus
¿Por qué no funciona? Siempre debe activar un comando completo que incluya la ejecución del script, ¿no es así? - user1830432
Tal vez ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd Es una solución un poco mejor en este caso. - kstep
@Otheus: Gran respuesta, guardada por día cuando tuve que crear un archivo de Tomcat 8 Unit. - Daniel
Existe una forma de ejecutar un comando de bash "en" un archivo de servicio systemd. Vea este enlace: coreos.com/os/docs/latest/… - Mark Lakata


Las respuestas por Miguel y Michał son útiles y responden a la pregunta original de cómo configurar una variable de entorno para un servicio de systemd. Sin embargo, uno uso común para las variables de entorno es configurar datos confidenciales como contraseñas en un lugar que no se comprometa accidentalmente con el control de fuente con el código de su aplicación.

Si es por eso que quiere pasar una variable de entorno a su servicio, no haga utilizar Environment= en el archivo de configuración de la unidad. Utilizar EnvironmentFile= y apúntelo a otro archivo de configuración que solo sea legible por la cuenta de servicio (y los usuarios con acceso root).

Los detalles del archivo de configuración de la unidad son visibles para cualquier usuario con este comando:

systemctl show my_service

Pongo un archivo de configuración en /etc/my_service/my_service.conf y poner mis secretos allí

MY_SECRET=correcthorsebatterystaple

Luego en mi archivo de unidad de servicio, utilicé 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

Revisé eso ps auxe no puedo ver esas variables de entorno, y otros usuarios no tienen acceso a /proc/*/environ. Comprueba tu propio sistema, por supuesto.


6
2018-05-04 00:29