September 7, 2024
By: 马海强

用WinSW注册windows 服务

  1. 需要
  2. 方法
  3. 使用准备
  4. 1. 把exe注册成服务
  5. 2. 把jar服务注册成服务
  6. 我们关注的日志配置
  7. 目前batch的日志
  8. 可能会用到
  9. 遗留问题
  10. 参考资料

需要

做windows上应用,我们有基于以下两个主要原因把自己的应用注册成了windows的服务。

  • 自动启动, 我们的应用要一直活着,不用写监控脚本什么的,服务崩溃后自动重启,开机自启。
  • 后台运行,当然让程序在后台运行的方法有很多,但是比如java进程可能就被人在任务管理中找到干掉了。

方法

把自己的exe或者jar注册成windows的服务有很多方式,比如:

windows自带的sc.exe

NSSM(Non-Sucking Service Manager)

微软自己家的instsrv+srvany

WinSW

我们本次选择使用的就是WinSW,这款通过xml配置属性的服务注册工具。

使用准备

  1. 在release页面上下载 WinSW-x64.exe

  2. 了解配置文件文档

  3. 基本命令

    命令描述
    install注册服务
    uninstall卸载服务
    start启动服务
    stop停止服务
    restart重启服务
    status查看服务的状态

    比如:

    .\WinSW-x64.exe stop .\batch-server.xml
    

1. 把exe注册成服务

在batch项目要把硬件连接器wincc-contector.exe注册成一个windows服务,实现开机自启。宕机自动重启。

  • WinSW-x64.exe,wincc-contector.exe,配置文件wincc-contector.xml配置文件放在同一目录(也可以用绝对路径)

  • wincc-contector.xml配置内容如下:

    <service>
      <id>WinccConnector</id>
      <name>WinccConnector</name>
      <description>WinccConnector</description>
      <!-- 可以是绝对路径 -->
      <executable>WinccConnector.exe</executable>   
      <logpath>log</logpath>
      <log mode="roll-by-size-time">
        <sizeThreshold>10240</sizeThreshold>
        <pattern>yyyyMMdd</pattern>
        <autoRollAtTime>00:00:00</autoRollAtTime>
      </log>
      <!-- 自动重启配置 -->
      <onfailure action="restart" delay="5 sec"/>
    
      <!-- 服务恢复策略 -->
      <recovery>
        <!-- 第一次失败后重启,延迟5秒 -->
        <action type="restart" delay="5 sec"/>
        <!-- 第二次失败后重启,延迟10秒 -->
        <action type="restart" delay="10 sec"/>
        <!-- 第三次失败后重启,延迟10秒 -->
        <action type="restart" delay="10 sec"/>
        <!-- 重置恢复策略计数器的时间周期 -->
        <resetPeriod>1 day</resetPeriod>
      </recovery>
    </service>
    
  • 安装,卸载,启动,停止的命令

    .\WinSW-x64.exe install .\wincc-connector.xml
    .\WinSW-x64.exe start .\wincc-connector.xml
    .\WinSW-x64.exe stop .\wincc-connector.xml
    .\WinSW-x64.exe uninstall .\wincc-connector.xml
    

2. 把jar服务注册成服务

需要执行jar所在的目录结构

C:.
|   backend.xml
|   clj-backend.jar
|   config.edn
|   mssql-jdbc_auth-9.4.0.x64.dll
|   server.db
|   WinSW-x64.exe
├───jdk-11.0.22
├───log

backend.xml配置文件内容如下:

<service>
  <id>batch-server</id>
  <name>Batch 服务</name>
  <description>Batch服务</description>
  <!-- 确保 PowerShell 的环境与直接运行 java -jar 时一致 -->
  <env name="PATH" value="%SystemRoot%\system32\WindowsPowerShell\v1.0;%PATH%"/>
  <workingdirectory>C:\CTBatch\batch-server\backend</workingdirectory>
  <executable>.\jdk-11.0.22\bin\java.exe</executable>
  <arguments> -jar -Dfile.encoding=UTF-8 -Dconf=config.edn -Dclojure.core.async.pool-size=300 .\clj-backend.jar</arguments>
  <logpath>log</logpath>
  <log mode="roll-by-size-time">
    <sizeThreshold>1024</sizeThreshold>
    <pattern>yyyyMMdd</pattern>
    <autoRollAtTime>00:00:00</autoRollAtTime>
  </log>
  <!-- 自动重启配置 -->
  <onfailure action="restart" delay="10 sec"/>

  <!-- 服务恢复策略 -->
  <recovery>
    <!-- 第一次失败后重启,延迟5秒 -->
    <action type="restart" delay="5 sec"/>
    <!-- 第二次失败后重启,延迟10秒 -->
    <action type="restart" delay="10 sec"/>
    <!-- 第三次失败后重启,延迟10秒 -->
    <action type="restart" delay="10 sec"/>
    <!-- 重置恢复策略计数器的时间周期 -->
    <resetPeriod>1 day</resetPeriod>
  </recovery>
