Вопрос: Как установить переменную среды в службе systemd?


у меня есть Система Arch Linux с systemd и я создал свой собственный сервис. Служба конфигурации на /etc/systemd/system/myservice.service выглядит так:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Теперь я хочу иметь переменную окружения, установленную для /bin/myforegroundcmd, Как мне это сделать?


109
2017-08-01 19:43


Источник




Ответы:


Времена меняются, поэтому лучшие практики.

текущий лучший способ сделать это - запустить systemctl edit myservice, который создаст для вас файл переопределения или позволит вам отредактировать существующий.

В обычных установках это создаст каталог /etc/systemd/system/myservice.service.d, и внутри этого каталога создайте файл, имя которого заканчивается на .conf (Как правило, override.conf), и в этом файле вы можете добавить или переопределить любую часть устройства, отправленного дистрибутивом.

Например, в файле /etc/systemd/system/myservice.service.d/myenv.conf:

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

Также обратите внимание, что если каталог существует и пуст, ваша служба будет отключена! Если вы не собираетесь вставлять что-то в каталог, убедитесь, что он не существует.


Для справки, старый способ был:

Рекомендуемый способ для этого нужно создать файл /etc/sysconfig/myservice который содержит ваши переменные, а затем загружать их EnvironmentFile,

Для получения полной информации см. Документацию Fedora по как написать сценарий systemd,


129
2017-08-01 20:07



Я думаю, что sysconfig путь специфичен для Fedora, но вопрос о Arch Linux. Ответ paluh интереснее, я думаю - Ludovic Kuty
/etc/sysconfig специфичен для Fedora. AFAIR Arch Linux настаивала на том, что файлы конфигурации где-то специфичны для пакета, а /etc а не на конкретное место в Fedora. подобно /etc/myservice.conf, хотя использование дополнительного файла здесь не кажется правильным. - Michał Górny
Нет нет нет. / etc / sysconfig не рекомендуется. Это обескураживается вместе с / etc / default / * из debian, потому что они бессмысленны, а имена бессмысленны и имеют смысл только для соображений обратной совместимости (все / etc - это конфигурация системы, а не только / etc / sysconfig и / etc / defaults для переопределений, а не значений по умолчанию). Просто поместите определения непосредственно в файл блока или, если это невозможно, в файл окружения, в котором есть определенное местоположение пакета (например, комментарий Михала). - zbyszek
@FrederickNord Это просто переменные = пары значений, такие как DJANGO_SETTINGS_MODULE=project.settings, по одной на линию. - Michael Hampton♦
@MichaelHampton Не могли бы вы добавить ссылку на документацию для «текущего наилучшего способа»? - jb.


Ответ зависит от того, должна ли переменная быть постоянной (т. Е. Не должна быть изменена пользователем, получающей устройство) или переменной (которая должна быть установлена ​​пользователем).

Поскольку это ваша локальная единица, граница довольно размыта и в любом случае будет работать. Однако, если вы начали распространять его, и это закончится тем, что /usr/lib/systemd/system, это станет важным.

Постоянное значение

Если значение не нужно изменять для каждого экземпляра, предпочтительным способом было бы разместить его как Environment=, непосредственно в файле устройства:

[Unit]
Description=My Daemon

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

[Install]
WantedBy=multi-user.target

Преимущество состоит в том, что переменная хранится в одном файле с устройством. Таким образом, единичный файл легче перемещается между системами.

Значение переменной

Однако вышеприведенное решение не работает хорошо, когда sysadmin должен изменить локальное значение переменной среды. Более конкретно, новое значение нужно будет устанавливать каждый раз, когда обновляется файл блока.

Для этого случая необходимо использовать дополнительный файл. Как обычно зависит от политики распределения.

Одним из особенно интересных решений является использование /etc/systemd/system/myservice.service.d каталог. В отличие от других решений, этот каталог поддерживается самой системой и поэтому не имеет путей распространения.

В этом случае вы помещаете файл как /etc/systemd/system/myservice.service.d/local.conf который добавляет недостающие части файла блока:

[Service]
Environment="FOO=bar baz"

Впоследствии systemd объединяет два файла при запуске службы (не забудьте systemd daemon-reload после изменения любого из них). И так как этот путь используется напрямую systemd, вы не используете EnvironmentFile= для этого.

Если значение должно быть изменено только в некоторых затронутых системах, вы можете объединить оба решения, предоставляя по умолчанию непосредственно в устройстве и локальное переопределение в другом файле.


64
2018-04-23 07:48



systemctl daemon-reload это команда перезагрузить systemd - Dmitry Buzolin
EnvironmentFile= лучше, когда значения являются секретами, такими как пароли. Видеть мой ответ для деталей. - Don Kirkby


http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= - у вас есть два варианта (один уже указал Майкл):

Environment=

а также

EnvironmentFile=

32
2017-10-16 13:55





Майкл дал одно чистое решение, но я хотел получить обновленную переменную env из сценария. К сожалению, выполнение команд bash невозможно в файле systemd. К счастью, вы можете вызвать bash внутри ExecStart:

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

Обратите внимание, что этот параметр напрямую не поддерживает командные строки оболочки. Если командные строки оболочки должны использоваться, они должны быть явно переданы в реализацию какой-либо оболочки.

Пример в нашем случае:

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

5
2017-07-23 13:31



Это не будет работать по нескольким причинам (если это не «одноразовый» сервис, что довольно бессмысленно). Мне удалось заставить работать: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program', -a обеспечивает экспорт окружающей среды в подпроцесс (если вы не хотите префикс всех переменных в whatever с export ) - Otheus
почему это не сработает? Он должен всегда запускать целую команду, которая включает выполнение скрипта, не так ли? - user1830432
Может быть ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd это немного лучшее решение в этом случае. - kstep
@Otheus: Отличный ответ, спасенный днем, когда мне пришлось создать файл Tomcat 8 Unit. - Daniel
Есть способ выполнить команду bash «в» системном файле systemd. См. Эту ссылку: coreos.com/os/docs/latest/... - Mark Lakata


Ответы Майкл а также Михал полезны и отвечают на исходный вопрос о том, как установить переменную среды для службы systemd. Однако один общего пользования для переменных окружения необходимо настроить конфиденциальные данные, такие как пароли, в месте, которое случайно не будет передано в исходное состояние с кодом вашего приложения.

Если вы хотите передать переменную окружения в свою службу, не использование Environment= в файле конфигурации устройства. использование EnvironmentFile= и укажите его в другой файл конфигурации, который доступен только для учетной записи службы (и для пользователей с правами root).

Детали файла конфигурации устройства видны любому пользователю с помощью этой команды:

systemctl show my_service

Я поместил файл конфигурации в /etc/my_service/my_service.conf и поставил там свои секреты:

MY_SECRET=correcthorsebatterystaple

Затем в моем файле служебной единицы я использовал 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

Я проверил, что ps auxe не могут видеть эти переменные среды, а другие пользователи не имеют доступа к /proc/*/environ, Конечно, проверьте свою систему.


5
2018-05-04 00:29