LINUX.ORG.RU
решено ФорумAdmin

systemd service файл для запуска java процесса ч.7685796

 , ,


1

2

Всем привет, такая проблема: нужно написать юнит-файл для приложения на java.

Он должен падать с ошибкой, если приложение не запустилось. Он должен рестартовать приложение если оно упало. Мой вариант:

[Unit]
Description=some backend service
After=network.target
Wants=nginx.service
[Service]
Type=forking #если сделать type=simple, то юнит не падает с ошибкой, если на старте что-то пошло не так.
User=ec2-user
PIDFile=/opt/some_shit/RUNNING_PID
EnvironmentFile=/etc/default/some_shit_config
#TimeoutStartSec=0
ExecStart=/opt/some_shit/bin/some_shit
Restart=on-failure
SuccessExitStatus=143 # без этой строчки оно думает, что приложение не запустилось, даже если оно запустилось и работает норально
[Install]
WantedBy=multi-user.target

https://www.freedesktop.org/software/systemd/man/systemd.service.html# и прилегающие маны закурил до дыр.

Проблема в том, что после старта сервис не отдаёт консоль и хотелось бы избежать использования --no-block, Кроме того, когда выполняешь

systemctl status some_shit.service
Оно показывает:
 Active: activating (start) since Thu 2017-12-07 08:39:01 PST; 10min 32s ago
Когда нормальный сервис должен показывать
active (running)
Предполагаю, нужно копать в сторону exit-codes, но что-то не получается. Знаю, intelfx шарит! Памагитепожалуйстааа!!11...

★★★★★

Тебе нужен Type=simple. С комментария поржал: вообще-то, вся задача systemd именно в том, чтобы сообщать, если «на старте что-то пошло не так».

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Но оно не справляетяс со своей задачей! Если ставлю simple, то после

systemctl start some.service
Оно завершается тихо-мирно, как будто всё ок, потом сервис падает, но это нигде не отображается, кроме как в логах, но это уже никого не колыбёт, ведь при forking такой ху,,ни нету, а если делать simple, то тогда потом придётся прикручивать дополнительный парсер логов, усложнять процесс деплоя, это грёбаный костыль!

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от Pyzia

Ничего не понял из твоих слов. И, кажется, ты тоже ничего не понял :)

Ты не должен выбирать Type= исходя из своих личных соображений. Он выбирается детерминистично исходя из того, как ведёт себя запускаемая программа. Type=forking выбирается, когда программа демонизируется. Type=simple — когда не демонизируется. Всё остальное решается другими способами.

Но оно не справляетяс со своей задачей!

Что за «задача», с которой нужно справляться?

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Ты не должен выбирать Type= исходя из своих личных соображений. Он выбирается детерминистично исходя из того, как ведёт себя запускаемая программа. Type=forking выбирается, когда программа демонизируется. Type=simple — когда не демонизируется. Всё остальное решается другими способами.

Это уже интереснее! Если в конце ExecStart я добавлю «&» это будет считаться за демонизацию?

Что за «задача», с которой нужно справляться?

Задача выдать при старте «failed to start some_shit, see systemctl status shit.service» если что-то пошло не так.

Pyzia ★★★★★
() автор топика

#если сделать type=simple, то юнит не падает с ошибкой, если на старте что-то пошло не так.

Уточняющий вопрос — если что-то пошло не так и some_shit завершился с ошибкой, то какой при этом exit code? Подозреваю, что несмотря на ошибку — нулевой, вследствие чего systemd думает, что все хорошо. Если подозрение верно, то, боюсь, придется костылить.

dexpl ★★★★★
()
Ответ на: комментарий от Pyzia

Если в конце ExecStart я добавлю «&» это будет считаться за демонизацию?

Нет, systemd — это не sh, и шелловые конструкции он не интерпретирует.

Задача выдать при старте «failed to start some_shit, see systemctl status shit.service» если что-то пошло не так.

