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

转自:F:\java\bhGetJzData\lib\wrapper.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

  有时候我们希望我们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\SW

C:\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 Stopped C:\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 Server wrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTART wrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = true wrapper.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 Stopped C:\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
487768 C:\Users\liqiang>jmap -heap 504320
Attaching to process ID 504320, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11 using thread-local object allocation.
Parallel GC with 4 thread(s) Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 134217728 (128.0MB)
NewSize = 1310720 (1.25MB)
MaxNewSize = 17592186044415 MB
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 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 Generation
capacity = 89653248 (85.5MB)
used = 0 (0.0MB)
free = 89653248 (85.5MB)
0.0% used
PS Perm Generation
capacity = 22020096 (21.0MB)
used = 6630336 (6.32318115234375MB)
free = 15389760 (14.67681884765625MB)
30.110386439732142% used 3336 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,B

log4j.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%n log4j.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 Server wrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTART wrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = true wrapper.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=stop wrapper.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.jmxremote wrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTART wrapper.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: examservice
TYPE : 110 WIN32_OWN_PROCESS (interactive)
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_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=1139632464
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Exam Server
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem C:\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

【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】

Java Service Wrapper 发布Java程序为Windows服务的更多相关文章

  1. Java Service Wrapper 发布Java程序或者jar包为Windows服务

    下载Windows版本:http://nchc.dl.sourceforge.net/sourceforge/wrapper/wrapper-windows-x86-32-3.2.3.zip 现在目前 ...

  2. java service wrapper将java程序包装成系统服务(一)

    一. 概述 使用java语言开发应用程序,在windows平台下,一般存在3种应用形式: 1. web应用.web应用多数打成war包在web容器(如tomcat,jetty等)中运行. 2. 桌面应 ...

  3. 利用JAVA Service Wrapper把JAVA程序做成windows服务

    今天做了一个读取数据入库的程序.由于读取的数据每天都更新,于是就想把程序做成一个服务,每天定时执行.研究了一下,发现有几种方式可以做.下面我主要记录一下JAVA Service Wrapper方式. ...

  4. Java Service Wrapper将java程序设置为服务

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

  5. 详解Maven项目利用java service wrapper将Java程序生成Windows服务

    在项目的开发中,有时候需要将Java应用程序打包成Windows服务,我们就直接可以通过windows的服务来启动和关闭java程序了. 本博文将通过有两种方法实现该功能,手动创建法和Maven自动打 ...

  6. 使用java service wrapper将java程序注册为window服务

    1.下载java service wrapper 下载地址:http://wrapper.tanukisoftware.com/doc/english/download.jsp 针对自己的需求下载相应 ...

  7. 利用Java Service Wrapper将java项目添加到windows服务中

    1.web项目,即tomcat/resin添加至window系统服务,步骤如下:第一步:找到tomcat的bin目录,如:D:\apache-tomcat-8.0.26\bin第二步:打开cmd,cd ...

  8. 使用Java Service Wrapper将java程序作为linux服务并且开机自动启动

    以java应用程序为例,打包为tianlong.jar,程序入口为tianlong.QueueTest. 下面在linux的/opt下建立tianlong目录,复制tianlong.jar到/opt/ ...

  9. 使用 Java Service Wrapper 启动java后台进程服务

    Java Service Wrapper (http://wrapper.tanukisoftware.com/doc/english/product-overview.html)可以很方便得在各个平 ...

随机推荐

  1. jQuery中判断input的checked属性

    <input type="checkbox" id="ipt1" checked> <input type="checkbox&qu ...

  2. Laravel基本使用

    laravel一.简介二.运行环境要求 1.php 版本>=5.5.9 2.Mcrypt PHP扩展 php的加密扩展,提供多种加密算法 3.openssl扩展 对传输的数据进行加密 4.mbs ...

  3. django开发博客(1) 入门

    现在正式开始博客开发 1.安装django1.4 如果你使用的是fedoraDVD版,安装时选择了web开发组建,这一步可以省略,因为它自带django环境 django下载地址 https://ww ...

  4. PID控制算法

    PID控制算法 四轴如何起飞的原理 四轴飞行器的螺旋桨与空气发生相对运动,产生了向上的升力,当升力大于四轴的重力时四轴就可以起飞了. 四轴飞行器飞行过程中如何保持水平: 我们先假设一种理想状况:四个电 ...

  5. latex 图形的放置

         Next: 16.3 清除未处理的浮动图形 Up: 16. 浮动图形环境 Previous: 16.1 创建浮动图形  16.2 图形的放置 图形(figure)环境有一个可选参数项允许用户 ...

  6. Linux下部署redis以及相关简介

    什么是redis? Redis是一个高性能的key-value数据库.key-value分布式存储系统查询速度快.存放数据量大.支持高并发,非常适合通过主键进行查询,但不能进行复杂的条件查询.key ...

  7. Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.

    In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...

  8. oracle 找回DROP掉的表

    select * from pan ;   --有数据 drop table pan;        --删除表 select * from pan ;   --表或视图不存在 flashback t ...

  9. Python学习---django之ORM语法[对象关系映射]180124

    ORM语法[对象关系映射] ORM: 用面向对象的方式去操作数据库的创建表以及增删改查等操作. 优点:1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句.快速开发. 2 ...

  10. 省钱小贴士(ECS):教你如何每年省出8w+ 块

    随着用户越来越多地使用阿里云的ECS服务,如何用最小的成本来保有ECS,成为用户越来越重要的关注点. 变更点 为了更好的服务客户,ECS团队调整了系统盘的最小容量限制 linux系统 core os调 ...