Почему в юнитах не работает Environment?

Сразу пример:

[Service]
Environment="FOO=bar"
ExecStart=/bin/bash /usr/local/sbin/bashdays.sh

Сделал юнит, но в скрипт bashdays.sh не передаётся переменная FOO. Хотя логически всё правильно.

Тут снова приколы.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Сам /bin/bash переменную не теряет: окружение из Environment= получает процесс из ExecStart, а затем его наследуют дочерние процессы. Если FOO не видно в скрипте, причина находится в другом месте.

Для начала проверяем сам скрипт: не очищает ли он окружение через env -i, не запускает ли следующую команду через sudo или su, не переопределяет ли либо не удаляет переменную. Ещё одна частая причина — юнит изменили, но не выполнили systemctl daemon-reload, либо проверяют другой экземпляр сервиса.

Оба варианта ExecStart сохраняют переменную:

[Service]
Environment="FOO=bar"
ExecStart=/bin/bash /usr/local/sbin/bashdays.sh
[Service]
Environment="FOO=bar"
ExecStart=/usr/local/sbin/bashdays.sh

А сам скрипт может выглядеть так:

#!/bin/bash

echo "FOO is $FOO"

В обоих случаях он должен вывести FOO is bar.

Использовать EnvironmentFile=

Если у тебя дохуя переменных, то выносим их в отдельный файл, например сюда /etc/bashdays-service.env.

FOO=bar
BAZ=qux

А в самом юните прописываем:

[Service]
EnvironmentFile=/etc/bashdays-service.env
ExecStart=/usr/local/sbin/bashdays.sh

Всё! Теперь переменные считываются из файла и скрипт их видит.

Передавать переменные прямо в ExecStart

[Service]
ExecStart=/bin/bash -c 'FOO=bar exec /usr/local/sbin/bashdays.sh'

Тут особо и комментировать нечего, всё очевидно.

Как отладить и задебажить?

А вот так:

systemctl show nginx

Вместо nginx подставляешь свой сервис и наблюдаешь все переменные, которые передались. В наших примерах увидишь Environment=FOO=bar.

Справедливо не только для собственных юнитов, но и для других, например для того же nginx или docker.

Как вариант, можешь добавить в скрипт такую хуйню:

env > /tmp/env.log

И смотришь, какие переменные реально передаются в твой скрипт.

Ещё одна база выдана: вроде очевидные вещи, но так глубоко в это никто не лезет. Пользуйся.