Windows service using java

Делаем 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 сервис.

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

Создание Windows службы на Java

February 22, 2019 Jazz Team Технические статьи

Читайте также:  Что такое виртуальный сервер vps windows

Введение

В рамках одного из проектов требовалось разработать Windows службу, которая могла бы выполнять ряд действий с помощью Windows API, Websocket и стандартных средств Java. Далее в статье будут описаны шаги, которые были сделаны для создания такой службы.
Потребность в Windows службе возникла из-за необходимости иметь программу со следующими возможностями:

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

Создание минимизированной версии JRE

Так как GraalVM всё ещё не поддерживает создание исполняемых файлов под Windows, было решено воспользоваться другими возможностями, которые предоставляет экосистема Java, а именно создание минимизированной версии JRE.

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

В первую очередь необходимо собрать jar-файл “fat jar” со всеми зависимостями.

Затем выполнить команду jdeps -s , чтобы получить список всех зависимостей. Например:

Далее создаём нашу версию JRE с данными зависимостями:

jlink –module-path –add-modules

java.base,java.datatransfer,java.desktop,java.logging,java.net.http,java.sql,java.xml,jdk.unsupported –strip-debug –compress 2 –no-header-files –no-man-pages –output

Обратите внимание, что перечисление пакетов для опции –add-modules необходимо разделять запятой и не ставить между ними пробелов. Остальные опции отвечают за сжатие и убирание файлов и другой информации, которая не пригодится для выполнения программы.

После выполнения этих действий JRE будет занимать порядка 30 mb, вместо сотен.

Создание Windows службы из любого приложения

Java не имеет стандартных средств по созданию служб, поэтому были изучены сторонние инструменты и был выбран WinSW в силу его бесплатности и простоты использования.

WinSW

WinSW – это утилита, которая позволяет запустить и обернуть любой процесс как Windows службу. Для того, чтобы начать с ней работать, необходимо скачать исполняемый и конфигурационный файлы по этой ссылке https://github.com/kohsuke/winsw/releases.

Необходимо поместить эти два файла в директорию. Переименовать исполняемый файл на своё усмотрение и дать такое же название файлу конфигурации, затем поместить в эту директорию jar-файл приложения и созданную JRE.

В конфигурационном файле необходимо прописать минимальную конфигурацию:

jre\bin\java.exe – относительный путь внутри нашей папки к исполняемому файлу нашей JRE.

После этих действий можно установить службу, для этого необходимо выполнить команду от имени администратора:

Список команд можно посмотреть здесь .

Взаимодействие Java и Windows API

Для использования функций Windows (таких как создание нового процесса или добавление ключей реестра) в нашем приложении был использован JNA.
JNA (Java Native Access) предоставляет Java-программам легкий доступ к библиотекам, написанным на другом языке, без написания чего-либо, кроме кода Java. JNA позволяет напрямую вызывать нативные функции, используя обычный вызов метода Java. Большинство методов не требуют специальной обработки или конфигурации; не требуется шаблон или сгенерированный код.
Подключить и работать с JNA очень просто, для этого необходимо скачать jar-файл или подключить зависимость в сборщик проекта – в нашем случает Maven:

В нашем проекте мы использовали JNA для достижения следующих целей: заблокировать и сделать вновь доступным диспетчер задач 1) по комбинации Ctrl+Shift+Esc и 2) в меню, доступном по комбинации Ctrl+Alt+Del.

Для достижения этого были использованы класс Advapi32Util (удобная обёртка над библиотекой advapi32.dll) и интерфейс WinReg с полезными константами , которые предоставляют функциональность для внесения изменений в реестр Windows (Рисунок 1. Класс TaskManager с методами enable() и disable() для изменения ключей реестра диспетчера задач).

Рисунок 1. Класс TaskManager с методами enable() и disable() для изменения ключей реестра диспетчера задач.

  • Создать новый процесс от имени определённого пользователя Windows. Для этого мы использовали метод CreateProcessAsUser()интерфейса Advapi32. В метод необходимо передать следующие параметры:
    • hToken – дескриптор токена пользователя, для которого мы запускаем процесс.
    • lpApplicationName – имя модуля, который должен быть выполнен.
    • lpCommandLine – командная строка для выполнения.
    • lpProcessAttributes – указатель на структуру SECURITY_ATTRIBUTES, которая определяет дескриптор безопасности для нового объекта процесса и определяет, могут ли дочерние процессы наследовать возвращенный дескриптор процесса.
    • lpThreadAttributes – указатель на структуру SECURITY_ATTRIBUTES, который определяет дескриптор безопасности для нового объекта потока и определяет, могут ли дочерние процессы наследовать возвращенный дескриптор потока.Создать новый процесс от имени определённого пользователя Windows. Для этого мы использовали метод CreateProcessAsUser() интерфейса Advapi32. В метод необходимо передать следующие параметры:
    • bInheritHandles – если этот параметр TRUE, каждый наследуемый дескриптор вызывающего процесса наследуется новым процессом. Если параметр FALSE, процессы не наследуются.
    • dwCreationFlags – флаги, которые контролируют класс приоритета и создают процесс.
    • lpEnvironment – указатель на блок среды для нового процесса. Если этот параметр равен NULL, новый процесс использует среду вызывающего процесса. Блок среды состоит из блока с нулевым завершением строк с нулевым завершением. Каждая строка имеет следующий вид: name = value \ 0.
    • lpCurrentDirectory – полный путь к текущему каталогу для процесса. Строка также может указывать путь UNC (universal naming convention).
    • lpStartupInfo – указатель на структуру STARTUPINFO или STARTUPINFOEX.lpProcessInformation – указатель на структуру PROCESS_INFORMATION, которая получает идентификационную информацию о новом процессе.
