LoginSignup
1
2

More than 1 year has passed since last update.

WinSW - 任意のプログラムをWindowsサービス化

Last updated at Posted at 2022-09-09

この記事の概要

独自でWindowsサービスとして登録する機能を持っていない、任意のコマンドをWindowsサービス化したい。

とくに Quarkus版Keycloak をターゲットにするけど、ほかにも候補があれば、それらもサービス化する。

WinSW の紹介

Windows Service Wrapper の略だそうです。

Java Service Wrapper への対抗だそうで。。
Project manifest に気付くのが遅かった)

単にKeycloakをサービス化するなら、 Java Service Wrapper でも良かったわ。

.net ベースで開発されている。

リリースバイナリ がちょっと面白くて、.netの マネージドコード ベースのものに加えて、x86とx64の実行ファイル(.netが未インストールでも動く)が提供されている。

x86とx64の建付けがどうなっているかというと、.NET Coreを含んたバイナリになっているそうな。

稼働環境にインストールされている.netのバージョンが明らかで変わる予定ないならマネージドコード版を使えばよいと思う。

インストール

例によってscoopで。

winsw3-net4.json
{
    "version": "3.0.0-alpha.10",
    "description": "A wrapper executable that can be used to host any executable as a Windows service",
    "homepage": "https://github.com/winsw/winsw",
    "license": "MIT",
    "url": "https://github.com/winsw/winsw/releases/download/v3.0.0-alpha.10/WinSW-net461.exe#/WinSw3.exe",
    "hash": "3c0671e7b6914512062895b5c96f6b9cf16a83889e235a2948379e6e329296e7",
    "bin": "WinSw3.exe",
    "checkver": "github",
    "autoupdate": {
        "url": "https://github.com/winsw/winsw/releases/download/v$version/WinSW.NET461.exe#/WinSw3.exe"
    }
}
> scoop install winsw3-net4

v3系がalpha.10で放置されているようだけど、v2系 は「実行ファイルと同名のxmlファイルを参照する」って「いけてない」つくりになっている。

馬鹿にならないサイズなのに、サービスの個数ぶんだけexeを準備するのも馬鹿らしいので、v3系を使う。
exe増やすのにシンボリックリンク使えばいい1という話は却下。

Keycloakをサービスとして登録

WinSWサービス用のxmlファイルを作成する。

keycloak.xml
<service>
  <id>keycloak</id>
  <name>Keycloak</name>
  <description>Keycloak</description>
  <workingdirectory>W:\my-service</workingdirectory>
  <executable>cmd.exe</executable>
  <arguments>/C start-keycloak.cmd</arguments>
  <log mode="rotate" />
  <onfailure action="restart" delay="300 sec" />
  <serviceaccount>
    <username>MYDOMAIN\k2ok-app</username>
    <allowservicelogon>false</allowservicelogon>
  </serviceaccount>
  <logpath>W:\my-service\keycloak\logs</logpath>
</service>

サービスとしてインストール。

> winsw3 install keycloak.xml

あとはコマンドラインで起動するのと同様にサービス起動できる。

また、マシン起動時に自動起動させることも可能。遅延開始設定も可能。

ログの出力方法も凝れるけど、とりあえず出力先を指定するくらいで触っていない。

SSHトンネル用コマンドをサービス登録

上記のとおり、XMLさえ記述すればサービス化できるので、sshのトンネルコマンドをサービス化することもできる。

MyTunnel.xml
<service>
  <id>MyTunnel</id>
  <name>My tunnel to some host</name>
  <description>My tunnel to some host using SSH</description>
  <executable>ssh</executable>
  <arguments>-N -g -R7161:127.0.0.1:7161 tunnel@some-host</arguments>
  <log mode="rotate" />
  <onfailure action="restart" delay="300 sec" />
  <serviceaccount>
    <username>MYDOMAIN\k2ok-app</username>
    <allowservicelogon>false</allowservicelogon>
  </serviceaccount>
  <logpath>W:\my-service\MyTunnel\logs</logpath>
</service>

課題

OSの再起動時に、起動してくれない場合があった。

(遅延起動は設定しているが、数時間経っても起動してくれないので意図する動作ではない)

システムログを追ってみると、Service Control Managerでサービス起動時のタイムアウト(30000 ミリ秒)になったと出ている。

非力なマシンで、起動直後の応答が悪いのも当然なので、タイムアウトの閾値を延ばす方法を探す…あった。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ControlServicesPipeTimeout 追加するとのこと。

参考: How to extend the timeout for services if they fail to start or stop

うまく起動できるようになりました。

グループポリシーでもいいそうだけど、ポリシーとして設定・配信するには躊躇する項目だ。

  1. この記事書いたあとで試してみたけど、実行ファイルパスや実行ファイル名の解決で支障があるのかサービス登録の時点で失敗した。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2