WinSW のファイルを deploy/ へ移す

ルート直下に並ぶサービス関係の 3 ファイルと登録スクリプトを、フォルダ規約どおり deploy/ へ移す。サービスの再登録が要るため、影響範囲と手順を先に固める

📅 作成: 2026-10-06 / 更新: 2026-10-07

i260830-01 の実装計画。移すこと自体は単純だが、本番のサービスを一度止めて登録し直す作業を含む。管理者権限が要り、止めている間は他プロジェクトの待受けが切れるため、実施の前に決めておく点と手順をここにまとめる。

決まったこと: 1-B (スクリプトも deploy/ へ移す)・2-B (arguments に ..\ を足す)・3-A (時刻を決めて周知してから実施する)。ガードを足す。実施済み (2026-10-07 06:40〜06:41)。結果は 5 章の末尾。

目次

  1. 何を移すか
  2. 調べたこと (影響範囲)
  3. 決めること
  4. 実施の手順
  5. 確かめること

何を移すか

共通ルール「プロジェクトフォルダ構成」は、デプロイ定義の置き場を deploy/ と定めている。いまは WinSW 関係の 3 ファイルがルート直下に並び、登録・解除のスクリプト 2 本は tools/70_deploy/ にある。

ファイル役目Git
node-ai-chat-lite-winsw.exeWinSW 本体。サービスとして登録される実行体管理外
node-ai-chat-lite-winsw.xmlサービス定義。WinSW が自分と同じ名前の XML を隣から読む管理
node-ai-chat-lite.exenode.exe のコピー (約 99 MB)。プロセス名で他の Node と見分けるため管理外
tools/70_deploy/install-service.cmd
tools/70_deploy/uninstall-service.cmd
サービスの登録・解除 (SJIS)管理

5 つとも deploy/ へ移す。名前は変えない。サービス名 (node-ai-chat-lite)もプロセス名も変わらないため、sc query node-ai-chat-lite や Stop-Process -Name node-ai-chat-lite の書き方は今までどおり使える。移したあと tools/70_deploy/ は空になり、なくなる。

いまの稼働状況

サービス node-ai-chat-lite は自動起動で稼働中。sc qc で確かめた登録先は、実体のフォルダ直下の node-ai-chat-lite-winsw.exe(C:\ (実体のパス)\ai-chat-lite\node-ai-chat-lite-winsw.exe。2026-10-06 時点)。

移すと登録先が変わるため、サービスの再登録 (uninstall → install)が要る。登録時に記録された ImagePath は、あとから書き換えない限り古い場所を指したままになる。メンテナンスの印や restart では代わりにならない。

調べたこと (影響範囲)

名前を変えるのではなく置き場を変えるため、「古い場所を指している箇所」を全体から探した。

影響を受けない

直す必要がある

場所いま直すこと
node-ai-chat-lite-winsw.xmlarguments が src\server\main.mjs、logpath が %BASE%\logs。コメントに「ルートに置いてあれば」とあるdeploy/ へ移し、arguments を ..\src\server\main.mjs、logpath を %BASE%\..\logs にする (2-B)。executable は変えない。コメントも直す
tools/70_deploy/install-service.cmd
uninstall-service.cmd
呼び先が %~dp0..\..\node-ai-chat-lite-winsw.exe。コメントに廃止した N: ドライブの記述が残っているdeploy/ へ git mv し、呼び先を %~dp0node-ai-chat-lite-winsw.exe にする (1-B)。コメントは X: のような subst ドライブという一般の言い方にする。ガードを足す (4 章)。SJIS なので convert-encoding で UTF-8 にしてから Edit し、すぐ戻す
利用者に出す文言
(node 版 2 か所・Rust 版 2 か所)
chat.mjs の 464 行・1221 行、main.rs の 360 行、commands.rs の 954 行が node-ai-chat-lite-winsw.exe status / start をパスなしで案内している移したあと、ルートからは見つからない。deploy\node-ai-chat-lite-winsw.exe と書く。2 本とも直し、突き合わせテストで食い違いを見る
tools/50_run/start-server.ps1コメントに node-ai-chat-lite-winsw.exe stopコメントのパスを合わせる
README.html5 か所 (exe の置き方の表と Copy-Item … .\node-ai-chat-lite.exe、登録・解除の tools\70_deploy\… の 2 か所、ポートを変える手順の XML 名)deploy/ での置き方に直す
p260829-01-設計.htmlフォルダ構成の図 (tools/70_deploy/ の行を含む)、「サービスとして常駐させる」の節 (関係ファイルをルート直下に並べる理由・XML の例・logpath の注意)、スクリプトを指す文実装したものが正になるよう、置き場と XML の例を最新にする

