有时候我们希望我们java写的程序作为服务注册到系统中,Java Service Wrapper(下面简称wrapper)是目前较为流行的将Java程序部署成Windows服务的解决方案, 本文将讨论如何使用wrapper把我们的程序打包成WIN服务! 

主要作用有:

  1.打包服务

  2.设置JVM参数

  3.所有的日志可以输出到指定文件

0.准备需要注册为服务的程序

public class MapTest {private static int i;public static void main(String[] args) {while (true) {try {System.out.println("访问次数:" + i++);HttpUtil.doGet("http://www.cnblogs.com/qlqwjy/");Thread.sleep(2 * 1000);} catch (InterruptedException e) {e.printStackTrace();}}}}

上面程序依赖的jar包:

将上面程序也打成包:(使用eclipse打包或者直接Jdk自带的jar打包)

  

1.下载serviceWrapper包

  下载地址:http://qiaoliqiang.cn/fileDown/wrapper-windows-x86-32-3.5.25.zip

下载后是一个压缩包,解压目录如下:

2.开始注册一个简单的服务:

1. 准备一个目录,例如我在桌面建了一个SW目录,并在里面新建如下结构的目录:   接下来全文的%EXAMPLE_HOME%  就是我新建的SW目录名称

%EXAMPLE_HOME%\
%EXAMPLE_HOME%\bin\
%EXAMPLE_HOME%\conf\
%EXAMPLE_HOME%\lang\
%EXAMPLE_HOME%\lib\
%EXAMPLE_HOME%\mylib\
%EXAMPLE_HOME%\logs\

如下:lang目录是存放支持其他语言的语言包,一般用不到

2.   然后将我们下载的wrapper目录下的文件拷贝到我们上面建的目录:

%WRAPPER_HOME%\bin\wrapper.exe -> %EXAMPLE_HOME%\bin\wrapper.exe
%WRAPPER_HOME%\lib\wrapper.jar -> %EXAMPLE_HOME%\lib\wrapper.jar
%WRAPPER_HOME%\lib\wrapper.dll -> %EXAMPLE_HOME%\lib\wrapper.dll
%WRAPPER_HOME%\conf\wrapper.conf -> %EXAMPLE_HOME%\conf\wrapper.conf

将自己程序打成的包以及自己程序依赖的包放到mylib:

3.修改配置文件    %EXAMPLE_HOME%\conf\wrapper.conf

