- Run Your Java App as a Service on Ubuntu
- Bring your JAR file to Ubuntu as a service using this example service wrapper. See how to make it work, including automatic starts and logging tips.
- Step 1: Create a Service
- Step 2: Create a Bash Script to Call Your Service
- Step 3: Start the Service
- Step 4: Set Up Logging
- Running Java application as Linux service with systemd
- Create bash script to run your jar :
- Test if Java Application is working with the following commands:
- Creating a Service:
- Jar файл как служба Ubuntu
- 1) Пара слов о systemctl.
- 2) Создание службы.
- А) Где?
- Б) Как?
- Б.0) Создаём файл
- Б.1) Запуск java напрямую
- Б.2) Запуск sh-скрипта
- Б.3) Что тут к чему?
- Б.4) Нюансы.
- SuccessExitStatus=143
- Type = forking
- Остановка и рестарт приложения по эксепшену.
- В) Ошибки.
- В.1) Как смотреть?
- В.2) Кавычки!
- В.3) Права доступа.
- Общий вывод.
Run Your Java App as a Service on Ubuntu
Bring your JAR file to Ubuntu as a service using this example service wrapper. See how to make it work, including automatic starts and logging tips.
Join the DZone community and get the full member experience.
Say you have a JAR file and you need to run it as a service. Additionally, you want it to start automatically if/when system restarts.
Ubuntu has a built-in mechanism to create custom services, enabling them to get started at system boot time and start/stop them as a service. In this post, I am going to share a simple and elegant way to create a service wrapper for your JAR file so you can run it as a service. Here we go.
Step 1: Create a Service
Copy/paste the following into the file /etc/systemd/system/my-webapp.service :
Step 2: Create a Bash Script to Call Your Service
Here’s the bash script that calls your JAR file: my-webapp
Don’t forget to give your script execute permission: sudo chmod u+x my-webapp
Step 3: Start the Service
Step 4: Set Up Logging
First, run: sudo journalctl —unit=my-webapp . See real-time logs by using the -f option.
If you want to trim them, use -n to view the specified number of lines of the log:
Tail the live log using the -f option:
Stop the service by using:
That’s it! Enjoy and show your support if you like it. Thanks!
Published at DZone with permission of Muhammad Sarwar . See the original article here.
Opinions expressed by DZone contributors are their own.
Источник
Running Java application as Linux service with systemd
Oct 3, 2018 · 2 min read
While searching for this online I got about 2–3 different ways on how to configure systemctl commands to run my Jar Files.I am writing the best way which worked for me and should work for you guys too.Also, none of them explained it from a java developer’s perspective. My goal in this blog is to document my findings, the information that would save everyone the efforts of finding alternatives.
I assume you have your java cod e with all its dependencies in a jar file.This means you should right now be able to run your code using:
(sudo) java -jar Name_Of_File.jar
Ubuntu has a built-in mechanism to create custom services, enabling them to get started at system boot time and start/stop them as a service.
Create bash script to run your jar :
- Create a vi /nano file under /usr/local/bin/ by running the following command
eg. sudo vi /usr/local/bin/Service_Name.sh
This will open a file Service_Name.sh. - Paste the following Code in your Service_Name.sh.
Modify the SERVICE_NAME(Name of your Service), PATH_TO_JAR(Absolute Path to you jar File), and choose a PID_PATH_NAME(just replace Service_Name to your Service_Name keeping -pid at end ) for the file you are going to use to store your service ID.Only Changes needed are to the first 3 variables.
3. Write and quit the above file and give execution permisions :
ex. sudo chmod +x /usr/local/bin/Service_Name.sh
Test if Java Application is working with the following commands:
Creating a Service:
- Create a file under /etc/systemd/system/ with nano or vi and paste the example script below.
eg. sudo vi /etc/systemd/system/Service_Name.service
2.Insert the following code in Service_Name:
3.Write and quit this file.
Your Service is all set up.To Test your Java Application as a Service use the following commands to enable/start/stop/:
This should get your Java Application up and running as a System Service.
Enjoy and Feel free to reach out to me in case of any doubts/discrepancies.
Источник
Jar файл как служба Ubuntu
Jan 13, 2020 · 10 min read
Чтобы создать кастомную службу, нужно чуточку знать о systemd.
systemd — это набор базовых утилит для Linux. Набор предоставляет диспетчер системы и служб, запаускаемый с PID 1, и запускающий остальную часть системы. Systemd управляет службами, запускает демонов, поддерживает монтирование, управляет конфигурацией системы, ведёт логи, отслеживает входящих в систему юзеров, запуск контейнеров и вирт машин и т.д.
С 8-ой версии Debian по умолчанию используется systemd вместо init.d, который использует unit-файлы из каталога /etc/systemd/system, вместо скриптов из /etc/init.d/.
systemctl — основная команда для контроля и отслеживания состояния systemd. С помощью неё мы и будем запускать кастомные службы.
1) Пара слов о systemctl.
Тольк о касательно запуска служб, ибо возможностей у неё гораздо больше.
Вывести список служб ( — no-legend — без шапки и пояснений; — all — не только активные, а все):
Юнитами могут быть как службы (.services), так и точки монтирования (.mount), устройства (.device) или сокеты (.socket)
если интересны только зафэйлиные службы:
Если юнит не указан, то считается, что это . service, в данном случае smbd. service; также точки монтирования преобразуются из / home в home. mount, а имена устройств в юниты-девайсы: /dev/sda2 в dev-sda2.device. При выводе статуса перечисляются все запущенные службой процессы и выводится последняя часть лога.
Посмотреть службы и зависящие процессы юзера:
Если в имени юнита содержится @, значит это экземпляр юнита-шаблона. Например, user@1000.service — экземпляр шаблона user@.service. Экземпляры отличаются идентификаторами, указывающимися после @.
После создания службы может потребоваться перезагрузка настроек systemd:
А также добавить службу в автозапуск при загрузке системы:
2) Создание службы.
А) Где?
Для начала надо создать файл описания службы. Где это сделать? Посмотрим, откуда вообще загружаются юниты:
Положим в приоритетную папку /etc/systemd/system.
Б) Как?
Посмотреть пример имеющейся службы можно так:
А вообще у нас как минимум два варианта:
— Запуск джавы напрямую (не надо никаких доп скриптов)
— Запуск скрипта, который запускает джаву (можно описать доп действия в скрипте)
Б.0) Создаём файл
Б.1) Запуск java напрямую
Б.2) Запуск sh-скрипта
Б.3) Что тут к чему?
Часть строк интуитивно понятна, а часть не очень. Разберём же их (и немного того, что ещё можно указать в файле службы):
Description = Java Test Service
# Зависимость службы от подключения к сети (или любой другой службы):
# если зависимость необходима
# если зависимость не обязательна (взаимоисключаемо с requires)
# если нужно запускать только после подключения к сети. Если не указать, то служба может быть запущена параллельно с поднятием сети (или любой другой указанной службой)
# Type — без указания будет simple — заупск cmd и получение от неё ответа об ЕЁ успешном запуске.
# exec — запуск cmd и получение ответа об успешном запуске именно итогового приложения.
# forking — ждёт, когда указанная служба сделает fork() от главного процесса, потом ждёт завершения главного процесса и стартует последующие за ним юниты.
(дальше в разделе «нюансы» будет объяснено дополнительно)
# пользователь, под которым запускать приложение
# Рабочая директория вашего приложения. Т.е. при получении внешних файлов ваша программа будет отталкиваться от указанной здесь папки.
WorkingDirectory=/home/snatchub/Documents/Share/jar as service test
# Путь к исполняемому файлу — либо к java с параметрами, либо к скрипту, запускающему ваше приложение.
ExecStart=/home/snatchub/Documents/Share/jar as service test/my_amazing.sh
# Скрипт, запускаемый по команде «Стоп». Если не указан, то просто шлётся SIGTERM
ExecStop = /home/snatchub/Documents/Share/jar as service test/my_amazing.sh stop
# скрипт для перезапуска
ExecReload = /home/snatchub/Documents/Share/jar as service test/my_amazing.sh reload
# Путь к PID файлу сервиса (туда пишется PID процесса приложения). Нужен для отслеживания основного процесса.
# Сервис менеджер сам не пишет в этот файл, только читает оттуда pid, а также удаляет его после завершения приложения.
# Это дополнительный «успешный» статус окончания работы приложения.
( дальше в разделе «нюансы» будет объяснено дополнительно)
# Если указан тайм-аут, то сначала мы ждём указанное время окончания выполнения команды ExecStop, потом если служба не остановилась, шлём SIGTERM и ждём указанное время, после чего шлём SIGKILL, если у нас очень живучее приложение.
# on-failure — перезапускать приложение при ошибке (Unclean exit code, Unclean signal, Timeout, Watchdog).
# Можно указать always , если приложение всегда должно быть запущено. На команду “ systemctl stop” это не распространяется.
( дальше в разделе «нюансы» будет объяснено дополнительно)
# Через какое время после остановки произойдёт рестарт. По дефолту время перезапуска 100ms
# Служба должна регулярно вызывать sd_notify(3) с “ WATCHDOG=1” (считай это “ keep-alive ping”-ом).
# Если время между двумя вызовами больше указанного, то служба считается «нерабочей» и останавливается сигналом SIGABRT или тем, что указан в « WatchdogSignal».
# По дефолту в значении control-group , что значит при остановке службы будут убиты все оставшиеся процессы в контрольной группе основного процесса (после выполнения скрипта, указанного в команде « ExecStop»).
# Если указан « process », то только главный процесс будет убит.
# уровень запуска. multi-user.target соответствует уровню runlevel3 и значит, что служба запустится ещё до запуска графической оболочки, но когда юзеры смогут входить в систему через консоль.
Кратко: если pid файл не существует, то стартуем джава-процесс и пишем его pid в файл, иначе убиваем процесс по pid’у из файла и удаляем файл.
if [ ! -f $PID_PATH_NAME ]; then
-f — истина, если файл существует.
nohup “$PATH_TO_JAVA” $JVM_PARAMS -jar $PATH_TO_JAR $APP_PARAMS >> amazing.out 2>&1 &
nohup — утилита, запускающая указанную команду с игнорированием сигналов потери связи (SIGHUP). Т.е. команда будет продолжать выполняться в фоновом режиме даже после выхода юзера из системы.
Знак & в конце означает старт джава-приложения как демона, т.е. скрипт не будет дожидаться окончания джава приложения и пойдёт дальше по своим командам.
2>&1 означает stderr(2) перенаправляется (>) в stdout(&1). Здесь & указывает, что последующую за ней единицу следует воспринимать как дескриптор файла, а не как имя файла.
>> amazing.out — перенаправление потоков в файл.
“ ! — Expands to the process ID of the most recently executed background (asynchronous) command.” (с) man bash
Из этой ни разу не витиеватой фразы делаем глубокомысленный вывод, что $! содержит ID процесса.
2>/dev/null — перенаправление потока ошибок в никуда. Просто подавление ошибок.
Б.4) Нюансы.
SuccessExitStatus=143
Как я уже упомянул — это дополнительный «успешный» статус окончания работы приложения, от которого зависит будет ли ваше приложение перезапускаться или нет в случае ошибки, т.е. когда указано Restart=on-failure или always.
Когда мы останавливаем службу « systemctl stop», то шлётся сигнал SIGTERM с кодом завершения приложения 15, который по умолчанию для службы считается успешным. Но джава завершается с кодом 143 вместо 15, поэтому нужно сказать убунте, что наш код 143 тоже должен считаться успешным.
Если не добавить этот статус, то при попытке остановить службу « systemctl stop», мы увидим статус “ failed” вместо “ inactive”, якобы приложение завершилось по ошибке, и если у нас стоит рестарт, то оно будет перезапущено, вместо остановки.
Почему 143? Потому что по Posix спецификации “The exit status of a command that terminated because it received a signal shall be reported as greater than 128”.
Джава решила следовать спецификации и, таким образом, 143–128 = 15 — это сигнал SIGTERM.
Type = forking
Если запустить джаву напрямую с типом « forking», то увидим такую картину в статусе службы:
Через 1,5 минуты служба отвалится по тайм-ауту и попробует рестартовать приложение, но снова безуспешно. Джава не может форкнуться. Поэтому если в службе вызываете джаву напрямую, то либо уберите этот пункт, либо ставьте явно « Type=simple».
Если запускаете .sh скрипт, то вот что будет при Type=forking:
Скрипт успешно завершился, а джава продолжает работать и может быть остановлена менеджером служб.
Основной процесс мёртв и джава не работает в фоне.
Если type=simple, то служба должна запускать джава приложение напрямую, либо через .sh-скрипт, который должен работать и ждать окончания джава приложения (т.е. не запускать её демоном).
Если type=forking, служба должна стартовать .sh-скрипт, который может завершиться после запуска джава-приложения (т.е. можно запустить её демоном).
Остановка и рестарт приложения по эксепшену.
Давайте сымитируем ошибку в пользовательском треде (не демоническом) и посмотрим, перезапустится ли служба ( пример кода на гитхабе). Если сделать это прямо в main-thread, то всё работает, как надо, приложение возвращает статус ошибки и перезапускается. Вот только main-thread как правило заканчивает свою жизнь быстро по выходу из метода main(String[] args), а приложение дальше живёт на остальных пользовательских тредах. Создадим такой отдельный тред и вызовем ошибку там. Оп-па, приложение завершается, вот только успешно, а не с ошибкой! Соответственно, перезапущена она при « Restart=on-failure» не будет. И если у нас не установлен общий « uncaught exception handler», мы даже увидим эту ошибку в логах службы:
Почему же так происходит?
Потому что джава возвращает только статус окончания main-треда и игнорирует статусы остальных пользовательских тредов.
Если ваше приложение должно всегда работать, то можно выставить « Restart=always». В ином случае рассмотрите вариант использования « Thread.setDefaultUncaughtExceptionHandler()» с логированием ошибки и « System.exit(1)» внутри этого обработчика.
В) Ошибки.
В.1) Как смотреть?
После запуска не забываем смотреть статус службы, там могли быть проблемы:
В таком случае стопорим службу (дабы не перезапускалась) и смотрим снова статус и последние строки лога службы:
Более полный лог можно посмотреть с помощью команды:
Также можем отслеживать живой лог с опцией -f :
В.2) Кавычки!
Важно не забывать знак равенства и не напутать с кавычками, если у вас в путях есть пробелы. Где-то кавычки нужны (в exec секции), а где-то нет (в working directory). Иначе рискуете наткнуться на кучу сообщений об ошибках, типа:
В.3) Права доступа.
Не забудьте добавить прав на запуск скрипта.
u означает чьи права на доступ будут изменены: юзера-владельца в данном случае.
Оператор + вызывает добавление выбранных битов режима файла к существующим. Т.е. добавляет права, а не переписывает их.
x — само право: выполнение (или поиск для директорий)
Если дали прав на скрипт, но не дали на директорию с логами и ресурсами:
Проверяем рестарт службы по ошибке:
Видно, что служба вылетела по ошибке и рестартовала через 5 секунд.
Общий вывод.
Встроенных средств в убунту достаточно для запуска jar-ников как служб, используем systemctl и радуемся безотказной работе!
Примеры кода лежат на гитхабе
Не стесняйтесь пожать руку на Medium или Telegram.
Источник