Понимаешь, тут есть принципиальная проблема. systemd не знает и не может знать, в какой момент у some_shit заканчивается запуск и начинается непосредственно работа. То есть: если сервис упал через 2 миллисекунды — это он упал, потому что не смог распарсить конфиг или потому что он распарсил конфиг, запустился и успел крашнуться? А если через 500 миллисекунд? А через 5000? Сколько systemctl start должен ждать краша, прежде чем говорить «мы запустились» и возвращать управление пользователю?

Если сервис не сообщает systemd, в какой момент он закончил запускаться и начал работать — эта задача принципиально не решается.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 3)
Ответ на: комментарий от intelfx

Можно заставить ждаву выдавать правильные екзит коды? Если тряхануть програмистов? Или может, можно заставить системд воспринимать некоторый выхлоп за ексит код? В целом, я понял мыслю и кажется придётся всё-таки городить костыляку.

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от Pyzia

Нет, ты ничего не понял. Дело не в exit-кодах. Ещё раз: как systemd поймёт, когда заканчивается «старт» и начинается «работа»? В какой момент systemctl должен вернуть управление?

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от Pyzia

Этот таймаут совсем о другом. TimeoutStartSec — это время, по истечении которого юнит будет прибит, если не перейдёт из фазы «старт» в фазу «работа». В случае Type=simple фаза «старт» вообще пропускается — как я уже сказал, в этом случае systemd не имеет возможности отличить одно от другого.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Спсибо, я понял немного что к чему, теперь я уверен, что вставить костыль будет быстрее.

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от Pyzia

Прежде чем разбираться с systemd, сначала разберись со своим демоном. Ответь на вопрос: как сам демон сообщает о том, что он закончил стартовать и начал работать? Если он этой информации не сообщает ­— ты ничего не сможешь сделать. И только в противном случае можно думать над тем, как передать эту информацию в systemd.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Да, я уже тряхнул програмистов и они начали неспеша обещать впилить правильные экзит-коды, через 30 лет, если повезёт... Всё-таки приложуха совсем не линукс-совместима. Правда, это типа вроде как бета, но всёравно обидно. Ещё раз спасибо.

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от intelfx

По завершении нормального старта приложение плюёт в лог сообщение вида:

Listening for HTTP on /0:0:0:0:0:0:0:0:9000
Распарсить лог штатными средствами системд невозможно, насколько я понял, за эксит код это не канает, там два екзит кода, насколько я понял, 143-если всё нормально и 255 если жопа. Что делать дальше именно в этом направлении я не знаю, как решение просто добавил ещё одну строчку в деплоймент скрипт а-ля:
if [[ -z $(systemctl status adept-backend.service | grep "Listening for HTTP") ]]; then exit 9; fi;

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от Pyzia

С этого и нужно было начинать.

Ставишь Type=forking и пишешь элементарный скрипт-обёртку, в котором:

  • вешаешь обработчик на SIGCHLD, который делает wait и завершает скрипт c этим кодом возврата
  • запускаешь демона через &
  • запускаешь греп по журналу (journalctl -f -n0 -u <имя юнита> | grep -q <строка>)
  • выходишь с нулём
intelfx ★★★★★
()
Ответ на: комментарий от intelfx

В этом предложении есть небольшая гонка (между запуском демона и запуском journalctl), поэтому если в твоей версии systemd есть поддержка invocation id — лучше сделай -nall и отфильтруй по текущему invocation id.

intelfx ★★★★★
()
Ответ на: комментарий от anonymous

Как тока загоню его на свежайший РХЕЛ на нашем продакшене, ага

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от Pyzia

вам не exit codes нужны, а почитать про sd_notify, и научить приложение сообщать systemd свой статус при запуске при Type=notify

pod ★★
()

делай враппер

debug-start.sh

systemctl restart my123.service && journalctl -u my123.service -f

и пиши адекватно в логи. Всё, как на ладони!

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от pod

Жаль, всё как всегда нужно на вчера а я выгляжу самым незагруженным человеком на проекте, не то, что погромисты!

Pyzia ★★★★★
() автор топика
Ответ на: комментарий от pod

systemctl is-failed

Вот спасибо! Как раз про эту опцию я и забыл, очень помогла мне в моём костылестроении, а вернее сократила предыдущую конструкцию отсюда systemd service файл для запуска java процесса ч.7685796 (комментарий)

Pyzia ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.