Java приложение как служба windows

Делаем java приложение как windows-сервис

Введение

В общем, расскажу я вам сказку про Terracota’овский сервер. В одной далёкой галактике На одной из наших виртуалок на конторе, жила-была ВебСфера (прожорливая сволочь), которая голодала от недостатка места на жёстом диске и, как результат, приложения живущие на ней начинали сильно лагать, вследствие чего приходилось часто приходилось ребутать вирталку для нормальной жизни приложений на сфере. Но не одиноки мы во вселенной(возможно), тем не менее на Земле так точно не одни, так и на виртуалке кроме сферы жили и другие монстры, куда менее прожорливые, вроде Terracotta сервера и других приложений. Так вот, вследствие перерождения галактики перезагрузки виртуалки терракотовский сервак постоянно надо было поднимать, так как наши приложения хранящие данные в кластере не могли запуститься, потому ожидали коннекшена от лежачего сервака. Естественно, кому-то из команды постоянно приходилось запускать Терракотту вручную, что, в общем, то было утомительно:). Мною было принято решение создать галактический отряд windows сервис по поднятию сервера после перезагрузки виртуалки, что казалось задачей на 15 минут, и тут я наткнулся на Дарта Вейдера подводные камни. Хренова конечно, что из коробки в терракоте нет создания сервиса после установки.

К делу

Посмотрим, что у нас есть:

  1. Windows Server 2008 какой-то edition(с установленным Windows Resource Kit Tools).
  2. Установленная JDK6
  3. Terracotta
  4. Световые мечи

Чего не хватало:

  1. Пива
  2. srvany.exe – утилита, позволяющая запускать любую программу как службу, позволяя тем самым создавать пользовательские службы(странно но у меня на виртуалке этого файла не было). Скачаваем с инета.
  3. Знаний использования реестра.(Этот недостатот быстро отпадает)

Для начала скопируем скачанный srvany.exe в папки /bin с терракотой. В моём случае нехватало батника для создания сервиса, т.к. путь к терракоте содержал
пробелы. Если кто знает как в консоли прописывать пути без пробелов, прошу писать в комменты.
Сообственно createService.bat:
sc.exe create Terracotta binPath=“c:\Program Files\terracotta-3.2.1_1\bin\srvany.exe” type=own start=auto DisplayName=“Terracotta Server 3.2.1_1”
Думаю пояснений не требуется. Windows сервис требует данных о приложении в регистре. Создаём tcservice.reg:

REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Terracotta\Parameters]
«Application»=»\»C:\\Java\\jdk1.6.0_17\\bin\\java.exe\\»
«AppParameters»=»-cp c:\\Program Files\\terracotta-3.2.1_1\\lib\\tc.jar -server -Xms4G –Xmx4G -XX:+HeapDumpOnOutOfMemoryError -Dtc.install-root=c:\\Program files\\terracotta-3.2.1_1 com.tc.server.TCServerMain»
«AppDirectory»=»c:\\Program Files\\terracotta-3.2.1_1\\»

