JavaアプリをWindowsサービス化する方法
Javaで作成したサーバアプリをWindowsで常駐される必要があったので
Windowsサービス化させてみた。
環境は以下の通り。
・Javaバージョン:1.7.0.15
・Windows Server 2008 R2 64bit
今回は、Tomcatでも使用されているApache Commons Daemon(移行、Daemo)を使用した。
今回試した手順は以下の通り。
1. ダウンロード
Daemonに関するライブラリだったりバイナリをダウンロードする。
ライブラリは、
http://commons.apache.org/proper/commons-daemon//download_daemon.cgi
バイナリは、
http://commons.apache.org/proper/commons-daemon//binaries.html
からそれぞれ最新版を入手する。
ライブラリは、commons-daemon-1.0.13.jarとバージョン付きのJarファイル
なので、これをプロジェクトのビルドパスに加えておく。
2. コーディング
Windowsサービス開始と停止時のエントリポイントとなるクラスを用意する。
このクラスは、org.apache.commons.daemon.Daemonインタフェースを
実装する必要がある。
サービス開始時と停止時にコールされるメソッドを用意する。
このメソッドは、public staticでなければならない。戻り値はどの型でも大丈夫だけど、評価できないのでvoidが妥当。
Linuxで使用する場合は、Daemonインタフェースで定義されているメソッドを
Overrideして処理を記述する必要があるけど、今回はWIndowsなので無視する。
サンプルは、以下の通り。
サンプルをビルドして実行可能JarとしてServiceLauncher.jarを作成する。
ServiceLauncher.java
package hoge; import org.apache.commons.daemon.Daemon; import org.apache.commons.daemon.DaemonContext; import org.apache.commons.daemon.DaemonInitException; /** * サービスを起動停止するクラス. * */ public class ServiceLauncher implements Daemon { // ランチャー private static ServiceLauncher launcher; // サービス private Service service; /** * コンストラクタ. */ public Service() { } /** * サービス実行. * */ public void run() { service = new Service(); ・ ・ ・ try { Thread t = new Thread(service ); t.setDaemon(true); t.start(); // サービスが停止するまで制御を戻したらダメ t.join(); } catch (InterruptedException e) { ・ ・ } } /** * サービス停止処理 */ public void terminate() { if (service != null) { service .stop(); } } /** * Windowsサービス開始時にcommons Daemonからコールされる * */ public static void startService(String args) { launcher = new ServiceLauncher(); launcher.run(); // サービス停止まで制御もどってこないはず } /** * Windowsサービス停止時にcommons Daemonからコールされる * * @param args */ public static void stopService(String args) { if (launcher != null) { launcher.terminate(); } } /** * Linuxで使用した場合commons Daemonからコールされる * 未実装 */ @Override public void destroy() { // Ingore } /** * Linuxで使用した場合commons Daemonからコールされる * 未実装 */ @Override public void init(DaemonContext arg0) throws DaemonInitException, Exception { // Ingore } /** * Linuxで使用した場合commons Daemonからコールされる * 未実装 */ @Override public void start() throws Exception { // Ingore } /** * Linuxで使用した場合commons Daemonからコールされる * 未実装 */ @Override public void stop() throws Exception { // Ingore } /** * メイン関数 * Windowsサービス時には未使用 * @param args */ public static void main(String[] args) { launcher = new ServiceLauncher(); launcher.run(); return; } }
Service.java
package hoge; /** * サービスクラス. * */ public class Service implements Runnable { // 実行中フラグ private boolean isRunning = false; /** * コンストラクタ. */ public Service () { } /** * サービスを停止する。 * */ public void stop() { isRunning = false; } /** * スケジューラを開始する。 * */ @Override public void run() { isRunning = true; while (_isRunning) { ・ ・ ・ } } }
3. インストール
できあがったJarファイルをWindowsサービスに登録する。
使用するのは、バイナリとしてダウンロードしたprunsvr.exeとprunmgr.exe。
64bit OSで使用する場合は、amd64/にあるファイルを使用する。
prunsvr.exeをServiceLauncher.exeにprunmgr.exeをServiceLauncherw.exeに
それぞれリネームする。
上記exeファイルと作成したJarファイルを同じフォルダに置く。
パラメータが多いのでインストール用バッチファイルを作成する。
Install.bat
set EXEC_DIR=%~dp0 echo %EXEC_DIR% set INSTALL_PATH=%EXEC_DIR%ServiceLauncher.exe set CLASSPATH=%EXEC_DIR%ServiceLauncher.jar;<commons-daemon-1.0.13.jarへのパス> # JVMのパスを指定する。オプションでauto指定もできるがうまくいかない set JVM_PATH="C:\Program Files\Java\jre7\bin\server\jvm.dll" ServiceLauncher //IS//ServiceLauncher--DisplayName="ServiceLauncher" --Install=%INSTALL_PATH% --Startup=auto --Jvm=%JVM_PATH% --StartMode=jvm --StopMode=jvm --Classpath=%CLASSPATH% --StartClass=hoge.ServiceLauncher --StartMethod=startService --StopClass=hoge.ServiceLauncher --StopMethod=stopService --LogPath=%EXEC_DIR% --LogLevel=DEBUG --StdOutput=auto --StdError=auto pause
アンインストール用のバッチファイルも用意する。
Uninstall.bat
ServiceLauncher //DS//ServiceLauncher pause
詳細は、
http://commons.apache.org/proper/commons-daemon//procrun.html
と
http://wiki.apache.org/commons/Daemon
を参照
4. サービス起動
prunmgr.exeをリネームしたServiceLauncherw.exeからサービスの起動停止を行う。
当然、通常のWindowsサービス起動停止手順でも可能。
prunmgr.exeでは他にもパラメータの変更ができる。
prunmgr.exeは、ファイル名=サービス名として認識する。
ファイル名内の'w'は無視するのでサービス名+'w'にリネームしておくと
サービス名にリネームしたprunsvr.exeと共存できるようになる。