WinSW 本体と node-ai-chat-lite.exe は、サービスが走っている間は動かせない。先にサービスを止めて登録を解除してから移す。走っている exe は名前を変えられるが、サービスの登録先を書き換える手段が無いので、結局は再登録になる。

決めること

決める点が 3 つある。番号は以降の章でもそのまま使う。3 つとも決まった (1-B・2-B・3-A)。

1. 登録スクリプトの置き場 (決定: 1-B)

案内容長所短所
1-A
tools/70_deploy のまま
呼び先だけ %~dp0..\..\deploy\ に変える共通ルールの番号付きフォルダ (tools/70_deploy)に沿う課題にある「%~dp0 だけにする」は実現しない
1-B (決定)
deploy/ へ一緒に移す
2 本のスクリプトも deploy/ に置き、呼び先を %~dp0 だけにする3 ファイルとスクリプトが 1 か所にまとまり、登録・解除・定義が deploy/ を開けば揃う。パスが最短になる実行するものが tools/ に無くなる。README・設計書の説明を直す

2. 作業フォルダの扱い (決定: 2-B)

案内容長所短所
2-A
作業フォルダを明示
executable を %BASE%\node-ai-chat-lite.exe、<workingdirectory>%BASE%\..</workingdirectory> を足し、arguments は変えない。logpath は %BASE%\..\logs子プロセスの作業フォルダを自分で決める未確認が 2 つ増える。<workingdirectory> が WinSW 2.12 で効くことと、executable で %BASE% が展開されること (logpath では展開されている実績がある)。作業フォルダをルートにすると、相対の executable がルート基準で探される恐れがあり、executable の変更が要る
2-B (決定)
課題どおり arguments に ..\ を足す
arguments を ..\src\server\main.mjs、logpath を %BASE%\..\logs にする。executable はそのままXML に足すのは 2 か所だけ。課題の記述どおり。前提は 1 つで、現状から裏付けがある子プロセスの既定の作業フォルダが WinSW の置き場であることに頼る。いま src\server\main.mjs が相対のまま動いていることから、作業フォルダは WinSW の置き場 (ルート)と分かる。移したあとは deploy/ になる。WinSW の既定の決まり方そのものは未確認

2-B で外れたとき。node が main.mjs を見つけられず、サービスは数秒で異常終了する。onfailure で 10 秒おきに再起動を繰り返し、logs/ の err.log に Cannot find module が出る。すぐ分かるので、4 章の「うまくいかなかったとき」で戻す。

3. 実施のしかた (決定: 3-A)

案内容長所短所
3-A (決定)
時刻を決めて周知してから
利用者が管理者として実行できる時刻を決め、実施の前に public ルームへ周知する。事前に控え (backup.ps1)を取る止まる時間を相手が知っている。他プロジェクトの待受けは親が張り直す決まりなので、周知があれば原因不明の exit 255 に見えない周知の案を出して確認を取る手間が増える
3-B
周知なしで実施
控えだけ取って、すぐに実施する手間が少ない他プロジェクトの待受けが予告なく切れ、他の AI が「サーバーが落ちた」原因を自分で調べに行くことになる

3-A の周知案は次のとおり。送る前にこの案で確認を取る。