И запускаем его. Не знаю почему, да и в общем то времени на разборку не было, но скрипт у меня не запускался, а данные в регистр не попадали:(. Поэтому делаем всё ручками. Запускаем regedit, заходим по пути HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Terracotta\Parameters и создаём там строковые параметры типа Application с указанием путей типа С:\\Java\\jdk1.6.0_17\\bin\\java.exe Также можно применить дополнительные параметры, если терракота работает не с дефолтовыми настройками:

«AppParameters»=»-cp c:\\ Program Files \\terracotta-3.2.1_1\\lib\\tc.jar -server –Xms512M –Xmx512M -XX:+HeapDumpOnOutOfMemoryError -Dtc.install-root=c:\\terracotta\\terracotta-3.2.1_1 com.tc.server.TCServerMain -f c:\\ Program Files \\my-tc-config.xml -n Server1″

Всё сделали. Тестим заходим в Панель Управления -> Администрирование –> Службы, ищем сервис с названием Terracotta Server 3.2.1_1. Запускаем. Провеяем порты и видим, что приложение стартануло, если нет, проверьте правильность указания путей. Надо бы ещё убедиться что приложение встанет после перезагрузки виртуалки. Значит, что делаем? Выключаем сервер из розетки перезагружаем виртуалку – видим, что сервер поднялся автоматически. Ура. Таким макаром можно любое Java приложение сделать как windows сервис.

Читайте также:  Где лежат файлы событий windows

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

По просьбе камрада Gangsta раскрываю подробности работы NSIS-скрипта, описанного в прошлом топике. В нем было перечислено несколько файлов, входящих в тестовый дистрибутив (install.bat, wrapper.properties) и т.п. Что в них находится и зачем они нужны? С точки зрения изучения возможностей установщика NSIS эта информация избыточна: файлы и файлы, которые могли называться как угодно и содержать что угодно. Главное было — положить их в нужную папку на целевой машине. В отладочных целях в том скрипте не был предусмотрен даже автозапуск самопального install.bat (хотя возможности для этого в NSIS есть).

Однако рассмотренный пример интересен еще и тем, что устанавливает на Windows-компьютер Java-приложение в качестве сервиса, а это весьма ценно. Ведь сервис запускается скрытым для обычного пользователя образом (т.е. на экране не маячит дурацкое черное окно), может выполнять привилегированные операции, его можно перезапускать и останавливать. Как всё это реализовать, если речь идет о Java-приложении (в данном случае — Apache Felix)?

Вообще-то, на затронутую тему я уже писал на Мтааламу. Однако было это в самом начале жизни сайта и материал почти никто не заметил (судя по его рейтингу и количеству комментариев). Да и сам топик был беглый: есть, мол такой проект — Java Service Wrapper, посвященный именно запуску Java приложений в качестве сервисов, причем как под Windows, так и под *NIX. Хорошо, что спустя год появился повод вернуться вернуться к этой теме.

Если вы скачаете дистрибутив Java Service Wrapper, то обнаружите там множество файлов на все случаи жизни: для разных версий Windows и Linux. Из них для запуска сервиса на обычной Windows-XP нужны только три:

* wrapper-windows-x86-32.exe
* wrapper-windows-x86-32.dll
* wrapper.jar

плюс конфигурационный файл, настроив который, вы можете запускать любое консольное Java-приложение, имеющее метод public static void main(String[] args) в виде сервиса. В зависимости от ключей, сервис может быть:

запущен в консольном режиме в целях отладки (без установки в качестве сервиса):

Осталось рассмотреть конфигурационный файл. В случае с Apache Felix он выглядит так:

По-моему, особые комментарии не требуются. Скажу лишь, что поскольку файл содержит кириллические буквы, желательно сохранить его в кодировке Cp1251, иначе его название в списке сервисов Windows будет крокозябрами. А о том, что всё это работает и сервис действительно появляется в списке, свидетельствует скриншот из старого топика:

Jar файл как служба windows (и бонусом jar to exe)

Aug 22, 2019 · 10 min read

Итак, ваш проект дожил до продакшена и хотелось бы стартовать его вместе с системой, а не поднимать ручками каждый раз. Но как нам это сделать с обычным jar’ником?

Есть кучка вариантов:

I) Положить в стартап винды батник с запуском java -jar или экзешник (предварительно сделав из jar’а exe-файл).

Это решит проблему, вот только запускаться ваше приложение будет в лучшем случае при первом входе в систему любого юзера (если кинуть в стартап для all users), а, как известно, хороший админ на сервер не лазит.

II) Сделать task в винде, стартующий батник при старте системы.

Этот ва р иант решает проблему с запуском на ура, вот только манипуляция приложением на этом заканчивается, ни старт-стопа тебе в любое время, ни перезапуска по ошибке.

Читайте также:  Что означает resuming windows

III) Можно запустить jar’ник в виде службы винды с помощью sc.exe (есть ещё Srvinstw.exe — гуёвая версия, но мы же тру-программисты и должны использовать командную строку).

Это маленькая программа из Resource Kit для создания служб из exe-шников.

Но у нас ведь jar-файл?! Не беда! Есть варианты на попробовать:

1) запускать напрямую java.exe -jar с параметрами.

2) сделать из jar’a exe-file и превратить его в службу.

а) запускать из него java.exe –jar

б) написать bat-ник с запуском java -jar и запускать его

IV) Заюзать сторонний софт.

Разгребём эту кучку, пропустив первые 2 пункта как наименее интересные.

0) Приложение

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

— ругаться на то, что параметров нет

— в зависимости от них читать те или иные файлики настроек

— парсить внешней библиотекой эти настройки

— каждые 5 секунд сыпать в лог снова эти же настройки

Пример приложения можно посмотреть здесь:

Моим результатом будет executable jar-файл, с зависимыми библиотеками и ресурсами снаружи в отдельной папке. Вы можете сделать, как хотите, поэкспериментируйте.

1) Запуск службы с sc.exe

Итак, чтобы ознакомиться со справкой sc достаточно ввести

Результатом будет «Ошибка. Неопознанная команда» и далее справка по возможным командам.

А) Создаём службу с java.exe –jar

У меня jdk таскается за собой, чтобы не зависеть от имеющихся на серверах версий и для придачи моей программе солидности в виде большого объёма. Полный путь к java.exe в случае наличия её в переменных окружения, не обязателен. Стоит отметить одну назойливую и малозаметную особенность: « binPath= » — после любого параметра (тут binPath) сразу идёт знак равенства, а после него обязательно пробел перед значением этого параметра.

Отлично, служба создана, запускаем её! Упс.

( у меня TestService будет иметь в примерах разные цифры, т.к. не всегда служба удалялась сразу, иногда она только помечалась на удаление)

