我试图用procrun包装弹簧靴“uber JAR”。
按预期运行以下工作:
java -jar my.jar
我需要弹簧启动jar才能在Windows启动时自动启动。最好的解决方案是将jar作为服务运行(与独立的tomcat相同)。
当我尝试运行此操作时,我收到“Commons Daemon procrun失败并退出值:3”
查看spring-boot源,它看起来好像使用自定义类加载器:
尝试直接运行main方法时,我也得到一个“ClassNotFoundException”。
java -cp my.jar my.MainClass
有没有一种方法可以用来在spring boot jar中运行我的main方法(不是通过JarLauncher)?
有没有人成功将spring-boot与procrun集成?
我知道http://wrapper.tanukisoftware.com/。但是由于他们的许可我不能使用它。
更新
我现在设法使用procrun启动服务。
set SERVICE_NAME=MyService
set BASE_DIR=C:\MyService\Path
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 Files\Java\jre7\bin\java.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),任务管理器中没有提到该进程(不是很好!除非我是盲人)。< / p>
答案 0 :(得分:5)
我遇到了类似的问题,但发现其他人(Francesco Zanutto)非常慷慨地写了一篇关于他们努力的博客文章。 他们的解决方案对我有用。我们没有相信他们实现这段代码的时间。
http://zazos79.blogspot.com/2015/02/spring-boot-12-run-as-windows-service.html
与我在示例中看到的exe模式相比,他正在使用jvm启动和停止模式。有了这个,他就可以扩展Spring Boot的JarLauncher来处理来自Windows服务的“开始”和“停止”命令,我相信你们希望这些命令能够正常关闭。
与他的示例一样,您将添加多个主要方法,具体取决于您的实现,您需要指明启动器现在应该调用哪些方法。我正在使用Gradle,只需将以下内容添加到我的build.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);
}
}
}
我的主要Spring应用程序类:
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);
}
}
}
}
答案 1 :(得分:5)
现在可以使用winsw从Spring Boot 1.3开始。
documentation会将您定向到显示如何设置服务的reference implementation。
答案 2 :(得分:4)
从springboot v1.2.2开始,没有干净的方法可以使用procrun关闭一个打包为超级jar的Spring Boot应用程序。请务必遵循这些问题,因为这也是其他人要问的问题:
目前还不清楚springboot维护者是否会如何处理它。在此期间,考虑解压缩超级jar并忽略Spring Boot的JarLauncher。
我对这个问题的原始答案(在历史中可见)提出了一种应该起作用的方式(我认为这样做了),但不是由于在JarLauncher中如何处理类加载器。
答案 3 :(得分:2)
刚刚遇到这个并希望分享,我一段时间后修复了这个问题并发出了拉取请求。 https://github.com/spring-projects/spring-boot/pull/2520
您可以使用我的分叉版本,直到它合并为使用procrun开始/停止。
答案 4 :(得分:-1)
远离winsw,它是用.NET制作的,我在客户环境中遇到了很多关于过时Windows的问题。
我推荐NSSM,它是使用纯C制作的,我在所有过时的Windows上使用它没有问题。它具有相同的功能和更多...
以下是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\""