Кавычки в ExecStart= разбираются не так, как ожидается
systemd разбирает строку запуска по своим правилам: кавычки снимаются, пробелы делят аргументы. Запись, скопированная из терминала, часто даёт программе не те аргументы — и она либо падает, либо работает не так.
Что это значит
Проверять надо не файл, а результат разбора: systemctl show -p ExecStart печатает аргументы по отдельности. Если аргумент разъехался на два или содержит лишние кавычки, это видно сразу.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Кавычки вокруг всего значения параметра
Запись
ExecStart="/usr/bin/app --opt a b"даёт один аргумент — путь с пробелами внутри. Программа не запустится. -
Одинарные кавычки внутри двойных или наоборот
Правила systemd отличаются от правил оболочки. Вложенные кавычки разбираются иначе, чем ожидает человек.
-
Обратная косая для переноса строки не там, где нужно
Перенос допустим, но обратная косая должна быть последним символом строки. Пробел после неё ломает разбор.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Разобранная команда: аргументы видны по отдельности.
systemctl show myapp.service -p ExecStartОшибки разбора строки запуска.
systemd-analyze verify /etc/systemd/system/myapp.serviceЧто сказала программа о полученных аргументах.
journalctl -u myapp.service -n 20 --no-pagerРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Запись
ExecStart="/usr/bin/app --opt a b"даёт один аргумент — путь с пробелами внутри. Программа не запустится.
- Как проверить
-
Посмотрите разобранные аргументы.
systemctl show myapp.service -p ExecStart
- Как исправить
-
Кавычки нужны только вокруг отдельных аргументов с пробелами, а не вокруг всей команды.
ExecStart=/usr/bin/app --opt "a b"
- Почему происходит
- Правила systemd отличаются от правил оболочки. Вложенные кавычки разбираются иначе, чем ожидает человек.
- Как проверить
-
Сравните написанное и разобранное.
systemctl cat myapp.service | grep ExecStart systemctl show myapp.service -p ExecStart
- Как исправить
- Избегайте вложенных кавычек: если аргумент сложный, вынесите его в файл окружения или в скрипт.
- Почему происходит
- Перенос допустим, но обратная косая должна быть последним символом строки. Пробел после неё ломает разбор.
- Как проверить
-
Посмотрите невидимые символы в конце строк.
grep -n "\\\\ *$" /etc/systemd/system/myapp.service | cat -A | head
- Как исправить
- Уберите пробелы после обратной косой. Проверка unit-файла на этом сайте такие строки отмечает.
Пример вывода
Кавычки вокруг всей команды. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
$ systemctl cat myapp.service | grep ExecStart
ExecStart="/usr/local/bin/myapp --listen 127.0.0.1:8080"
$ systemctl show myapp.service -p ExecStart
ExecStart={ path=/usr/local/bin/myapp --listen 127.0.0.1:8080 ; argv[]=... }
systemd[4100]: myapp.service: Failed at step EXEC spawning /usr/local/bin/myapp --listen 127.0.0.1:8080: No such file or directory
Связанные ошибки
- status=203/EXEC в systemd Код 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
- status=2/INVALIDARGUMENT в systemd Код 2/INVALIDARGUMENT: программа сочла аргументы или настройки недопустимыми. Частая причина — лишние кавычки в ExecStart=.
- Unit file is bad и ошибки разбора unit-файла systemd не может разобрать unit-файл: неизвестные параметры, ошибки в секциях, недопустимые значения. Как найти проблемную строку.
- Apache: Invalid command — не включён модуль Apache не запускается: директива требует модуль, который не подключён. Как найти нужный модуль и включить.
- Apache: правила .htaccess не действуют Файл .htaccess игнорируется: запрещён параметром AllowOverride, нет нужного модуля, файл не читается.
- Configuration file is marked world-inaccessible Предупреждение о правах на unit-файл: служба работает, но файл недоступен для чтения другим.
- Docker: unable to configure the Docker daemon with file daemon.json Демон Docker не запускается из-за ошибки в /etc/docker/daemon.json: неверный JSON или неизвестный ключ.
- Docker: unable to configure the Docker daemon — конфликт -H и hosts Адрес прослушивания задан дважды: ключом -H в unit-файле и параметром hosts в daemon.json. Демон отказывается стартовать.
Источники
-
systemd.service(5)
Правила разбора командной строки и кавычек. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено кавычками вокруг всей команды запуска.