#java.exe所在位置wrapper.java.command=C:\Program Files\Java\jdk1.7.0_80\bin\java.exe#日志级别
wrapper.java.command.loglevel=INFO
#主类入口,第一个mainClass是固定写法,是wrapper自带的,不可以写成自己的,如果写成自己的入口程序自己的程序需要实现wrapper的WrapperListener接口#parameter.1是自己的主程序入口所在类(从包名开始)
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
wrapper.app.parameter.1=MapTest
#依赖的包,第一个是wrapper包,第二个是自己打的包以及程序依赖包
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.2=../mylib/*.jar
#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib
#日志文件位置
wrapper.logfile=../logs/wrapper.log
#服务名称以及描述信息
wrapper.console.title=Hello World Server
wrapper.name=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Server

注意:

  (1)上面的主类实际是:org.tanukisoftware.wrapper.WrapperSimpleApp,此类实现了WrapperListener接口。所以如果我们用此参数定义自己的主函数需要实现此接口。实现此接口就不用wrapper.app.parameter.1作为函数参数了

  (2)wrapper.app.parameter.1=MapTest  是将Maptest作为参数传入到主函数中,也就是依次作为类WrapperSimpleApp的main(String[] args)函数的参数。源码如下:

  (3)不能一次传多个参数,生效的始终是第一个参数,传第二个参数也不会生效。传第二个参数或者多个参数是作为MapTest的主函数的参数。
package org.tanukisoftware.wrapper;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.tanukisoftware.wrapper.WrapperListener;
import org.tanukisoftware.wrapper.WrapperManager;
import org.tanukisoftware.wrapper.WrapperPrintStream;
import org.tanukisoftware.wrapper.WrapperSystemPropertyUtil;public class WrapperSimpleApp implements WrapperListener, Runnable {private static WrapperPrintStream m_outInfo;private static WrapperPrintStream m_outError;private static WrapperPrintStream m_outDebug;private Method m_mainMethod;private String[] m_appArgs;private boolean m_mainStarted;private boolean m_mainComplete;private Integer m_mainExitCode;private boolean m_ignoreMainExceptions;private boolean m_startComplete;protected WrapperSimpleApp(String[] args) {if (class$org$tanukisoftware$wrapper$WrapperManager == null) {class$org$tanukisoftware$wrapper$WrapperManager = class$("org.tanukisoftware.wrapper.WrapperManager");} else {Class arg9999 = class$org$tanukisoftware$wrapper$WrapperManager;}this.m_mainMethod = null;m_outInfo = new WrapperPrintStream(System.out, "WrapperSimpleApp: ");m_outError = new WrapperPrintStream(System.out, "WrapperSimpleApp Error: ");m_outDebug = new WrapperPrintStream(System.out, "WrapperSimpleApp Debug: ");if (args.length < 1) {this.showUsage();WrapperManager.stop(1);} else {String mainClassString = args[0];String mainMethodString = "main";String[] ar = args[0].split("/");if (ar.length > 1) {mainClassString = ar[0];mainMethodString = ar[1];}Class mainClass;try {mainClass = Class.forName(mainClassString);} catch (ClassNotFoundException arg11) {m_outError.println(WrapperManager.getRes().getString("Unable to locate the class {0} : {1}",mainClassString, arg11));this.showUsage();WrapperManager.stop(1);return;} catch (ExceptionInInitializerError arg12) {m_outError.println(WrapperManager.getRes().getString("Class {0} found but could not be initialized due to:", mainClassString));arg12.printStackTrace(m_outError);WrapperManager.stop(1);return;} catch (LinkageError arg13) {m_outError.println(WrapperManager.getRes().getString("Class {0} found but could not be initialized: {1}", mainClassString, arg13));WrapperManager.stop(1);return;}try {this.m_mainMethod = mainClass.getMethod(mainMethodString, new Class[]{String[].class});} catch (NoSuchMethodException arg9) {try {this.m_mainMethod = mainClass.getMethod(mainMethodString, new Class[0]);} catch (NoSuchMethodException arg8) {;}if (this.m_mainMethod == null) {m_outError.println(WrapperManager.getRes().getString("Unable to locate a public static {2} method in class {0} : {1}", mainClassString, arg9,mainMethodString));this.showUsage();WrapperManager.stop(1);return;}} catch (SecurityException arg10) {m_outError.println(WrapperManager.getRes().getString("Unable to locate a public static {2} method in class {0} : {1}", mainClassString, arg10,mainMethodString));this.showUsage();WrapperManager.stop(1);return;}int modifiers = this.m_mainMethod.getModifiers();if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {String[] appArgs = new String[args.length - 1];System.arraycopy(args, 1, appArgs, 0, appArgs.length);WrapperManager.start(this, appArgs);} else {m_outError.println(WrapperManager.getRes().getString("The {1} method in class {0} must be declared public and static.", mainClassString,mainMethodString));this.showUsage();WrapperManager.stop(1);}}}public void run() {synchronized (this) {this.m_mainStarted = true;this.notifyAll();}Object t = null;try {if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("invoking main method"));}try {this.m_mainMethod.invoke((Object) null, new Object[]{this.m_appArgs});} catch (IllegalArgumentException arg15) {this.m_mainMethod.invoke((Object) null, new Object[0]);} finally {Thread.currentThread().setPriority(10);}if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("main method completed"));}synchronized (this) {this.m_mainComplete = true;this.notifyAll();return;}} catch (IllegalAccessException arg18) {t = arg18;} catch (IllegalArgumentException arg19) {t = arg19;} catch (InvocationTargetException arg20) {t = arg20.getTargetException();if (t == null) {t = arg20;}}m_outInfo.println();m_outError.println(WrapperManager.getRes().getString("Encountered an error running main:"));((Throwable) t).printStackTrace(m_outError);synchronized (this) {if (this.m_ignoreMainExceptions) {if (!this.m_startComplete) {this.m_mainComplete = true;this.notifyAll();}} else if (this.m_startComplete) {WrapperManager.stop(1);} else {this.m_mainComplete = true;this.m_mainExitCode = new Integer(1);this.notifyAll();}}}public Integer start(String[] args) {boolean waitForStartMain = WrapperSystemPropertyUtil.getBooleanProperty(WrapperSimpleApp.class.getName() + ".waitForStartMain", false);this.m_ignoreMainExceptions = WrapperSystemPropertyUtil.getBooleanProperty(WrapperSimpleApp.class.getName() + ".ignoreMainExceptions", false);int maxStartMainWait = WrapperSystemPropertyUtil.getIntProperty(WrapperSimpleApp.class.getName() + ".maxStartMainWait", 2);maxStartMainWait = Math.max(1, maxStartMainWait);int maxLoops;if (waitForStartMain) {maxLoops = Integer.MAX_VALUE;if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("start(args) Will wait indefinitely for the main method to complete."));}} else {maxLoops = maxStartMainWait;if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("start(args) Will wait up to {0} seconds for the main method to complete.",new Integer(maxStartMainWait)));}}Thread mainThread = new Thread(this, "WrapperSimpleAppMain");synchronized (this) {this.m_appArgs = args;mainThread.start();Thread.currentThread().setPriority(10);while (!this.m_mainStarted) {try {this.wait(1000L);} catch (InterruptedException arg10) {;}}for (int loops = 0; loops < maxLoops && !this.m_mainComplete; ++loops) {try {this.wait(1000L);} catch (InterruptedException arg9) {;}if (!this.m_mainComplete) {WrapperManager.signalStarting(5000);}}this.m_startComplete = true;if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("start(args) end.  Main Completed={0}, exitCode={1}",new Boolean(this.m_mainComplete), this.m_mainExitCode));}return this.m_mainExitCode;}}public int stop(int exitCode) {if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("stop({0})", new Integer(exitCode)));}return exitCode;}public void controlEvent(int event) {if (event != 202 || !WrapperManager.isLaunchedAsService() && !WrapperManager.isIgnoreUserLogoffs()) {if (WrapperManager.isDebugEnabled()) {m_outDebug.println(WrapperManager.getRes().getString("controlEvent({0}) Stopping", new Integer(event)));}WrapperManager.stop(0);} else {m_outInfo.println(WrapperManager.getRes().getString("User logged out.  Ignored."));}}protected void showUsage() {System.out.println();System.out.println(WrapperManager.getRes().getString("WrapperSimpleApp Usage:"));System.out.println(WrapperManager.getRes().getString("  java org.tanukisoftware.wrapper.WrapperSimpleApp {app_class{/app_method}} [app_arguments]"));System.out.println();System.out.println(WrapperManager.getRes().getString("Where:"));System.out.println(WrapperManager.getRes().getString("  app_class:      The fully qualified class name of the application to run."));System.out.println(WrapperManager.getRes().getString("  app_arguments:  The arguments that would normally be passed to the"));System.out.println(WrapperManager.getRes().getString("                  application."));}public static void main(String[] args) {new WrapperSimpleApp(args);}
}

 

4.开始注册服务以及测试

(1)控制台测试

C:\Users\Administrator>cd C:\Users\Administrator\Desktop\SWC:\Users\Administrator\Desktop\SW>bin\wrapper.exe -c ..\conf\wrapper.conf
wrapper  | --> Wrapper Started as Console
wrapper  | Java Service Wrapper Community Edition 32-bit 3.5.25
wrapper  |   Copyright (C) 1999-2014 Tanuki Software, Ltd. All Rights Reserved.
wrapper  |     http://wrapper.tanukisoftware.com
wrapper  |
wrapper  | Launching a JVM...
wrapper  | Java Command Line:
wrapper  |   Command: "C:\Program Files\Java\jdk1.7.0_80\bin\java.exe" -Djava.library.path="../lib" -classpath "../lib/wrapper.jar;../mylib/commons-logging-1.0.4.jar;../mylib/commons.jar;../mylib/httpclient-4.3.1.jar;../mylib/httpcore-4.3.jar;../mylib/httpmime-4.3.1.jar;../mylib/log4j-1.2.12.jar" -Dwrapper.key="2azws1iyaXYR9r26" -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=21292 -Dwrapper.version="3.5.25" -Dwrapper.native_library="wrapper" -Dwrapper.arch="x86" -Dwrapper.cpu.timeout="10" -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp MapTest
jvm 1    | WrapperManager: Initializing...
jvm 1    | WrapperManager:
jvm 1    | WrapperManager: WARNING - Unable to load the Wrapper''s native library 'wrapper.dll'.
jvm 1    | WrapperManager:           The file is located on the path at the following location but
jvm 1    | WrapperManager:           could not be loaded:
jvm 1    | WrapperManager:             C:\Users\Administrator\Desktop\SW\bin\..\lib\wrapper.dll
jvm 1    | WrapperManager:           Please verify that the file is both readable and executable by the
jvm 1    | WrapperManager:           current user and that the file has not been corrupted in any way.
jvm 1    | WrapperManager:           One common cause of this problem is running a 32-bit version
jvm 1    | WrapperManager:           of the Wrapper with a 64-bit version of Java, or vica versa.
jvm 1    | WrapperManager:           This is a 64-bit JVM.
jvm 1    | WrapperManager:           Reported cause:
jvm 1    | WrapperManager:             C:\Users\Administrator\Desktop\SW\lib\wrapper.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
jvm 1    | WrapperManager:           System signals will not be handled correctly.
jvm 1    | WrapperManager:
jvm 1    | 访问次数:0
jvm 1    | log4j:WARN No appenders could be found for logger (org.apache.http.impl.conn.BasicClientConnectionManager).
jvm 1    | log4j:WARN Please initialize the log4j system properly.
jvm 1    | 访问次数:1
jvm 1    | 访问次数:2
jvm 1    | 访问次数:3

(2)将程序注册为服务:

bin\wrapper.exe -i ..\conf\wrapper.conf

结果:

wrapper  | Hello World Server service installed.

(3)启动服务:

net start helloworld

或者:

bin\wrapper.exe -t ..\conf\wrapper.conf

启动之后我们回看到程序输出在logs\wrapper.log文件内:

(4)停止服务

net stop helloword

或者

bin\wrapper.exe -p ..\conf\wrapper.conf

(5)删除服务

sc delete helloword

或者

bin\wrapper.exe -r ..\conf\wrapper.conf

-----------上面是在系统有Java环境的情况下的设置,现在假设我们不存在Java运行环境,也就是没有JRE与JDK:-------------

(1)拷贝java安装目录下的JRE(包含bin目录和相关lib)目录到上面的目录%EXAMPLE_HOME%,如下:

jre目录下:

(2)修改配置文件,利用我们上面的jre目录下的jar包和bin\java.exe

#java.exe所在位置
wrapper.java.command=../jre/bin/java.exe
#日志级别
wrapper.java.command.loglevel=INFO#主类入口,第一个mainClass是固定写法,是wrapper自带的,不可以写成自己的,如果写成自己的入口程序自己的程序需要实现wrapper的WrapperListener接口
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
#parameter.1是自己的主程序入口所在类(从包名开始)
wrapper.app.parameter.1=MapTest#依赖的包,第一个是wrapper包,第二个是自己打的包以及程序依赖包
wrapper.java.classpath.1=../jre/lib/*.jar
wrapper.java.classpath.2=../lib/wrapper.jar
wrapper.java.classpath.3=../mylib/*.jar#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib#日志文件位置
wrapper.logfile=../logs/wrapper.log#服务名称以及描述信息
wrapper.console.title=Hello World Server
wrapper.name=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Server

(3)安装服务与测试与上面一样:

C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -c ..\conf\wrapper.conf
wrapper  | --> Wrapper Started as Console
wrapper  | Java Service Wrapper Community Edition 32-bit 3.5.25
wrapper  |   Copyright (C) 1999-2014 Tanuki Software, Ltd. All Rights Reserved.
wrapper  |     http://wrapper.tanukisoftware.com
wrapper  |
wrapper  | Launching a JVM...
wrapper  | Java Command Line:
wrapper  |   Command: "..\jre\bin\java.exe" -Djava.library.path="../lib" -classp
arsets.jar;../jre/lib/deploy.jar;../jre/lib/javaws.jar;../jre/lib/jce.jar;../jre
/lib/jsse.jar;../jre/lib/management-agent.jar;../jre/lib/plugin.jar;../jre/lib/r
apper.jar;../mylib/commons-logging-1.0.4.jar;../mylib/commons.jar;../mylib/httpc
r;../mylib/httpmime-4.3.1.jar;../mylib/log4j-1.2.12.jar" -Dwrapper.key="408rjGp1
.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=336144 -Dwrapper.
y="wrapper" -Dwrapper.arch="x86" -Dwrapper.cpu.timeout="10" -Dwrapper.jvmid=1 or
p MapTest
jvm 1    | WrapperManager: Initializing...
jvm 1    | WrapperManager:
jvm 1    | WrapperManager: WARNING - Unable to load the Wrapper''s native librar
jvm 1    | WrapperManager:           The file is located on the path at the foll
jvm 1    | WrapperManager:           could not be loaded:
jvm 1    | WrapperManager:             C:\Users\liqiang\Desktop\xxx\SW\bin\..\li
jvm 1    | WrapperManager:           Please verify that the file is both readabl
jvm 1    | WrapperManager:           current user and that the file has not been
jvm 1    | WrapperManager:           One common cause of this problem is running
jvm 1    | WrapperManager:           of the Wrapper with a 64-bit version of Jav
jvm 1    | WrapperManager:           This is a 64-bit JVM.
jvm 1    | WrapperManager:           Reported cause:
jvm 1    | WrapperManager:             C:\Users\liqiang\Desktop\xxx\SW\lib\wrapp
MD 64-bit platform
jvm 1    | WrapperManager:           System signals will not be handled correctl
jvm 1    | WrapperManager:
jvm 1    | 访问次数:0
jvm 1    | log4j:WARN No appenders could be found for logger (org.apache.http.im
jvm 1    | log4j:WARN Please initialize the log4j system properly.
jvm 1    | 访问次数:1
wrapper  | CTRL-C trapped.  Shutting down.
wrapper  | <-- Wrapper StoppedC:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -i ..\conf\wrapper.conf
wrapperm | Hello World Server service installed.C:\Users\liqiang\Desktop\xxx\SW>java
'java' 不是内部或外部命令,也不是可运行的程序
或批处理文件。C:\Users\liqiang\Desktop\xxx\SW>javac
'javac' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

  为了验证我们的服务是使用的jre目录下的JDK,我们可以将jre目录删掉进行测试,或者是将配置文件中jre\lib的引入注释掉进行测试。

  现在我们将jre目录删掉,启动服务报错如下:

  在wrapper.log中查看到的日志文件如下:

 

  至此我们实现了简单的有JRE与无JRE两种情况的注册服务,实际没有JRE环境的时候我们只需要将我们的JRE附到目录中并且在wrapper.conf中指明所在路径即可。

补充1.:上面配置会导致JVM不断重启,需要加JVM参数以及设置,同时设置服务开机启动:并且使用一变量记住我们的项目路径;修改wrapper.conf并且删掉服务重新添加:

#定义了一个根路径,注意set和.之间没有空格,下面就可以用%basePath%取此变量
set.basePath=C:\Users\liqiang\Desktop\xxx\SW#java.exe所在位置
wrapper.java.command=%basePath%/jre/bin/java.exe
#日志级别
wrapper.java.command.loglevel=INFO#主类入口,第一个mainClass是固定写法,是wrapper自带的,不可以写成自己的,如果写成自己的入口程序自己的程序需要实现wrapper的WrapperListener接口
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
#parameter.1是自己的主程序入口所在类(从包名开始)
wrapper.app.parameter.1=MapTest#依赖的包,第一个是wrapper包,第二个是自己打的包以及程序依赖包
wrapper.java.classpath.1=../jre/lib/*.jar
wrapper.java.classpath.2=../lib/wrapper.jar
wrapper.java.classpath.3=../mylib/*.jar#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib#日志文件位置
wrapper.logfile=../logs/wrapper.log#服务名称以及描述信息
wrapper.console.title=Hello World Server
wrapper.name=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Serverwrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTARTwrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = truewrapper.java.monitor.deadlock = true
wrapper.java.monitor.heap = true
wrapper.java.monitor.gc.restart = true# Java Heap 初始化大小(单位:MB)
wrapper.java.initmemory=128
# Java Heap 最大值(单位:MB)
wrapper.java.maxmemory=128

删除重装服务:

C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -r ..\conf\wrapper.conf
wrapperm | Hello World Server service removed.

C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -c ..\conf\wrapper.conf
wrapper  | --> Wrapper Started as Console
wrapper  | Java Service Wrapper Community Edition 32-bit 3.5.25
wrapper  |   Copyright (C) 1999-2014 Tanuki Software, Ltd. All Rights Reserved.
wrapper  |     http://wrapper.tanukisoftware.com
wrapper  |
wrapper  | Launching a JVM...
wrapper  | Java Command Line:
wrapper  |   Command: "C:\Users\liqiang\Desktop\xxx\SW\jre\bin\java.exe" -Xms128
-classpath "../jre/lib/alt-rt.jar;../jre/lib/charsets.jar;../jre/lib/deploy.jar;
;../jre/lib/jfr.jar;../jre/lib/jfxrt.jar;../jre/lib/jsse.jar;../jre/lib/manageme
e/lib/resources.jar;../jre/lib/rt.jar;../lib/wrapper.jar;../mylib/commons-loggin
b/httpclient-4.3.1.jar;../mylib/httpcore-4.3.jar;../mylib/httpmime-4.3.1.jar;../
P7sqJIaMu25Avke" -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm
rapper.version="3.5.25" -Dwrapper.native_library="wrapper" -Dwrapper.arch="x86"
id=1 org.tanukisoftware.wrapper.WrapperSimpleApp MapTest
jvm 1    | WrapperManager: Initializing...
jvm 1    | WrapperManager:
jvm 1    | WrapperManager: WARNING - Unable to load the Wrapper''s native librar
jvm 1    | WrapperManager:           The file is located on the path at the foll
jvm 1    | WrapperManager:           could not be loaded:
jvm 1    | WrapperManager:             C:\Users\liqiang\Desktop\xxx\SW\bin\..\li
jvm 1    | WrapperManager:           Please verify that the file is both readabl
jvm 1    | WrapperManager:           current user and that the file has not been
jvm 1    | WrapperManager:           One common cause of this problem is running
jvm 1    | WrapperManager:           of the Wrapper with a 64-bit version of Jav
jvm 1    | WrapperManager:           This is a 64-bit JVM.
jvm 1    | WrapperManager:           Reported cause:
jvm 1    | WrapperManager:             C:\Users\liqiang\Desktop\xxx\SW\lib\wrapp
MD 64-bit platform
jvm 1    | WrapperManager:           System signals will not be handled correctl
jvm 1    | WrapperManager:
jvm 1    | 访问次数:0
wrapper  | CTRL-C trapped.  Shutting down.
jvm 1    | log4j:WARN No appenders could be found for logger (org.apache.http.im
jvm 1    | log4j:WARN Please initialize the log4j system properly.
wrapper  | <-- Wrapper StoppedC:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -i ..\conf\wrapper.conf
wrapperm | Hello World Server service installed.

如果我们想检测JVM参数可以用jps+jmap监测即可:

C:\Users\liqiang>jps
505668 Jps
504320 WrapperSimpleApp
487768C:\Users\liqiang>jmap -heap 504320
Attaching to process ID 504320, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11using thread-local object allocation.
Parallel GC with 4 thread(s)Heap Configuration:MinHeapFreeRatio = 0MaxHeapFreeRatio = 100MaxHeapSize      = 134217728 (128.0MB)NewSize          = 1310720 (1.25MB)MaxNewSize       = 17592186044415 MBOldSize          = 5439488 (5.1875MB)NewRatio         = 2SurvivorRatio    = 8PermSize         = 21757952 (20.75MB)MaxPermSize      = 85983232 (82.0MB)G1HeapRegionSize = 0 (0.0MB)Heap Usage:
PS Young Generation
Eden Space:capacity = 34603008 (33.0MB)used     = 9710016 (9.26019287109375MB)free     = 24892992 (23.73980712890625MB)28.06119051846591% used
From Space:capacity = 5242880 (5.0MB)used     = 0 (0.0MB)free     = 5242880 (5.0MB)0.0% used
To Space:capacity = 5242880 (5.0MB)used     = 0 (0.0MB)free     = 5242880 (5.0MB)0.0% used
PS Old Generationcapacity = 89653248 (85.5MB)used     = 0 (0.0MB)free     = 89653248 (85.5MB)0.0% used
PS Perm Generationcapacity = 22020096 (21.0MB)used     = 6630336 (6.32318115234375MB)free     = 15389760 (14.67681884765625MB)30.110386439732142% used3336 interned Strings occupying 269976 bytes.

补充2:我们可以用上面的service wrapper的bin包中的bat文件进行安装服务: (将上面安下载解压后的wrapper-windows-x86-32-3.5.25\bin中的文件复制到我们的%EXAMPLE_HOME%\bin目录下)

  我们只需要点击上面的bat文件即可实现上面的操作。

*************************

我已经将我的一个例子上传到我的服务器,下载地址:http://qiaoliqiang.cn/fileDown/serviceWrapperExample.zip

下载解压之后只需要将自己程序打的包以及依赖包放到mylib目录下,修改conf\wrapper.conf文件中下面两处

set.basePath=C:\Users\liqiang\Desktop\xxx\SW   #替换为自己的目录

#parameter.1是自己的主程序入口所在类(从包名开始)
wrapper.app.parameter.1=MapTest   #替换为自己的程序入口

然后点击bin目录的TestWrapper.bat测试即可

**************************

3.将log4j日志与servicewrapper日志进行整合

开发环境下一切正常。用JavaServiceWrapper部署到服务器上之后,发现log文件没有生成。同时在wrapper的log中有两行log4j的错误信息:

log4j:WARN No appenders could be found for logger (com.xxxxx).

log4j:WARN Please initialize the log4j system properly.

查找了一番,最后发现在wrapper.conf中加入一行,硬性指明log4j的配置文件就OK了:

 wrapper.java.additional.1=-Dlog4j.configuration=file:../conf/log4j.properties

StackOverflow上有人回答类似的问题,用的方法是

wrapper.java.additional.1=-Dlog4j.configuration=../config/log4j.properties

但是我这样测试没成功。不知道是不是和版本有关。

(1) 测试代码:

package serviceWrapper;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class MapTest {private static Logger log = LoggerFactory.getLogger(MapTest.class);public static void main(String[] args) {int times = 0;while (true) {try {Thread.sleep(3 * 1000);} catch (InterruptedException e) {}try {int i = 1 / 0;} catch (Exception e) {log.error("error[{}] by / 0 ", times++, e);}}}}

(2)测试代码打成包并一起复制到mylib目录下:

依赖的jar包以及自己打的包:

(3)目录结构:

(4)bin目录与上面一样,jre也一样,lang也一样,lib也一样,logs也一样,mylib在(2)中换过,将log4j.properties文件复制到conf目录下:

log4j.properties文件:

log4j.rootLogger=info,A,Blog4j.appender.A=org.apache.log4j.ConsoleAppender
log4j.appender.A.layout=org.apache.log4j.PatternLayout
log4j.appender.A.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%nlog4j.appender.B=org.apache.log4j.RollingFileAppender
log4j.appender.B.File=E:\\test.log
log4j.appender.B.MaxFileSize=10MB
log4j.appender.B.MaxBackupIndex=5
log4j.appender.B.layout=org.apache.log4j.PatternLayout
log4j.appender.B.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n

(5)修改wrapper.conf文件:

#定义了一个根路径,注意set和.之间没有空格,下面就可以用%basePath%取此变量
set.basePath=C:\Users\liqiang\Desktop\logTest#java.exe所在位置
wrapper.java.command=%basePath%/jre/bin/java.exe#主类入口,第一个mainClass是固定写法,是wrapper自带的,不可以写成自己的,如果写成自己的入口程序自己的程序需要实现wrapper的WrapperListener接口
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
#parameter.1是自己的主程序入口所在类(从包名开始),生效的始终是第一个参数
wrapper.app.parameter.1=serviceWrapper.MapTest
wrapper.app.parameter.2=MapTest# Java Classpath配置,必须从序号"1"开始,添加新的jar包后序号递增
#JRE的包
wrapper.java.classpath.1=../jre/lib/*.jar
#wrapper.jar
wrapper.java.classpath.2=../lib/wrapper.jar
#自己的包以及程序依赖包
wrapper.java.classpath.3=../mylib/*.jar#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=%basePath%/lib#日志文件位置
wrapper.logfile=../logs/wrapper.log
# 控制台信息输出格式
wrapper.console.format=PM
# 日志文件输出格式
wrapper.logfile.format=LPTM
# 日志文件日志级别
wrapper.logfile.loglevel=INFO#服务名称以及描述信息
wrapper.console.title=Hello World Server
wrapper.name=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Serverwrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTARTwrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = truewrapper.java.monitor.deadlock = true
wrapper.java.monitor.heap = true
wrapper.java.monitor.gc.restart = true# Java Heap 初始化大小(单位:MB)
wrapper.java.initmemory=128
# Java Heap 最大值(单位:MB)
wrapper.java.maxmemory=128# 32/64位选择,true为自动选择
wrapper.java.additional.auto_bits=TRUE#附加参数即为java命令可选参数,如下所示:
#设置log4J日志文件位置
wrapper.java.additional.1=-Dlog4j.configuration=file:../conf/log4j.properties

注意:  附加参数 wrapper.java.additional.1 即为java命令可选参数(可用于指定JVM参数与指定垃圾收集器组合),如下所示:

C:\Users\liqiang>java
用法: java [-options] class [args...](执行类)或  java [-options] -jar jarfile [args...](执行 jar 文件)
其中选项包括:-d32          使用 32 位数据模型 (如果可用)-d64          使用 64 位数据模型 (如果可用)-server       选择 "server" VM-hotspot      是 "server" VM 的同义词 [已过时]默认 VM 是 server.-cp <目录和 zip/jar 文件的类搜索路径>-classpath <目录和 zip/jar 文件的类搜索路径>用 ; 分隔的目录, JAR 档案和 ZIP 档案列表, 用于搜索类文件。-D<名称>=<值>设置系统属性-verbose:[class|gc|jni]启用详细输出-version      输出产品版本并退出-version:<值>需要指定的版本才能运行-showversion  输出产品版本并继续-jre-restrict-search | -no-jre-restrict-search在版本搜索中包括/排除用户专用 JRE-? -help      输出此帮助消息-X            输出非标准选项的帮助-ea[:<packagename>...|:<classname>]-enableassertions[:<packagename>...|:<classname>]按指定的粒度启用断言-da[:<packagename>...|:<classname>]-disableassertions[:<packagename>...|:<classname>]禁用具有指定粒度的断言-esa | -enablesystemassertions启用系统断言-dsa | -disablesystemassertions禁用系统断言-agentlib:<libname>[=<选项>]加载本机代理库 <libname>, 例如 -agentlib:hprof另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help-agentpath:<pathname>[=<选项>]按完整路径名加载本机代理库-javaagent:<jarpath>[=<选项>]加载 Java 编程语言代理, 请参阅 java.lang.instrument-splash:<imagepath>使用指定的图像显示启动屏幕
有关详细信息, 请参阅 http://www.oracle.com/technetwork/java/javase/documentation

(6)点击bin目录下的TestWrapper.bat测试控制台:

logs\wrapper.log文件内容如下:

E:\test.log文件内容如下:

  log4j生成的日志文件与wrapper.logs文件的内容几乎一样,只是格式不一样。

  至此完成与log4j的整合,其实与log4j整合也简单,就是在配置文件下面加一行引入log4j.properties文件的位置

wrapper.java.additional.1=-Dlog4j.configuration=file:../conf/log4j.properties

4.将tomcat注册为服务:设置tomcat服务开机启动,还是在没有JRE的环境下进行:(公司集成部署系统可以采用这种方式)

1.新建一目录,解压一个全新的tomcat,在%TOMCAT%目录下新建一个servicewrapper目录:

2.将自己的项目解压之后放在webapps目录下(这里采用目录解压部署,参考:https://www.cnblogs.com/qlqwjy/p/9478649.html)

3.与上面部署一样将所需要的文件拷贝到servicewrapper目录下:

  bin目录是启动服务的bat文件和wrapper.exe文件,conf是wrapper.conf文件,jre是拷贝的jre环境,lang是空目录,lib是wrapper.jar和wrapper.dll文件,logs用于存放wrapper.log文件,mylib可以存放自己以及第三方jar包(不过web项目用不到这个)。

4.修改wrapper.conf文件的配置:(重要)

#定义了一个根路径,注意set和.之间没有空格,下面就可以用%basePath%取此变量
set.basePath=C:\Users\liqiang\Desktop\n2\tomcat\apache-tomcat-7.0.72#java.exe所在位置
wrapper.java.command=%basePath%/servicewrapper/jre/bin/java.exe
#日志级别
wrapper.java.command.loglevel=INFO#依赖的包,第一个是wrapper包,第二个是自己打的包以及程序依赖包
#jre的lb路径
wrapper.java.classpath.1=%basePath%/servicewrapper/jre/lib/*.jar
#wrapper.jar路径
wrapper.java.classpath.2=%basePath%/servicewrapper/lib/wrapper.jar
#自己的依赖jar包
wrapper.java.classpath.3=%basePath%/servicewrapper/mylib/*.jar
#tomcat依赖的包(tomcat启动类在这个包中)
wrapper.java.classpath.4 = %basePath%/bin/bootstrap.jar
wrapper.java.classpath.5 = %basePath%/bin/tomcat-juli.jar#Wrapper集成主类。有4种集成方式,适合tomcat这样启动使用一个类,
#停止使用另一个类的应用的是WrapperStartStopApp类
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperStartStopApp#tomcat应用参数,无需修改(第一个参数是tomcat的启动类)
wrapper.app.parameter.1=org.apache.catalina.startup.Bootstrap
wrapper.app.parameter.2=1
wrapper.app.parameter.3=start
wrapper.app.parameter.4=org.apache.catalina.startup.Bootstrap
wrapper.app.parameter.5=TRUE
wrapper.app.parameter.6=1
wrapper.app.parameter.7=stopwrapper.working.dir = %basePath%/bin#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib#wrapper.log日志文件位置
wrapper.logfile=%basePath%/servicewrapper/logs/wrapper.log#服务名称以及描述信息
wrapper.console.title=Exam Server
wrapper.name=examservice
wrapper.displayname=Exam Server
wrapper.description=Exam Server#Tomcat的固定参数(一般不用修改)
wrapper.java.additional.1=-Djava.util.logging.config.file=%basePath%/conf/logging.properties
wrapper.java.additional.2 = -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
wrapper.java.additional.3 = -Djava.endorsed.dirs=%basePath%/endorsed -Dcatalina.base=%basePath% -Dcatalina.home=%basePath%
wrapper.java.additional.4 = -Djava.io.tmpdir=%basePath%/temp
wrapper.java.additional.5 = -Djava.net.preferIPv4Stack=true
wrapper.java.additional.6 = -XX:MaxNewSize=256m
wrapper.java.additional.7 = -XX:MaxPermSize=256m
wrapper.java.additional.8 = -XX:-UseGCOverheadLimit
wrapper.java.additional.9 = -Dcom.sun.management.jmxremotewrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTARTwrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = true#监测JVM死锁
wrapper.java.monitor.deadlock = true
wrapper.java.monitor.heap = true
wrapper.java.monitor.gc.restart = true# Java Heap 初始化大小(单位:MB)
wrapper.java.initmemory=1024
# Java Heap 最大值(单位:MB)
wrapper.java.maxmemory=1024

5.注册为服务:

C:\Users\liqiang\Desktop\n2\tomcat\apache-tomcat-7.0.72\servicewrapper>bin\wrapper.exe -i ..\conf\wrapper.conf
wrapperm | Exam Server service installed.C:\Users\liqiang\Desktop\n2\tomcat\apache-tomcat-7.0.72\servicewrapper>sc qc examservice
[SC] QueryServiceConfig 成功SERVICE_NAME: examserviceTYPE               : 110  WIN32_OWN_PROCESS (interactive)START_TYPE         : 2   AUTO_STARTERROR_CONTROL      : 1   NORMALBINARY_PATH_NAME   : C:\Users\liqiang\Desktop\n2\tomcat\apache-tomcat-7.0.72\servicewrapper\bin\wrapper.exe -s C
:\Users\liqiang\Desktop\n2\tomcat\apache-tomcat-7.0.72\servicewrapper\conf\wrapper.conf wrapper.console.flush=true wrapp
er.internal.namedpipe=1139632464LOAD_ORDER_GROUP   :TAG                : 0DISPLAY_NAME       : Exam ServerDEPENDENCIES       :SERVICE_START_NAME : LocalSystemC:\Users\liqiang\Desktop\n2\tomcat\apache-tomcat-7.0.72\servicewrapper>

6.启动服务并进行日志查看:

  由于项目中使用了log4j,所以现在可以从两个地方查看log日志。第一个是log4j指定的日志的输出的位置,第二个是wrapper.logs文件。

7.监测Tomcat的参数信息:

  可以jps+jmap进行查看(前提是安装JDK),如果没有安装JDK可以利用tomcat自带的manager项目进行监测(参考:https://www.cnblogs.com/qlqwjy/p/8037392.html)。如果需要对参数进行优化,只需要修改上面wrapper.conf文件即可。

  总结:

  上面还可以进行大量的优化,比如讲一些不用的文件删掉,将多个lib目录进行合并;

  至此完成了tomcat注册为web服务,项目中一般使用这种方式进行部署项目,而且mysql可以采用集成部署集成到系统中,到时候系统上线的时候只用一个压缩包传到服务器,避免大量的下载tomcat、mysql等以及大量的配置。我上个项目上线也确实是通过安装JDK、mysql、tomcat等进行部署安装的,采用这种集成的方式都不用安装JDK等软件,简化部署。

5.linux环境下的注册为服务

  参考:https://www.cnblogs.com/zifengli/archive/2015/11/30/5007568.html

附件:官网的一份配置:

#encoding=UTF-8
# Configuration files must begin with a line specifying the encoding
#  of the the file.#********************************************************************
# Wrapper License Properties (Ignored by Community Edition)
#********************************************************************
# Professional and Standard Editions of the Wrapper require a valid
#  License Key to start.  Licenses can be purchased or a trial license
#  requested on the following pages:
# http://wrapper.tanukisoftware.com/purchase
# http://wrapper.tanukisoftware.com/trial# Include file problems can be debugged by removing the first '#'
#  from the following line:
##include.debug# The Wrapper will look for either of the following optional files for a
#  valid License Key.  License Key properties can optionally be included
#  directly in this configuration file.
#include ../conf/wrapper-license.conf
#include ../conf/wrapper-license-%WRAPPER_HOST_NAME%.conf# The following property will output information about which License Key(s)
#  are being found, and can aid in resolving any licensing problems.
#wrapper.license.debug=TRUE#********************************************************************
# Wrapper Localization
#********************************************************************
# Specify the locale which the Wrapper should use.  By default the system
#  locale is used.
#wrapper.lang=en_US # en_US or ja_JP# Specify the location of the Wrapper's language resources.  If these are
#  missing, the Wrapper will default to the en_US locale.
wrapper.lang.folder=../lang#********************************************************************
# Wrapper Java Properties
#********************************************************************
# Java Application
#  Locate the java binary on the system PATH:
wrapper.java.command=java
#  Specify a specific java binary:
#set.JAVA_HOME=/java/path
#wrapper.java.command=%JAVA_HOME%/bin/java# Tell the Wrapper to log the full generated Java command line.
#wrapper.java.command.loglevel=INFO# Java Main class.  This class must implement the WrapperListener interface
#  or guarantee that the WrapperManager class is initialized.  Helper
#  classes are provided to do this for you.  See the Integration section
#  of the documentation for details.
wrapper.java.mainclass=org.tanukisoftware.wrapper.demo.DemoApp# Java Classpath (include wrapper.jar)  Add class path elements as
#  needed starting from 1
wrapper.java.classpath.1=../lib/wrapperdemo.jar
wrapper.java.classpath.2=../lib/wrapper.jar# Java Library Path (location of Wrapper.DLL or libwrapper.so)
wrapper.java.library.path.1=../lib# Java Bits.  On applicable platforms, tells the JVM to run in 32 or 64-bit mode.
wrapper.java.additional.auto_bits=TRUE# Java Additional Parameters
wrapper.java.additional.1=# Initial Java Heap Size (in MB)
#wrapper.java.initmemory=3# Maximum Java Heap Size (in MB)
#wrapper.java.maxmemory=64# Application parameters.  Add parameters as needed starting from 1
wrapper.app.parameter.1=#********************************************************************
# Wrapper Logging Properties
#********************************************************************
# Enables Debug output from the Wrapper.
# wrapper.debug=TRUE# Format of output for the console.  (See docs for formats)
wrapper.console.format=PM# Log Level for console output.  (See docs for log levels)
wrapper.console.loglevel=INFO# Log file to use for wrapper output logging.
wrapper.logfile=../logs/wrapper.log# Format of output for the log file.  (See docs for formats)
wrapper.logfile.format=LPTM# Log Level for log file output.  (See docs for log levels)
wrapper.logfile.loglevel=INFO# Maximum size that the log file will be allowed to grow to before
#  the log is rolled. Size is specified in bytes.  The default value
#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
wrapper.logfile.maxsize=0# Maximum number of rolled log files which will be allowed before old
#  files are deleted.  The default value of 0 implies no limit.
wrapper.logfile.maxfiles=0# Log Level for sys/event log output.  (See docs for log levels)
wrapper.syslog.loglevel=NONE#********************************************************************
# Wrapper General Properties
#********************************************************************
# Allow for the use of non-contiguous numbered properties
wrapper.ignore_sequence_gaps=TRUE# Do not start if the pid file already exists.
wrapper.pidfile.strict=TRUE# Title to use when running as a console
wrapper.console.title=Test Wrapper Sample Application#********************************************************************
# Wrapper JVM Checks
#********************************************************************
# Detect DeadLocked Threads in the JVM. (Requires Standard Edition)
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=10
wrapper.max_failed_invocations=99
wrapper.console.fatal_to_stderr=FALSE
wrapper.console.error_to_stderr=FALSE
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL# Out Of Memory detection.
#  Ignore -verbose:class output to avoid false positives.
wrapper.filter.trigger.1000=[Loaded java.lang.OutOfMemoryError
wrapper.filter.action.1000=NONE
# (Simple match)
wrapper.filter.trigger.1001=java.lang.OutOfMemoryError
# (Only match text in stack traces if -XX:+PrintClassHistogram is being used.)
#wrapper.filter.trigger.1001=Exception in thread "*" java.lang.OutOfMemoryError
#wrapper.filter.allow_wildcards.1001=TRUE
wrapper.filter.action.1001=RESTART
wrapper.filter.message.1001=The JVM has run out of memory.#********************************************************************
# Wrapper Email Notifications. (Requires Professional Edition)
#********************************************************************
# Common Event Email settings.
#wrapper.event.default.email.debug=TRUE
#wrapper.event.default.email.smtp.host=<SMTP_Host>
#wrapper.event.default.email.smtp.port=25
#wrapper.event.default.email.subject=[%WRAPPER_HOSTNAME%:%WRAPPER_NAME%:%WRAPPER_EVENT_NAME%] Event Notification
#wrapper.event.default.email.sender=<Sender email>
#wrapper.event.default.email.recipient=<Recipient email># Configure the log attached to event emails.
#wrapper.event.default.email.attach_log=TRUE
#wrapper.event.default.email.maillog.lines=50
#wrapper.event.default.email.maillog.format=LPTM
#wrapper.event.default.email.maillog.loglevel=INFO# Enable specific event emails.
#wrapper.event.wrapper_start.email=TRUE
#wrapper.event.jvm_prelaunch.email=TRUE
#wrapper.event.jvm_start.email=TRUE
#wrapper.event.jvm_started.email=TRUE
#wrapper.event.jvm_deadlock.email=TRUE
#wrapper.event.jvm_stop.email=TRUE
#wrapper.event.jvm_stopped.email=TRUE
#wrapper.event.jvm_restart.email=TRUE
#wrapper.event.jvm_failed_invocation.email=TRUE
#wrapper.event.jvm_max_failed_invocations.email=TRUE
#wrapper.event.jvm_kill.email=TRUE
#wrapper.event.jvm_killed.email=TRUE
#wrapper.event.jvm_unexpected_exit.email=TRUE
#wrapper.event.wrapper_stop.email=TRUE# Specify custom mail content
wrapper.event.jvm_restart.email.body=The JVM was restarted.\n\nPlease check on its status.\n#********************************************************************
# Wrapper Windows NT/2000/XP Service Properties
#********************************************************************
# WARNING - Do not modify any of these properties when an application
#  using this configuration file has been installed as a service.
#  Please uninstall the service before modifying this section.  The
#  service can then be reinstalled.# Name of the service
wrapper.name=testwrapper# Display name of the service
wrapper.displayname=Test Wrapper Sample Application# Description of the service
wrapper.description=Test Wrapper Sample Application Description# Service dependencies.  Add dependencies as needed starting from 1
wrapper.ntservice.dependency.1=# Mode in which the service is installed.  AUTO_START, DELAY_START or DEMAND_START
wrapper.ntservice.starttype=AUTO_START# Allow the service to interact with the desktop.
wrapper.ntservice.interactive=false

参考Java Service Wrapper官网介绍:https://wrapper.tanukisoftware.com/doc/english/qna-service.html

wrapper高级配置详解参考:https://blog.csdn.net/u010419967/article/details/37690269

补充:wrapper安装的服务不能正常启动

  报错Unable to execute Java command.  系统找不到指定的文件。

  原因是找不到Java命令,解决办法就是修改wrapper.conf将java路径设为绝对路径,如下:

# Path to JVM executable. By default it must be available in PATH.
# Can be an absolute path, for example:
#wrapper.java.command=/path/to/my/jdk/bin/java
wrapper.java.command=C:\Program Files\Java\jdk1.8.0_121\bin\java.exe

转载于:https://www.cnblogs.com/qlqwjy/p/9492813.html

Java Service Wrapper将java程序设置为服务相关推荐

  1. Java Service Wrapper 发布Java程序为Windows服务

    下载Windows版本:https://www.krenger.ch/blog/java-service-wrapper-3-5-37-for-windows-x64/ 转自:F:\java\bhGe ...

  2. java 压缩jar 仓库,java服务安装(一):使用java service wrapper及maven打zip包

    tags: java jsw maven zip 1.概述 使用java开发程序,在windows平台下,一般有web应用,后台服务应用,桌面应用: web应用多数打成war包在web容器(如tomc ...

  3. JSW Java_java服务安装(一):使用java service wrapper及maven打zip包

    1.概述 使用java开发程序,在windows平台下,一般有web应用,后台服务应用,桌面应用: web应用多数打成war包在web容器(如tomcat,jetty等)中运行 桌面应用一般打成jar ...

  4. java windows wrapper_Java Service Wrapper 发布Java程序为Windows服务

    现在目前只要32位有免费的,64位免费版目前还没有做出来.官网上(社区)那一列是免费的. 1.先把你的项目用MANIFEST.MF打成jar包,例如bb.jar.新建目录,例如:dist,放在D盘下面 ...

  5. java service wrapper日志参数设置及优化

    一般在容器比如tomcat/weblogic中运行时,我们都是通过log4j控制日志输出的,因为我们现在很多服务端使用java service wrapper(至于为什么使用jsw,原先是比较排斥使用 ...

  6. Java Service Wrapper 使用经验总结

    1. 需求背景和工具简介 1.1 需求背景 最近因为公司需要管理上传的附件,准备把过期的文件夹(我们都是在指定目录下以日期8位来规定文件夹命名)移走进行备份,这时候就需要一个定时任务来进行定时检查文件 ...

  7. java service wrapper jar 服务_javaservice wrapper 实现注册服务功能

    2.例子1 a.创建HelloWorld_HOME文件夹,在下面编写例子程序HelloWorld.java public class HelloWorld { public static void m ...

  8. Windows Service Wrapper:将程序注册为windows系统服务工具

    前言 wsw 2.3.0 Windows Service Wrapper WinSW is an executable binary, which can be used to wrap and ma ...

  9. java service wrapper导致内存剧增直至崩溃

    应用程序使用wrapper包装之后导致内存溢出,直至应用程序崩溃. 现象: java应用程序在运行一段时间后把服务器内存耗光,程序死掉,但是守护进程wrapper还活着.虽然java应用程序死了,但是 ...

最新文章

  1. iOS开发-开发总结
  2. assign,copy,strong,weak,nonatomic的具体理解
  3. 富士康第三季度净利润10.9亿美元 同比下滑8.7%
  4. java 中的 super
  5. 文献学习(part12)--GMNN: Graph Markov Neural Networks
  6. spss三次指数平滑_17 统计学:SPSS基础
  7. Linux如何从普通用户切换到root用户
  8. 2020即将过去,数据库最好的时代已经到来!
  9. svn 配置详解,以及各种可能遇到的问题
  10. [PBRT-V3]代码中的#define(持续更新)
  11. 二阶系统阶跃响应实验_实验2二阶系统的阶跃响应及稳定性分析实验
  12. s5p4418安卓系统适配fpc8563芯片遇到的问题及解决
  13. Netty权威指南(第2版) pdf百度网盘下载
  14. The Backrooms - Level 0.2 - 我爱杏仁水
  15. 腾讯入股艺龙,在线旅游市场引发关注
  16. 计算机转换汉子英语,中英文切换(电脑怎么切换拼音打字)
  17. php api开发书籍,概述 · ThinkPHP API开发入门 · 看云
  18. 【小程序背景图之海贼王篇】
  19. Zabbix 邮件报警、钉钉报警、微信报警
  20. 旁路电容和去耦电容基础知识

热门文章

  1. 【C#】C#调用Bartender模板打印
  2. 时光老去,远了年少的我
  3. Linux gsoap生成onvif框架(C语言客户端代码)一
  4. 微软常用运行库合集(3264位)
  5. 三栏布局的七种实现方式
  6. Cookie存储购物车
  7. Android-实现邮箱格式的验证
  8. 蚂蚁海图tms切片工具
  9. 网友晒异性合租趣事:坐马桶都要签协议
  10. 微信小程序全栈开发实践 第三章 微信小程序开发常用的API介绍及使用 -- 3.7 网络接口简介(七)学习EventChannel对象