Смотрим на всякий случай, не появился ли лог нашего приложения. А он-таки есть! Только крохотный, содержащий инфу с момента попытки запуска службы до момента выдачи ошибки. Что произошло? А вот что:

— старт службы запустил java.exe с нужными параметрами

— наше приложение начало свою работу

— менеджер служб винды ждёт некоторое время ответа от java.exe о её успешном (или нет) запуске

— но java.exe ничего не возвращает, потому что она никому ничего не должна

— менеджер служб отсчитал положенные по таймауту секунды и отстрелил джаву

Вывод: не каждый exe-шник одинаково полезен для запуска в виде службы. Нельзя просто так взять и запустить любой exe-шник, он должен быть специально заточен под виндовые службы (как минимум возвращать некие данные о своём запуске).

А может javaw попробуем? Попробуйте, вот только double-V в имени не означает двойную победу.

Б) Создаём службу с cmd /c java.exe -jar

А что если запустить cmd в cmd в cmd и в ней бахнуть джаву? Закроется вся цепочка? Начнём с малого — запустим просто джаву из cmd, а саму cmd укажем как binpath при запуске службы:

Точно также отваливаемся по тайм-ауту, вот только завершает свою никчёмную жизнь лишь процесс cmd, а наше мега джава приложение продолжает дышать и радовать.

Читайте также:  Подключение onedrive как сетевой диск windows 10

Работает? Да! Как полноценная служба? Да ни в зуб!

Но положим наш джарник в папку с пробелами, чтобы ещё немного поэкранировать насладиться созиданием наклонных палочек подле кавычек:

Заглянем в реестр:

Выглядит неплохо, только параметры бы ещё в кавычки запихнуть для полного счастья.

Вывод: трюки — это хорошо, но не всегда полезно на все 100%.

В) Создаём службу с srvany.exe java.exe –jar

srvany.exe — это тоже программулина из Resource Kit. Её работа проста — запускать указанное приложение. Т.е. мы регистрируем srvany.exe в качестве службы с параметрами, указывающими путь к нашей программе. Порядок: стартуем службу → стартует srvany → стартует наше приложение.

Добавим параметры для запуска srvany:

Стартуем.. наблюдаем.. ждём.. наблюдаем.. работает!! Всё? Это конец? Или чего-то не хватает? Зачем придумывали сторонний софт (кроме цели самообучения и рекламы)? А вы попробуйте убить процесс или вызвать в нём ошибку. А мы плавно перейдём к следующему пункту.

Вывод: srvany работает, но хромает ловля ошибок.

2) Запуск службы сторонним софтом NSSM.

Краткий список разного софта:

— jsvc (версия для извращенцев: «It can run on Win32 via the Cygwin emulation layer» (с))

Вот последний-то мы и используем. Для ленивых повторим вопрос: так зачем нам сторонний софт? Для них же ответ есть прямо с сайта nssm:

«srvany and other service helper programs suck because they don’t handle failure of the application running as a service. If you use such a program you may see a service listed as started when in fact the application has died. nssm monitors the running service and will restart it if it dies.»

Как оно работает? Всё также: nssm.exe устанавливается в качестве службы с определёнными параметрами, при старте этой службы запускается сам nssm.exe, который в свою очередь запускает java.exe –jar. Вот вам сразу наглядный запуск в диспетчере задач:

Теперь по порядку. Выполняем « nssm.exe install TestServ » для запуска GUI.

Тоже самое можем сделать с помощью командной строки:

AppDirectory установить для нас важно, т.к. используемые нами конфиги и библиотеки лежат именно там, рядом с нашим приложением в поддиректориях resources, res.

Если служба вам надоела, или вы накосячили при её создании, то выполните команду:

Поглядим впритык на записи в реестре:

Все параметры и кавычки в них на месте. Смотрим инфу о службе:

Запускаем службу.. Ура! Всё работает, логи пишутся!

Попробуйте убить джаву или зафейлить своё приложение изнутри.

Вывод: сторонний софт, не написанный нашими великолепными руками, мозгами и ногами, тоже имеет право на жизнь.

3) Автоматизируй это!

Негоже ручками запускать на 30 серверах, нужен скрипт! Опустим раскидывание по тачкам, сделаем хотя бы создание службы, чтобы можно было заменить одно имя переменной, и всё корректно создалось, и запустилась именно та конфигурация для вашего приложения, которая нужна на текущем сервере.

Но скрипт — это же просто! Уверены? А если в имена добавить пробелы? Боль кроется в деталях тонкой настройки кавычек и их экранирования. Допустим, выносим мы AppDir в переменную. Как должны записать её в параметрах и в качестве текущей директории, где кавычки надо, а где нет?

использование в параметрах:

как текущая директория:

При неправильной настройке можно получить такую ошибку при старте службы:

Идём за подробностями в журнал системных событий:

Оцените статью