</service>

操作的命令

.\WinSW-x64.exe install .\backend.xml
.\WinSW-x64.exe start .\backend.xml
.\WinSW-x64.exe stop .\backend.xml
.\WinSW-x64.exe uninstall .\backend.xml

安装完后在windows的服务里能看到如下:

服务列表

服务详情

服务重启设置

我们关注的日志配置

日志模块的配置官方配置说明在此。

  • 日志路径

    <!-- 当前目录下的log里存放日志 -->
    <logpath>.\log</logpath>
    
  • 日志模式

    <log mode="append"/>
    

    append: 默认的模式,输出myapp.out.log and myapp.err.log 这两个日志文件

    reset:每次服务重启都会把之前的日志清空

    none: 忽略日志,不收集日志

    roll :这个模式使我们日常使用最多的。详细的解释如下:

    <log mode="roll-by-size-time">
      <sizeThreshold>10240</sizeThreshold>
      <pattern>yyyyMMdd</pattern>
      <autoRollAtTime>00:00:00</autoRollAtTime>
    </log>
    

    这时候的mode有roll-by-size,roll-by-time,roll-by-size-time,这符合我们日常对日志的需要,就是按日志大小和日期归档日志,最终会生成比如:myapp.20240101.out.logmyapp.20240101.err.log这样的日志。

目前batch的日志

  • 按照上面的配置,log目录下会有四个日志文件

    `backend.out.log`: 标注输出log,我们平时用timbre打的日志,会在这里。
    `backend.err.log`: 目前batch项目里这里只有告警日志,并没有错误日志(待明确)。
    `backend.wrapper.log`: winsw的start,install等控制的操作日志
    `clj-backend.log`: 标注输出log,我们平时用timbre打的日志,会在这里。
    
  • batch的后台用taoensso.timbre打的日志,因为java启动命令重定向了日志输入,所以日志在jar包同级的log目录里,命名还是clj-backend.log这个我们clojure里指定的文件名。

    因此,按照上面的配置,batch项目现在大量2份日志。如果要关闭winsw的收集,只需要在xml不配置日志即可。

  • wincc-connector的日志

    这是C#程序打出来的exe文件。log用winsw控制的,按照xml的配置收集了wincc-connector里的日志,但是C#的日志用dotnet run在控制台能看到,打包后看不到了。

可能会用到

  • 启动和停止要执行的脚本和命令参数不一样

    <executable>catalina.sh</executable>
    <startarguments>jpda run</startarguments>
    
    <stopexecutable>catalina.sh</stopexecutable>
    <stoparguments>stop</stoparguments>
    
  • 启动和停止命令前需要先执行什么

    <!-- 主程序启动前需要干点啥 -->
    <prestart>
      <executable></executable>
      <arguments></arguments>
      <stdoutPath></stdoutPath>
      <stderrPath></stderrPath>
    </prestart>
    <!-- 主程序启动成功后要干啥 -->
    <poststart>
      <!-- ... -->
    </poststart>
    
    <!-- 主程序停止前要干啥 -->
    <prestop>
      <!-- ... -->
    </prestop>
    
    <!-- 主程序启动后后干啥 -->
    <poststop>
      <!-- ... -->
    </poststop>
    
  • 环境变量,指定活动目录

    <env name="HOME" value="C:\CTBatch" />
    
  • 设置服务账号密码

    这部分我没有尝试,官方介绍还比较详细,需要的时候可以再深入试用一下。

    <serviceaccount>
      <username>DomainName\UserName</username>
      <password>Pa55w0rd</password>
      <allowservicelogon>true</allowservicelogon>
      <prompt>dialog|console</prompt>   <!-- 这是账号密码在哪输入 -->
    </serviceaccount>
    

遗留问题

  • wincc-connector服务中,C#中打的log,在dotnet run执行时能看到日志,但是打包成服务后不知道日志在哪里了。
  • jar服务,在代码中调用了powershell的命令,用java -jar启动程序后能读到powershell命令的执行结果,但是注册成服务后执行命令没有报错,但是读不到命令的执行结果。

参考资料

github首页

Tags: windows