Spring boot JAR как служба windows

Я пытаюсь обернуть пружинный ботинок "uber JAR" с procrun.

выполнив следующие работы:

java-jar my.Джар

Мне нужна моя весенняя загрузочная банка для автоматического запуска при загрузке windows. Самым приятным решением для этого было бы запустить jar как службу (такую же, как автономный tomcat).

когда я пытаюсь запустить это, я получаю "Commons Daemon procrun не удалось со значением выхода: 3"

глядя на источник spring-boot выглядит так, как будто он использует пользовательский загрузчик классов:

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/JarLauncher.java

Я также получаю "ClassNotFoundException" при попытке запустить мой основной метод напрямую.

java-cp my.банку мою.MainClass

есть ли метод, который я могу использовать для запустите мой основной метод в весенней загрузочной банке (не через JarLauncher)?

кто-нибудь успешно интегрировал spring-boot с procrun?

Я в курсе http://wrapper.tanukisoftware.com/. Однако из-за их лицензии я не могу использовать его.

обновление

теперь мне удалось запустить службу с помощью procrun.

set SERVICE_NAME=MyService
set BASE_DIR=C:MyServicePath
set PR_INSTALL=%BASE_DIR%prunsrv.exe

REM Service log configuration
set PR_LOGPREFIX=%SERVICE_NAME%
set PR_LOGPATH=%BASE_DIR%
set PR_STDOUTPUT=%BASE_DIR%stdout.txt
set PR_STDERROR=%BASE_DIR%stderr.txt
set PR_LOGLEVEL=Error

REM Path to java installation
set PR_JVM=auto
set PR_CLASSPATH=%BASE_DIR%%SERVICE_NAME%.jar

REM Startup configuration
set PR_STARTUP=auto
set PR_STARTIMAGE=c:Program FilesJavajre7binjava.exe 
set PR_STARTMODE=exe
set PR_STARTPARAMS=-jar#%PR_CLASSPATH%

REM Shutdown configuration
set PR_STOPMODE=java
set PR_STOPCLASS=TODO
set PR_STOPMETHOD=stop

REM JVM configuration
set PR_JVMMS=64
set PR_JVMMX=256

REM Install service
%PR_INSTALL% //IS//%SERVICE_NAME%

теперь мне просто нужно потренироваться, как остановить службу. Я думаю сделать что-нибудь с выключением пружинного привода JMX Bean.

что происходит, когда я останавливаю службу в данный момент; windows не может остановить службу (но отмечает ее как остановленную), служба все еще работает (я могу перейти к localhost), нет упоминания о процессе в диспетчере задач (не очень хорошо! если я не слепой).

5 ответов


я столкнулся с подобными проблемами, но нашел кого-то другого (Франческо Занутто) был достаточно любезен, чтобы написать сообщение в блоге об их усилиях. их решение работает для меня. Я не беру на себя ответственность за время, которое они вложили в реализацию этого кода.

http://zazos79.blogspot.com/2015/02/spring-boot-12-run-as-windows-service.html

Он использует режим запуска и остановки jvm, по сравнению с режимом exe, который я вижу в вашем примере. С этим, он может расширьте JarLauncher Spring Boot для обработки команд" пуск "и" стоп " из служб Windows, которые, я считаю, вы хотите сделать для изящного завершения работы.

как и в его примерах, вы добавите несколько основных методов, в зависимости от вашей реализации, вам нужно будет указать, какой теперь должен быть вызван пусковой установкой. Я использую Gradle и просто должен был добавить следующее к моей сборке.Gradle в:

springBoot{
    mainClass = 'mydomain.app.MyApplication'
}

моя установка Procrun сценарий:

D:\app\prunsrv.exe //IS//MyServiceName ^
--DisplayName="MyServiceDisplayName" ^
--Description="A Java app" ^
--Startup=auto ^
--Install=%CD%\prunsrv.exe ^
--Jvm=%JAVA_HOME%\jre\bin\server\jvm.dll ^
--Classpath=%CD%\SpringBootApp-1.1.0-SNAPSHOT.jar; ^
--StartMode=jvm ^
--StartClass=mydomain.app.Bootstrap ^
--StartMethod=start ^
--StartParams=start ^
--StopMode=jvm ^
--StopClass=mydomain.app.Bootstrap ^
--StopMethod=stop ^
--StopParams=stop ^
--StdOutput=auto ^
--StdError=auto ^
--LogPath=%CD% ^
--LogLevel=Debug

класс расширения JarLauncher:

package mydomain.app;


import org.springframework.boot.loader.JarLauncher;
import org.springframework.boot.loader.jar.JarFile;

public class Bootstrap extends JarLauncher {

    private static ClassLoader classLoader = null;
    private static Bootstrap bootstrap = null;

    protected void launch(String[] args, String mainClass, ClassLoader classLoader, boolean wait)
            throws Exception {
        Runnable runner = createMainMethodRunner(mainClass, args, classLoader);
        Thread runnerThread = new Thread(runner);
        runnerThread.setContextClassLoader(classLoader);
        runnerThread.setName(Thread.currentThread().getName());
        runnerThread.start();
        if (wait == true) {
            runnerThread.join();
        }
    }

