WinSW服务化工具

发布于 2025-06-26  1.27k 次阅读


    WinSW(Windows Service Wrapper)是一个开源工具,主要用于将任意的可执行文件(比如:.exe,.bat、.jar)包装成Windows服务,方便随Windows系统启动并在后台运行。这个工具特别适合用来部署一些持续运行的持续,例如:Java应用、NodeJS程序、脚本任务等

WinSW的核心用途:

  1. 将普通命令行程序注册为Windows服务
  2. 管理服务的启动、停止、自动重启、卸载等行为
  3. 配置灵活,支持日志重定向、环境变量、依赖服务等

应用场景:

    • Java程序部署成Windows
    • Nodejs后台服务随系统启动运行
    • 各类批处理脚本或定时任务守护进程
    • 将轻量程序注册为服务

WinSW的GitHub开源地址

1.  🔗 Winsw下载

 下载winsw.exe程序地址

文件名
说明
使用场景
WinSW-x64.exe
针对 64 位 Windows 系统构建的主流版本
适用于绝大多数现代 Windows 系统
WinSW-x86.exe
针对 32 位 Windows 系统构建
仅当你运行在 32 位 Windows 时使用
WinSW.NET2.exe
依赖 .NET Framework 2.0 的版本
用于非常旧的 Windows(如 XP)系统
WinSW.NET4.exe
依赖 .NET Framework 4.0+ 的通用版本
可作为兼容版使用
WinSW.NET461.exe
明确依赖 .NET Framework 4.6.1 的构建版本
更适合一些企业环境特定版本需求

2. 🧩 Winsw使用

步骤:

  1. 重命名服务名
  2. 创建并编写配置文件
  3. 注册安装服务

示例:将Java的jar包运行注册成一个Windows服务

📂 文件目录结构:

S:\My-Shoot-Server

├── whsingleshoot-server.exe    ← 从 GitHub 下载并重命名
├── whsingleshoot-server.xml    ← 配置文件(必须和exe注册程序重名)
├── whsingleshoot-system.jar    ← 你要运行的程序
└── logs\             ← 日志目录(自动生成)

注:执行文件和配置文件必须是重名,否则会找不到配置启动识别

1)下载后的winSW默认为WinSW.NET461.exe,改为自定义名称(该名字就是注册后的服务名)

WinSW.NET461.exe -->  whsingleshoot-server.exe

2)创建whsingleshoot-server.xml配置文件(内容如下)

<service>

  <!-- 服务 ID(唯一标识符,用于注册服务名,不可包含空格) -->
  <id>whsingleshoot-server</id>

  <!-- 服务显示名称(在服务管理器中看到的名称) -->
  <name>whsingleshoot-server</name>

  <!-- 服务描述(在服务管理器的描述栏显示) -->
  <description>五昊智能报靶系统服务</description>

  <!-- 要执行的主程序,这里是调用 java 命令 -->
  <executable>java</executable>

  <!-- 启动参数,这里是运行一个 .jar 包(注意路径要加引号,防止空格或特殊字符出错) -->
  <arguments>-jar "S:\My-Shoot-Server\whsingleshoot-system.jar"</arguments>

  <!-- 设置服务启动类型为“自动”,即开机自动启动 -->
  <startmode>Automatic</startmode>

  <!-- 日志文件存放路径 -->
  <logpath>S:\My-Shoot-Server\logs</logpath>

  <!-- 日志策略:按日期滚动日志 -->
  <log mode="roll-by-time">
    <!-- 日志文件的命名模式(如 logs/whsingleshoot-server.20250626.log) -->
    <pattern>yyyyMMdd</pattern>
  </log>
</service>

3)注册安装服务:

  • myapp.exe install: 安装服务
  • myapp.exe start :启动服务
S:\My-Shoot-Server>whsingleshoot-server.exe install
2025-06-26 23:18:13,289 INFO  - Installing service 'whsingleshoot-server (whsingleshoot-server)'...
2025-06-26 23:18:13,310 INFO  - Service 'whsingleshoot-server (whsingleshoot-server)' was installed successfully.

S:\My-Shoot-Server>whsingleshoot-server.exe start
2025-06-26 23:18:21,584 INFO  - Starting service 'whsingleshoot-server (whsingleshoot-server)'...
2025-06-26 23:18:22,180 INFO  - Service 'whsingleshoot-server (whsingleshoot-server)' started successfully.

查看windows系统服务是否已注册启动:

3. ⚓Winsw配置文件说明

配置标签说明:
  1. 基本信息:
    1. <id>:服务ID,系统唯一标识(不能有空格)
    2. <name>:显示名称,服务管理可见
    3. < description >:描述,可见于服务说明
  2. 执行信息:
    1. < executable>:运行程序启动头部(如:java、node、python等)
    2. <arguments>: 启动时传递的参数,路径建议加引号
    3. <workingdirectory>: 程序运行时的工作目录,方便有些程序需要在特定目录下启动
  3. 启动发生:
    1. <startmode>:服务启动模式
      1. Automatic:自动模式
      2. Manual:手动模式
    2. <depend>:服务依赖, 指定此服务所依赖的其他服务的ID。当服务X依赖于服务Y时,X只能在Y正在运行时运行,例如:java程序运行前需要先启动Mysql和Redis服务
  4. 故障恢复:
    1. <onfailure>:程序异常退出后的操作,如自动重新启动,属性如下
      1. action属性: 可选值:restart(重新启动)、none(不做如何操作)
      2. delay属性: 重启前等待时间,如 "10 sec"
  5. 停止控制:
    1. <stopexecutable>:服务停止时再运行启动程序头部(主要用于服务停止之后执行其他操作)
    2. <stoparguments>: 停止时的命令参数
    3. <stopTimeout>: 停止等待的最长时间(如:30 sec)
  6. 附操作:
    1. <prestart>:  服务启动时和主进程启动之前执行
    2. <prestop>:  在服务启动时和主进程启动后执行
    3. <poststop>: 服务停止时和主进程停止之前执行

📋 日志配置:

日志标签 说明
<logpath> 日志文件存放路径
<log mode="..." /> 日志滚动策略,支持:

• none(不记录日志)

• append(默认)

• roll-by-size(按文件大小切割)

• roll-by-time(按时间切割)

<pattern> 时间滚动日志命名模式(yyyyMMdd 等)
<sizeThreshold> 日志大小阈值(单位 KB)
<keepFiles> 保留日志数量上限

重点说明:

1)<depend>依赖:指定此服务所依赖的其他服务的ID。当服务X依赖于服务Y时,X只能在Y正在运行时运行

多个元素可用于指定多个依赖项:

<depend>Eventlog</depend>
<depend>W32Time</depend>
2)附操作
<prestart>
  <!--处理标签-->
  <executable></executable>
  <arguments></arguments>
  <stdoutPath></stdoutPath>
  <stderrPath></stderrPath>
</prestart>
  • stdoutPath指定将标准输出重定向到的路径。
  • stderrPath指定将标准错误输出重定向到的路径。
① pre-start命令在服务启动时和主进程启动之前执行。
<poststart>
  <!-- ... -->
</poststart>
② post-start命令在服务启动时和主进程启动后执行。
<prestop>
  <!-- ... -->
</prestop>
③ pre-stop命令在服务停止时和主进程停止之前执行。
<poststop>
  <!-- ... -->
</poststop>
3)<stoptimeout>:延迟停止

当请求服务停止时,winsw首先尝试向控制台应用程序发送Ctrl+C信号,或者向Windows应用程序发布关闭消息,然后等待最多15秒,让进程自己优雅地退出。如果超时或信号或消息无法发送,则winsw立即终止服务。

此可选元素允许您更改此“15秒”值,以便您可以控制winsw为服务关闭自身提供多长时间

<stoptimeout>10sec</stoptimeout>
4)<onfailure>:故障处理

这个可选的可重复元素控制winsw启动的进程失败时的行为(即以非零退出代码退出)

<onfailure action="restart" delay="10 sec"/>
<onfailure action="restart" delay="20 sec"/>
<onfailure action="reboot" />

例如,上述配置导致服务在第一次失败后10秒内重新启动,在第二次失败后20秒内重新启动,然后如果服务再次失败,Windows将重新启动。

