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%\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

 

補充: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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM