分享

以Windows服务方式运行Java程序

 dinghj 2014-11-27

然后利用系统自带的sc命令将其创建为系统服务:(这里为了测试效果,我加上了交互式运行服务的参数)

  1. sc create test binPath= "C:\FFE.exe" type= own type= interact start= auto 

注意,坑跌的windows命令一向是不走寻常路:

  • “=”后面一定要有空格
  • 如果要使用type参数,则一定要设置两个,比如上面的栗子中加了第一个”独立运行“,后面还要跟一个”交互式“才能最终生效,否则会报错:[SC] CreateService FAILED 87

参考: How to create windows services (Command Line)

Using some of the options will trigger a "[SC] CreateService FAILED 87" this usually means the option used like "type" needs another declaration. In case for instance when using type= interact, the type= option must be declared again with an alternative type like own. So effectivly the service type will be type= own interactive.

创建完成之后就可以启动服务:net start test

发现程序正常启动了,但是服务一直是启动状态,把程序关闭后,服务又变成了停止状态。Why?

因为系统服务并不知道你程序启动到什么状态才算是启动成功,也不知道程序停止是正常结束还是异常退出。

归根结底,就是通过sc命令将一般程序添加为系统服务的方式没有实现Win服务接口,不满足作为一个标准的daemon程序的条件。

在网上搜索一番,发现还有微软的开发工具可以利用:使用srvany.exe将任何程序作为Windows服务运行

上面这篇文章写得很棒,作者还开发了一个轻巧的工具SrvanyUI方便创建自定义服务。

但是我经过试验没有成功,原因不明。后台监控发现java程序闪现之后迅速关闭,可能是因为classpath设置错误。

总而言之,这种方式还是不够灵活,出错没有任何提示,只能通过经验去排错;

另外,如文中所说,该工具已不被微软支持了,并且win7以上的版本可能会出现兼容问题。

二、来自Java世界的工具

How to create a windows service from java app?

各种牛人都在这篇问答里发表了他们的看法:

JSW我使用了较长的时间,稳定性和扩展性都不错,高级版本还提供了对Java异常处理,比如OOM产生时可以选择是否自动重启服务。

但不足之处是,收费、64位版本需要购买Licence。放在5年前,或许不用担忧是否需要64位JVM,但如今,32位仅1.5G的堆内存略显不足。

一个 wrapper.conf配置文件示例如下:(官方下载包有更详细的例子和说明)

  1. wrapper.java.command="C:\Program Files\Java\jdk1.7.0_72\bin\java" 
  2. wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp 
  3. wrapper.java.classpath.1=../test.jar 
  4. wrapper.java.classpath.2=wrapper.jar 
  5. wrapper.java.classpath.3=../lib/* 
  6. wrapper.java.library.path.1=. 
  7. wrapper.java.additional.1= -Xms512m 
  8. wrapper.java.additional.2= -Xmx512m 
  9. wrapper.java.initmemory=256 
  10. wrapper.java.maxmemory=512 
  11. wrapper.app.parameter.1=test.Main 
  12. wrapper.app.parameter.2=arg1 
  13. wrapper.console.format=PM 
  14. wrapper.console.loglevel=INFO 
  15. wrapper.logfile=../log/test.log 
  16. wrapper.logfile.format=LPTM 
  17. wrapper.logfile.loglevel=INFO 
  18. wrapper.logfile.maxsize=0 
  19. wrapper.logfile.maxfiles=0 
  20. wrapper.syslog.loglevel=NONE 
  21. wrapper.console.title=Test_Service 
  22. wrapper.ntservice.name=Test_Service 
  23. wrapper.ntservice.displayname=Test_Service 
  24. wrapper.ntservice.description=Test_Service 
  25. wrapper.ntservice.dependency.1= 
  26. wrapper.ntservice.starttype=AUTO_START 
  27. wrapper.ntservice.interactive=false 

或许YAJSW出现就是为了替换JSW,因为它是开源免费的,且支持从JSW快速无缝迁移。但是,有个哥们都说被它19M的下载包给吓到了…所以……

  • WinRun4J,java2exe2service集合,额外提供 eclipse插件一键导出!

以下工具本人并未测试,但不代表不适用:

  • FireDaemon(看到Buy Now两个字后我就X了)

三、久违的 Apache Commons Daemon

先来说说情怀:Tomcat,相信很多同学从第一天学习Java的时候就开始熟知。看到ACD的图标后才发现,原来Tomcat win安装版就是用的它!

再来说说用法:Win版的入口程序是procrun。创建一个服务是如此之简单:

  1. set APP_HOME=D:\ 
  2. set CP=%APP_HOME%\test.jar;%APP_HOME%\lib\* 
  3. REM 创建服务 
  4. prunsrv //IS//test_service --DisplayName=test_service --Install=%APP_HOME%\bin\prunsrv.exe --StartMode=jvm --StopMode=jvm --Startup=auto --JavaHome="C:\Program Files\Java\jdk1.7.0_72\" --JvmMs=2048 --JvmMx=2048 --JvmSs=128 ++JvmOptions=-server;-XX:+UseParallelGC;-XX:ParallelGCThreads=4;-XX:+UseParallelOldGC;-XX:+UseAdaptiveSizePolicy --Classpath=%CP%" --StartClass=com.test.Main --StopClass=com.test.Main --StopMethod=stop --LogPath=%APP_HOME%\log --StdOutput=auto --StdError=auto 
  5. REM 删除服务 
  6. prunsrv //DS//test_service 

参数很多,看看注释就明白了,这里也有中文翻译:Commons Daemon 之 procrun

此外,Wiki页上有一些答问和一个Java主程序栗子。注意:

  • --LogPath 一定要指定,下面的报错信息都可在日志文件中找到:commons-daemon.2014-11-11.log
  • --Classpath 一定要写成变量,否则会添加失败,原因不详
  • --Classpath=%CP%" 这句最后多出的那个双引号一定要写,否则创建失败,原因不详!
  • --StopMethod=stop 关闭服务的时候会自动调用该stop方法,具体写法如下:
  1. public static void stop(String[] args) { 
  2.     System.out.println("服务关闭了"); 
  3.     System.exit(0); 

Procrun不仅可将Java类生成服务,也可将exe变为服务,详见参数设置。

参考:用common-deamon构建java后台服务Windows 64位环境的Java 服务配置

四、最后来看强大的WinRun4J

先来说说它的弊端:需要一个入口类,依赖WinRun4J.jar包,相比ACD有一定耦合度,而非直接用主启动类,除此之外,一切看起来都不错~

The only drawback is that it requires a special class for working as a service (instead of simply calling standard main class)

官网上有个生成服务的栗子,下载的包里也有,但是都有点问题:

  1. import org.boris.winrun4j.AbstractService; 
  2. import org.boris.winrun4j.EventLog; 
  3. import org.boris.winrun4j.ServiceException; 
  4.   
  5. public class ServiceTest extends AbstractService { 
  6.       
  7.     public int serviceMain(String[] args) throws ServiceException { 
  8.         int count = 0; 
  9.         while (!shutdown) { 
  10.             try { 
  11.                 Thread.sleep(1000); 
  12.             } catch (InterruptedException e) { 
  13.             } 
  14.             if (++count % 10 == 0) { 
  15.                 EventLog.report("test", EventLog.INFORMATION, "test..." + count); 
  16.                 System.out.println("test log...." + count); 
  17.             } 
  18.         } 
  19.         System.out.println("service shutdown..."); 
  20.         return 0; 
  21.     } 
  22.   
  23.     public boolean isShutdown() { 
  24.         System.out.println("isShutdown called..."); 
  25.         return super.isShutdown(); 
  26.     } 

上面类中调用 EventLog.report方法生成的日志只会写到系统日志里,只有在 计算机管理 - 系统工具 - 事件查看器 - 应用程序 中才能看到

对应的日志文件在XP系统中的位置是:C:\WINDOWS\system32\config\SysEvent.Evt

显然我们更希望日志可控,而不是被操作系统接管。但是我没有找到合适的参数来设置,只能通过Java程序来指定。

将上面的类编译后生成class文件,然后再来编辑配置文件WinRun4Jc.ini:

  1. service.class=ServiceTest 
  2. service.id=WinRun4J_Test 
  3. service.name=WinRun4J_Test 
  4. service.description=test WinRun4J. 
  5. classpath.1=. 
  6. classpath.2=D:\winrun4j\bin\WinRun4J.jar 
  7. log=test.log 

注意了:

  • WinRun4Jc.ini与 WinRun4Jc.exe必须位于相同目录且名称要一致,因为没有参数可以指定配置文件路径…
  • 以上参数缺一不可,并且 service.id与 service.name一定要写相同的服务名称
  • classpath.2指定为 WinRun4J.jar的路径,因为上面的服务入口类实现了该包中的某类

通过以下命令创建和删除服务:

  1. WinRun4Jc --WinRun4J:RegisterService 
  2. WinRun4Jc --WinRun4J:UnregisterService 

WinRun4J还提供了Eclipse插件以及给exe程序增加ico图标的小工具,用法很简单,官网上也有说明。

不管怎么说,WinRun4J相当于ACD和 Launch4j的合体,虽然整体功能没有两者强大,但是也都做得不错,

尤其是对于使用eclipse的同学可是方便了不少,看看它贴心的导出功能即可见一斑:

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多