Передача нескольких параметров в 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