每个元素都包含一个强制action属性,它控制Windows SCM将执行的操作,以及可选的delay属性,它控制直到采取操作的延迟。操作的法定值是:

  • restart:重启服务
  • reboot:重启Windows。将显示带有CRITICAL_PROCESS_DIEDbug校验码的蓝屏
  • none:什么都不做,让服务停止

延迟属性可能的后缀是 sec/secs/min/mins/hour/hours/day/days(秒/秒/分钟/分钟/小时/小时/天/天)。如果缺少,延迟属性默认为0。

如果服务一直失败并且超出了配置的<onfailure>数量,将重复最后一个操作。因此,如果您只想始终自动重启服务,只需指定一个<onfailure>元素,如下所示:

<onfailure action="restart" />
案例:现在有 Spring Boot 项目 whshoot.jar,部署在 S:\My-Shoot-Server 目录下。程序运行依赖于 MySQL 和 Redis 服务(必须先启动)。
要求:
  1. 开机自启动
  2. 以专有用户身份运行服务(账号 mysvc)
  3. 设置环境变量(如 JAVA_HOME)
  4. 日志按天滚动,保留最近 10 天
  5. 程序启动前,再启动一个python程序(shoot.py)
  6. 程序崩溃后 10 秒自动重启
  7. 优雅停止程序(调用 java -jar myapp.jar stop)
  8. 停止超时时间 60 秒
  9. 日志保存在 S:\My-Shoot-Server\logs
<service>

  <!-- 唯一服务 ID(注册名) -->
  <id>whshoot-service</id>

  <!-- 在服务管理器中显示的名称 -->
  <name>智能报靶服务</name>

  <!-- 服务的描述信息 -->
  <description>这是一个springBoot服务,依赖Mysql和Redis</description>

  <!-- 执行的命令程序,这里是 java -->
  <executable>java</executable>

  <!-- 程序启动参数,运行 myapp.jar -->
  <arguments>-jar "S:\My-Shoot-Server\whshoot.jar"</arguments>

  <!-- 程序运行的工作目录(相对路径行为会受它影响) -->
  <workingdirectory>D:\apps\myapp</workingdirectory>

  <!-- 服务依赖项:必须在 mysql 和 redis 启动后才能启动 -->
  <depend>MySQL</depend>
  <depend>Redis</depend>

  <!-- 服务启动方式:自动随系统启动 -->
  <startmode>Automatic</startmode>

  <!-- 主应用启动时启动 shoot.py -->
  <prestart>
    <executable>python</executable>
    <arguments>shoot.py</arguments>
  </prestart>

  <!-- 主应用停止服务前先杀掉 shoot.py -->
  <prestop>
    <executable>cmd</executable>
    <arguments>/c taskkill /f /im python.exe /t</arguments>
  </prestop>

  <!-- 环境变量(可多个) -->
  <env name="JAVA_HOME" value="C:\Program Files\Java\jdk-17"/>
  <env name="SPRING_PROFILES_ACTIVE" value="prod"/>

  <!-- 日志目录 -->
  <logpath>D:\apps\myapp\logs</logpath>

  <!-- 日志策略:按天滚动 -->
  <log mode="roll-by-time">
    <pattern>yyyy-MM-dd</pattern>         <!-- 每天一个日志文件 -->
    <keepFiles>10</keepFiles>             <!-- 最多保留10个日志文件 -->
  </log>

  <!-- 程序崩溃后的处理策略,10秒之后重新启动 -->
  <onfailure action="restart" delay="10 sec"/>

  <!-- 服务停止时执行的命令(用于优雅关闭服务) -->
  <stopexecutable>java</stopexecutable>
  <stoparguments>-jar "D:\apps\myapp\myapp.jar" stop</stoparguments>

  <!-- 停止超时时间(60秒内未退出将强制结束) -->
  <stopTimeout>60 sec</stopTimeout>

  <!-- 以指定账号运行服务(注意账户权限,避免启动失败) -->
  <serviceaccount>
    <domain>.</domain>          <!-- 本地机器 -->
    <user>mysvc</user>          <!-- 本地用户 -->
    <password>mysecurepassword</password>  <!-- 密码(可配合 Windows 密码管理) -->
  </serviceaccount>
</service>

路漫漫其修远兮,吾将上下而求索