    public static void start (String []args) {
        bootstrap = new Bootstrap ();
        try {
            JarFile.registerUrlProtocolHandler();
            classLoader = bootstrap.createClassLoader(bootstrap.getClassPathArchives());
            bootstrap.launch(args, bootstrap.getMainClass(), classLoader, true);
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    public static void stop (String []args) {
        try {
            if (bootstrap != null) {
                bootstrap.launch(args, bootstrap.getMainClass(), classLoader, true);
                bootstrap = null;
                classLoader = null;
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    public static void main(String[] args) {
        String mode = args != null && args.length > 0 ? args[0] : null;
        if ("start".equals(mode)) {
            Bootstrap.start(args);
        }
        else if ("stop".equals(mode)) {
            Bootstrap.stop(args);
        }
    }

}

мой основной класс весеннего приложения:

package mydomain.app;

import java.lang.management.ManagementFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan
@EnableAutoConfiguration
public class MyApplication {

    private static final Logger logger = LoggerFactory.getLogger(MyApplication.class);
    private static ApplicationContext applicationContext = null;

    public static void main(String[] args) {
        String mode = args != null && args.length > 0 ? args[0] : null;

        if (logger.isDebugEnabled()) {
            logger.debug("PID:" + ManagementFactory.getRuntimeMXBean().getName() + " Application mode:" + mode + " context:" + applicationContext);
        }
        if (applicationContext != null && mode != null && "stop".equals(mode)) {
            System.exit(SpringApplication.exit(applicationContext, new ExitCodeGenerator() {
                @Override
                public int getExitCode() {
                    return 0;
                }
            }));
        }
        else {
            SpringApplication app = new SpringApplication(MyApplication.class);
            applicationContext = app.run(args);
            if (logger.isDebugEnabled()) {
                logger.debug("PID:" + ManagementFactory.getRuntimeMXBean().getName() + " Application started context:" + applicationContext);
            }
        }
    }
}

теперь это возможно с Spring Boot 1.3 с помощью winsw.

на документация направляет вам эталонной реализации, который показывает, как настроить сервис.


по состоянию на springboot v1.2.2 нет чистого способа завершения работы приложения Spring Boot, упакованного в виде Uber jar, с помощью procrun. Обязательно следуйте этим вопросам, так как это то, о чем спрашивают другие:

неясно, если / как springboot сопровождающие собираются справиться с этим. Тем временем, подумайте о том, чтобы расстегнуть банку uber и игнорировать JarLauncher Spring Boot.

мой оригинальный ответ на этот вопрос (в истории) предложил способ, который должен работать (и я думал, что сделал), но не из-за того, как загрузчик классов осуществляется в JarLauncher.


просто столкнулся с этим и хотел поделиться, я исправила эту проблему некоторое время назад и выдал запрос. https://github.com/spring-projects/spring-boot/pull/2520

вы можете использовать мою раздвоенную версию, пока она не будет объединена для запуска / остановки с помощью procrun.


держись подальше от winsw, это сделано с .NET, и я испытываю много проблем с моей средой клиентов о устаревших окнах.

рекомендую NSSM, это сделано с использованием чистого C, и я использовал его на всех моих устаревших окнах без проблем. Он имеет те же особенности и многое другое...

здесь batch script (.bat) пример использования:

rem Register the service
nssm install my-java-service "C:\Program Files\Java\jre1.8.0_152\bin\java.exe" "-jar" "snapshot.jar"
rem Set the service working dir
nssm set my-java-service AppDirectory "c:\path\to\jar-diretory"
rem Redirect sysout to file
nssm set my-java-service AppStdout "c:\path\to\jar-diretory\my-java-service.out"
rem Redirect syserr to file
nssm set my-java-service AppStderr "c:\path\to\jar-diretory\my-java-service.err"
rem Enable redirection files rotation
nssm set my-java-service AppRotateFiles 1
rem Rotate files while service is running
nssm set my-java-service AppRotateOnline 1
rem Rotate files when they reach 10MB
nssm set my-java-service AppRotateBytes 10485760
rem Stop service when my-java-service exits/stop
nssm set my-java-service AppExit Default Exit
rem Restart service when my-java-service exits with code 2 (self-update)
nssm set my-java-service AppExit 2 Restart
rem Set the display name for the service
nssm set my-java-service DisplayName "My JAVA Service"
rem Set the description for the service
nssm set my-java-service Description "Your Corp"
rem Remove old rotated files (older than 30 days)
nssm set my-java-service AppEvents Rotate/Pre "cmd /c forfiles /p \"c:\path\to\jar-diretory\" /s /m \"my-java-service-*.*\" /d -30 /c \"cmd /c del /q /f @path\""
rem Make a copy of my-java-service.jar to snapshot.jar to leave the original JAR unlocked (for self-update purposes)
nssm set my-java-service AppEvents Start/Pre "cmd /c copy /y \"c:\path\to\jar-diretory\my-java-service.jar\" \"c:\path\to\jar-diretory\snapshot.jar\""