Java-служба не запускается: не найдена среда исполнения
Классическая ошибка для служб на JVM: в команде запуска указано имя java без пути, либо путь ведёт на удалённую при обновлении версию. systemd не ищет программу в PATH, и запуск завершается сразу.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Имя java без полного пути
systemd не использует PATH при запуске. Имя команды для него — несуществующий путь.
-
Среда исполнения удалена или обновлена
После обновления пакета каталог версии меняется. Жёстко прописанный путь перестаёт существовать.
-
Переменная с каталогом среды исполнения не передана
Часть приложений требует переменную с путём к среде исполнения. В профиле она есть, у службы — нет.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Команда запуска и окружение.
systemctl cat myapp.service | grep -E "^Exec|^Environment"Фактический путь к среде исполнения.
readlink -f "$(command -v java)"Шаг и причина отказа запуска.
journalctl -xeu myapp.service -n 20 --no-pagerРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- systemd не использует PATH при запуске. Имя команды для него — несуществующий путь.
- Как проверить
-
Посмотрите команду запуска и настоящий путь.
systemctl cat myapp.service | grep ExecStart command -v java; readlink -f "$(command -v java)"
- Как исправить
- Укажите полный путь к java. Ссылки, ведущие на текущую версию, надёжнее конкретного каталога: они переживают обновления.
- Почему происходит
- После обновления пакета каталог версии меняется. Жёстко прописанный путь перестаёт существовать.
- Как проверить
-
Проверьте путь из команды запуска.
ls -l /usr/lib/jvm/ 2>/dev/null | head
- Как исправить
- Используйте ссылку на текущую версию или задавайте путь через переменную окружения в файле окружения.
- Почему происходит
- Часть приложений требует переменную с путём к среде исполнения. В профиле она есть, у службы — нет.
- Как проверить
-
Посмотрите окружение службы.
systemctl show myapp.service -p Environment | tr " " "\n" | grep -i java
- Как исправить
- Задайте переменную в unit-файле или в файле окружения: служба не читает профиль оболочки.
Пример вывода
В команде запуска имя без пути. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
× myapp.service - Java application
Process: 4100 ExecStart=java -jar /opt/myapp/app.jar (code=exited, status=203/EXEC)
systemd[4100]: myapp.service: Failed at step EXEC spawning java: No such file or directory
Связанные ошибки
- status=203/EXEC в systemd Код 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
- status=127 в systemd: команда не найдена Код 127 без имени: оболочка не нашла команду. Появляется, когда ExecStart запускает скрипт или sh -c, а внутри команды нет.
- Переменная в unit-файле не разворачивается Запись со знаком доллара попадает в аргументы буквально. Где подстановка работает, а где нет.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Exec format error при запуске службы Ошибка формата исполняемого файла: не та архитектура, нет строки #!, повреждённый файл или попытка запустить не программу.
- Java-служба: OutOfMemoryError и куча Служба на JVM падает с нехваткой памяти: размер кучи, предел контрольной группы, дампы кучи.
- Job for … failed because a timeout was exceeded Задание на запуск прервано по таймауту. Как отличить медленный старт от заблокированного и правильно настроить TimeoutStartSec.
- Python-служба: ModuleNotFoundError при запуске Служба не находит модули: другое виртуальное окружение, неверный интерпретатор, отсутствующие зависимости.
Источники
-
systemd.service(5)
Требование абсолютного пути в Exec*=. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено командой запуска без полного пути к java.