管理者権限での実行は利用者が行う。AI エージェントは UAC の確認を出せない。実施の前に、実行する 2 本のスクリプトと実行順を提示する。

実施の手順

1-B・2-B・3-A を前提にする。停止時間を短くするため、新しい XML とスクリプトは停止の前に deploy/ へ用意する。ルートの XML は触らない。WinSW は起動のたびに XML を読み直すため、稼働中に書き換えると、異常終了後の自動再起動で新しい内容を読んでしまう。

事前準備 (サービス稼働中)

順すること実行する人
P1全テストを実行する (既知の失敗は i260928-02 の 3 件と、bun test の i260916-01)AI
P2tools/80_ops/backup.ps1 -Kind daily で控えを取る。サービスを止めずに実行でき、_backup/daily/chat-yyyymmdd-hhmmss.db.zip に出るAI
P3deploy/node-ai-chat-lite-winsw.xml を新規に作る (2-B の arguments・logpath・コメント)AI
P4deploy/install-service.cmd と deploy/uninstall-service.cmd を新規に作る (ガード付き。下の表)。deploy/ に exe が無いあいだは、必要ファイルのガードで止まるので、間違えて動かしても何も起きないAI
P53-A の場合は、周知案で確認を得てから public ルームへ送るAI

停止中

順すること実行する人
1管理者として、現行の tools\70_deploy\uninstall-service.cmd を実行する (stop → uninstall)。ここから他プロジェクトの待受けが切れる利用者
2node-ai-chat-lite-winsw.exe と node-ai-chat-lite.exe を deploy/ へ Move-Item(追跡外。同じドライブ内の移動なので 99 MB でもすぐ終わる)。ルートの XML と、tools/70_deploy/ の旧スクリプト 2 本を git rmAI
3管理者として、deploy\install-service.cmd を実行する (install → start)。実体のフォルダ (C: 側)から実行する利用者
45 章の確認を行うAI
5利用者に出す文言 (node 版・Rust 版)、README・設計書・status・課題を直す。node 版・Rust 版の両方を直し、突き合わせテストを通す。Rust 版は install-aichat.mjs まで行うAI

停止時間は、1 の stop から 3 の start までで、実測していない。AI の作業は移動 2 件・削除 1 件・git rm 2 件だけなので、数十秒から数分と見込んでいる。aichat wait は繋がらないあいだ 10 秒おきに最大 60 回 (約 10 分)粘る (options.mjs の RETRY_TIMES.wait)。10 分以内に戻れば他プロジェクトは気づかない見込みだが、停止の瞬間に待っていた接続の挙動は実測していない。

登録スクリプトのガード

両方のスクリプトの頭で、次の順に確かめ、満たさなければメッセージを出して終了コード 1 で止める。実際の WinSW を呼ぶ前に必ず止まる順にしている。

順確かめること書き方対象
1C: ドライブから実行しているif not "%~d0" == "C:" (echo C:ドライブで実行してください。& …)。いまのスクリプトにもある。subst のドライブはサービスから見えず、ImagePath に記録されると起動に失敗するためinstall・uninstall
2必要なファイルが隣にあるif not exist "%~dp0node-ai-chat-lite-winsw.exe" (…)。install は node-ai-chat-lite-winsw.exe・node-ai-chat-lite-winsw.xml・node-ai-chat-lite.exe の 3 つ、uninstall は WinSW 本体だけ。移す前に動かしても、実体を呼ばずに止まるinstall・uninstall
3すでに登録されていないsc query node-ai-chat-lite >nul 2>&1 が成功したら「登録済みです。先に uninstall-service.cmd を実行してください。」。古い ImagePath のまま入れ直すのを防ぐinstall のみ
4管理者として実行しているfltmc >nul 2>&1 が失敗したら「管理者として実行してください。」。この非管理者のシェルでは fltmc が終了コード 1、net session が 2 を返すことを実測した (管理者のときに 0 を返すかは、実機での実行で確かめる)install・uninstall

うまくいかなかったとき

