Передача нескольких параметров в systemd service

Почему systemctl не поддерживает передачу параметров напрямую

Передача параметров в systemd.

Команда sudo systemctl start myapp.service -- parameter1 parameter2

не поддерживается напрямую в systemd, так как система управления сервисами systemd ожидает фиксированные команды и параметры, заранее заданные в файле юнита.

Методы обхода для передачи параметров

Метод 1: Использование скрипта-обёртки

Этот метод заключается в создании скрипта, который принимает параметры и передаёт их приложению:

#!/bin/bash
/usr/local/bin/my_app "$@"

Затем создаётся юнит-файл со следующим содержимым:

[Unit]
Description=Пример сервиса со скриптом-обёрткой

[Service]
ExecStart=/usr/local/bin/myapp_wrapper.sh
Restart=always

Теперь сервис можно запускать с параметрами:

sudo systemctl start myapp.service -- parameter1 parameter2

Метод 2: Использование окружения

Параметры можно передавать через переменные среды:

sudo PARAMS="parameter1 parameter2" systemctl start myapp.service

Юнит-файл при этом должен быть настроен следующим образом:

[Unit]
Description=Пример сервиса с параметрами из среды

[Service]
ExecStart=/usr/local/bin/my_app $PARAMS
Environment=PARAMS=""
Restart=always

Метод 3: Использование шаблонных юнитов

Шаблонные юниты позволяют передавать параметры через имя сервиса:

[Unit]
Description=Пример шаблонного сервиса

[Service]
ExecStart=/usr/local/bin/my_app %I
Restart=always

Сервис запускается с параметрами следующим образом:

sudo systemctl start myapp@"param1 param2".service

Здесь %I подставляет строку после символа @ в команду ExecStart.

Метод 4: Использование Override юнита

Если нужно временно изменить параметры запуска, можно использовать команду systemctl edit:

Выполните команду:

sudo systemctl edit myapp.service

В открывшемся редакторе добавьте временный ExecStart с параметрами:

[Service]
ExecStart=/usr/local/bin/my_app parameter1 parameter2

Сохраните изменения и запустите сервис:

sudo systemctl start myapp.service

После завершения работы удалите временные изменения:

sudo systemctl revert myapp.service

Выберите подходящий метод в зависимости от требований вашего приложения и используемой среды. Шаблонные юниты удобны для типовых сценариев, а скрипт-обёртка и метод Override дают больше гибкости для временных настроек.

Передача параметров в systemd

Проектировщики явно отошли от классических параметров в командной строке. Впрочем ясно почему. Systemd service выполняется в отдельном окружении и соответственно передача параметров классическим образом выглядит как-то некорректно.

В systemd параметры командной строки передаются сервису не так, как в классическом shell-скрипте. Это связано с тем, что ExecStart в .service-файлах не использует оболочку (sh или bash) для интерпретации команд, а выполняет исполняемый файл напрямую.

Основные причины, почему параметры могут не передаваться:
1. Отсутствие кавычек при сложных аргументах
Если аргументы содержат пробелы или специальные символы, их нужно либо экранировать, либо заключать в кавычки.
Пример ошибки:

ExecStart=/usr/bin/myapp --option value

В этом случае systemd считает value отдельным аргументом.


Правильный вариант:

ExecStart=myapp --config /etc/myapp.conf

2. Отсутствие полного пути к исполняемому файлу


systemd требует явного указания полного пути к бинарному файлу.


Неправильно:

ExecStart=myapp --config /etc/myapp.conf

Правильно:

ExecStart=/usr/bin/myapp --config /etc/myapp.conf

3. Использование оболочечных конструкций (|, &&, ;, $())
systemd не использует оболочку для исполнения команд.
Неправильно:

ExecStart=/usr/bin/myapp $(date +%Y-%m-%d)

Правильно (если нужен shell):

ExecStart=/bin/sh -c "/usr/bin/myapp $(date +%Y-%m-%d)"

4.Некорректное использование кавычек


systemd не обрабатывает кавычки так, как оболочка. Иногда необходимо экранировать аргументы:

ExecStart=/usr/bin/myapp "--name=Test Service"

5. Передача переменных окружения
Если скрипт использует переменные окружения, они должны быть определены в секции [Service]:

[Service]
Environment="MY_VAR=value"
ExecStart=/usr/bin/myapp --config "$MY_VAR"

Если параметры командной строки не передаются, проверьте журнал с помощью:

journalctl -u myservice --no-pager -n 50

Или проверьте, как systemd интерпретирует команду:

systemctl show myservice | grep ExecStart