Читайте также:  Windows 10 возникла проблема с запуском устройства код 411

Рисунок 2. Метод для создания нового процесса для определённого пользователя Windows.

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

Работа с процессами

Для работы и слежения за процессами в Windows был использован, добавленный в Java 9, класс ProcessHandle. ProcessHandle позволяет получать и производить различные манипуляции с процессами. В частности, при решении задачи, требовалось собирать PID процессов, фильтровать процессы на основе имени и принудительно завершать необходимые процессы.

Рисунок 3. Класс ProcessHandler с методами takeSnapshot() для создания снимка текущих процессов и closeNewProcesses() для завершения процессов, отличных от снимка.

Взаимодействие с другими компонентами системы

WebSocket

Для Java существует стандартизированный API для работы с WebSocket.

Но одного API недостаточно, поэтому для запуска кода была выбрана одна из его реализаций – Tyrus.

Далее можно создать минималистичный сервер и указать обработчики (EndPoints).

Заготовка обработчика выглядит следующим образом:

HTTP-клиент

С выпуском 11-ой версии Java в ней появился удобный HTTP-клиент, поэтому потребность в сторонних клиентах исчезла.

Для создания экземпляра клиента необходимо воспользоваться билдером. В простейшем случае:

Далее необходимо создать запрос(request), например:

Затем этот запрос можно использовать для отправки на сервер:

Заключение

Благодаря модульной организации версий Java 9 и выше, утилите WinSW, обновлённому Process API для взаимодействия с процессами операционной системы и библиотеки JNA (Java Native Access), которая предоставляет программам Java простой доступ к нативным библиотекам, мы смогли создать Windows службу с использованием языка Java, на котором была реализована и серверная часть. Что в итоге позволило не вводить в процесс разработки новый язык.

How to create a windows service from java app

I’ve just inherited a java application that needs to be installed as a service on XP and vista. It’s been about 8 years since I’ve used windows in any form and I’ve never had to create a service, let alone from something like a java app (I’ve got a jar for the app and a single dependency jar — log4j). What is the magic necessary to make this run as a service? I’ve got the source, so code modifications, though preferably avoided, are possible.

19 Answers 19

Apache Commons Daemon is a good alternative. It has Procrun for windows services, and Jsvc for unix daemons. It uses less restrictive Apache license, and Apache Tomcat uses it as a part of itself to run on Windows and Linux! To get it work is a bit tricky, but there is an exhaustive article with working example.

Besides that, you may look at the bin\service.bat in Apache Tomcat to get an idea how to setup the service. In Tomcat they rename the Procrun binaries (prunsrv.exe -> tomcat6.exe, prunmgr.exe -> tomcat6w.exe).

Читайте также:  Уровень целостности файла windows

Something I struggled with using Procrun, your start and stop methods must accept the parameters (String[] argv). For example «start(String[] argv)» and «stop(String[] argv)» would work, but «start()» and «stop()» would cause errors. If you can’t modify those calls, consider making a bootstrapper class that can massage those calls to fit your needs.

With Apache Commons Daemon you can now have a custom executable name and icon! You can also get a custom Windows tray monitor with your own name and icon!

I now have my service running with my own name and icon (prunsrv.exe), and the system tray monitor (prunmgr.exe) also has my own custom name and icon!

Download the Apache Commons Daemon binaries (you will need prunsrv.exe and prunmgr.exe).

Rename them to be MyServiceName.exe and MyServiceNamew.exe respectively.

Download WinRun4J and use the RCEDIT.exe program that comes with it to modify the Apache executable to embed your own custom icon like this:

Now install your Windows service like this (see documentation for more details and options):

Now you have a Windows service of your Jar that will run with your own icon and name! You can also launch the monitor file and it will run in the system tray with your own icon and name.

One more option is WinRun4J. This is a configurable java launcher that doubles as a windows service host (both 32 and 64 bit versions). It is open source and there are no restrictions on its use.

(full disclosure: I work on this project).

Yet another answer is Yet Another Java Service Wrapper, this seems like a good alternative to Java Service Wrapper as has better licensing. It is also intended to be easy to move from JSW to YAJSW. Certainly for me, brand new to windows servers and trying to get a Java app running as a service, it was very easy to use.

Some others I found, but didn’t end up using:

  • Java Service Launcher I didn’t use this because it looked more complicated to get working than YAJSW. I don’t think this is a wrapper.
  • JSmooth Creating Window’s services isn’t its primary goal, but can be done. I didn’t use this because there’s been no activity since 2007.

If you use Gradle Build Tool you can try my windows-service-plugin, which facilitates using of Apache Commons Daemon Procrun.

To create a java windows service application with the plugin you need to go through several simple steps.

Create a main service class with the appropriate method.

Include the plugin into your build.gradle file.

The same script snippet for new, incubating, plugin mechanism introduced in Gradle 2.1:

Configure the plugin.

Run createWindowsService gradle task to create a windows service distribution.

That’s all you need to do to create a simple windows service. The plugin will automatically download Apache Commons Daemon Procrun binaries, extract this binaries to the service distribution directory and create batch files for installation/uninstallation of the service.

In $/windows-service directory you will find service executables, batch scripts for installation/uninstallation of the service and all runtime libraries. To install the service run

-install.bat and if you want to uninstall the service run

-uninstall.bat . To start and stop the service use

Note that the method handling service start should create and start a separate thread to carry out the processing, and then return. The main method is called from different threads when you start and stop the service.

For more information, please read about the plugin and Apache Commons Daemon Procrun.

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