サービスが上がらなければ、3 ファイルを deploy/ からルート直下へ戻し、ルートの XML を git restore し、旧スクリプトを tools/70_deploy/ へ戻して、登録し直す。データ (_data)は移動の対象ではないので、戻しても失われるものは無い。手順 1 から 3 の間は止まっているため、長引かせずに戻す。

確かめること

サービスの登録は自動で動く部分なので、手元での手動実行では確かめたことにならない。実機で再登録して、結果を見るまで課題を「済」にしない。

  1. sc qc node-ai-chat-lite の BINARY_PATH_NAME が …\ai-chat-lite\deploy\node-ai-chat-lite-winsw.exe になっている
  2. sc query node-ai-chat-lite が RUNNING で、aichat who がサーバーから応答を返す
  3. ログがルート直下の logs/ に出ている(…-winsw.out.log・.err.log・.wrapper.log の更新時刻が再登録のあと)。deploy/logs/ や C:\Windows\System32\Logs に出ていない。2-B の前提 (作業フォルダが deploy/)が当たっていれば、err.log に Cannot find module が出ない
  4. プロセスがタスクマネージャーに node-ai-chat-lite.exe として現れる (psls node-ai-chat-lite)。親は node-ai-chat-lite-winsw.exe
  5. 他プロジェクトの待受けが張り直され、aichat waiters に並ぶ
  6. ガードが動く (AI が非管理者のシェルで確かめる。fltmc が失敗することを先に確認してから呼ぶ)。C: 以外のパス (W: など)から deploy\install-service.cmd nopause を呼ぶと 1 のメッセージで止まる。手順 2 のあと(登録が解除され、3 つのファイルが揃った状態)に実体のパスから呼ぶと、管理者でないため 4 のメッセージで止まる。手順 3 のあと (登録済み)に呼ぶと 3 のメッセージで止まる
  7. 全テストが通る。利用者に出す文言を直した分は、cli-rs.test.mjs と compare-cli.mjs の突き合わせで食い違いが出ない
  8. (任意)PC を再起動して、サービスが自動で上がる。startmode は Automatic のため、登録先が変わっても上がるはずだが、実測はしていない

実施の結果 (2026-10-07)

停止は 06:40:37、開始は 06:41:28 で、止まっていたのは約 51 秒。上の項目の順に、実測した結果を書く。

項目結果実測した内容
1✅ 合格BINARY_PATH_NAME が …\ai-chat-lite\deploy\node-ai-chat-lite-winsw.exe、START_TYPE は AUTO_START
2✅ 合格RUNNING。aichat who が 9 人を返した
3✅ 合格logs/ の out.log・wrapper.log が 06:41:29 に更新された。err.log は 0 バイトで Cannot find module は無く、deploy/logs は作られていない。2-B の前提 (作業フォルダが deploy/)は当たっていた
4✅ 合格psls で node-ai-chat-lite-winsw.exe の下に node-ai-chat-lite.exe(別のプロセス ID)が並ぶ
5✅ 合格待受け 9 本が張り直しなしで生き残った (起動時刻が 06:39:46〜58 のまま)。繋がらないあいだの粘りで足りた
6✅ 合格C: 以外・必要なファイルが無い、は tests/deploy-scripts.test.mjs で ❌Red 6 件 → ✅Green 6 件。登録済み・管理者は、ダミーのファイルを置いた一時フォルダで終了コード 1 で止まった。実機でも、再登録の途中 (登録解除のあと)に非管理者のシェルから deploy\install-service.cmd を呼び、管理者のガードで止まった。管理者のコンソールでは、install と start が成功した
7✅ 合格突き合わせ 54 通りが全部一致、cli-rs.test.mjs・client-unreachable.test.mjs が合格
8⬜ 未実施(任意)PC の再起動後の自動起動

突き合わせ (compare-cli.mjs)は、テスト用サーバーを先に立てないと止まる。start-test-server.mjs で立て、--file はルートからの相対パスで渡し、終わったら --stop で止める。