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


      有时候我们希望我们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%in
    %EXAMPLE_HOME%conf
    %EXAMPLE_HOME%lang
    %EXAMPLE_HOME%lib
    %EXAMPLE_HOME%mylib
    %EXAMPLE_HOME%logs

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

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

    %WRAPPER_HOME%inwrapper.exe -> %EXAMPLE_HOME%inwrapper.exe
    %WRAPPER_HOME%libwrapper.jar -> %EXAMPLE_HOME%libwrapper.jar
    %WRAPPER_HOME%libwrapper.dll -> %EXAMPLE_HOME%libwrapper.dll
    %WRAPPER_HOME%confwrapper.conf -> %EXAMPLE_HOME%confwrapper.conf


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

    3.修改配置文件    %EXAMPLE_HOME%confwrapper.conf

    #java.exe所在位置
    wrapper.java.command=C:Program FilesJavajdk1.7.0_80injava.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:UsersAdministrator>cd C:UsersAdministratorDesktopSW
    
    C:UsersAdministratorDesktopSW>binwrapper.exe -c ..confwrapper.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 FilesJavajdk1.7.0_80injava.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:UsersAdministratorDesktopSWin..libwrapper.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:UsersAdministratorDesktopSWlibwrapper.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)将程序注册为服务:

    binwrapper.exe -i ..confwrapper.conf

    结果:

    wrapper  | Hello World Server service installed.

    (3)启动服务:

    net start helloworld

     或者:

    binwrapper.exe -t ..confwrapper.conf

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

    (4)停止服务

    net stop helloword

    或者

    binwrapper.exe -p ..confwrapper.conf

    (5)删除服务

    sc delete helloword

    或者

    binwrapper.exe -r ..confwrapper.conf

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

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

    jre目录下:

    (2)修改配置文件,利用我们上面的jre目录下的jar包和binjava.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:UsersliqiangDesktopxxxSW>binwrapper.exe -c ..confwrapper.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: "..jreinjava.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:UsersliqiangDesktopxxxSWin..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:UsersliqiangDesktopxxxSWlibwrapp
    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:UsersliqiangDesktopxxxSW>binwrapper.exe -i ..confwrapper.conf
    wrapperm | Hello World Server service installed.
    
    C:UsersliqiangDesktopxxxSW>java
    'java' 不是内部或外部命令,也不是可运行的程序
    或批处理文件。
    
    C:UsersliqiangDesktopxxxSW>javac
    'javac' 不是内部或外部命令,也不是可运行的程序
    或批处理文件。

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

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

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

     

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

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

    #定义了一个根路径,注意set和.之间没有空格,下面就可以用%basePath%取此变量
    set.basePath=C:UsersliqiangDesktopxxxSW
    
    #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:UsersliqiangDesktopxxxSW>binwrapper.exe -r ..confwrapper.conf
    wrapperm | Hello World Server service removed.
    C:UsersliqiangDesktopxxxSW>binwrapper.exe -c ..confwrapper.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:UsersliqiangDesktopxxxSWjreinjava.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:UsersliqiangDesktopxxxSWin..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:UsersliqiangDesktopxxxSWlibwrapp
    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:UsersliqiangDesktopxxxSW>binwrapper.exe -i ..confwrapper.conf
    wrapperm | Hello World Server service installed.

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

    C:Usersliqiang>jps
    505668 Jps
    504320 WrapperSimpleApp
    487768
    
    C:Usersliqiang>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.25in中的文件复制到我们的%EXAMPLE_HOME%in目录下)

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

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

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

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

    set.basePath=C:UsersliqiangDesktopxxxSW   #替换为自己的目录
    #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:UsersliqiangDesktoplogTest
    
    #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:Usersliqiang>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测试控制台:

    logswrapper.log文件内容如下:

    E: est.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:UsersliqiangDesktop
    2	omcatapache-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:UsersliqiangDesktop
    2	omcatapache-tomcat-7.0.72servicewrapper>binwrapper.exe -i ..confwrapper.conf
    wrapperm | Exam Server service installed.
    
    C:UsersliqiangDesktop
    2	omcatapache-tomcat-7.0.72servicewrapper>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:UsersliqiangDesktop
    2	omcatapache-tomcat-7.0.72servicewrapperinwrapper.exe -s C
    :UsersliqiangDesktop
    2	omcatapache-tomcat-7.0.72servicewrapperconfwrapper.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:UsersliqiangDesktop
    2	omcatapache-tomcat-7.0.72servicewrapper>

    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.
    
    Please check on its status.
    
    
    #********************************************************************
    # 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 FilesJavajdk1.8.0_121injava.exe
  • 相关阅读:
    C# 1.0 到 C# 3.0 委托创建过程的发展
    C#禁用窗体最大化按钮
    TeamViewer 通过Internet进行远程访问和远程支持
    c# 匿名方法
    BeginInvoke会重新开一个线程
    c# 线程调用带参数的函数
    c# msdn 委托
    判断某张表是否存在在数据库中(access 2003 与sql server 2008)
    新浪微博自动发送微博 功能已实现(net)
    validateRequest="false" 在asp.net 4.0中失效的解决办法
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9492813.html
Copyright © 2020-2023  润新知