--- name: nssm-114 description: NSSM (Non-Sucking Service Manager) operations and Windows service maintenance targeting the internal host 114. Use this skill whenever the user mentions NSSM, nssm.exe, or any nssm command (install, remove, set, get, reset, dump, start, stop, restart, pause, continue, rotate, status), or asks to manage/configure/restart a Windows service that you know or suspect is an NSSM-wrapped service. Also use it when the user says "运维/管理/重启/查一下服务" in connection with 114 or an internal service. In this environment, NSSM-related ops ALWAYS target host 114 (SSH alias `114`) — never run nssm locally. Route everything through `ssh 114 "..."`. --- # NSSM Ops on Host 114 ## The core routing rule **Every NSSM operation targets host 114 over SSH.** Never run `nssm` on the local machine. - SSH alias: `114` (Windows Server host, non-interactive) - All commands go through: `ssh 114 "nssm ..."` or `ssh 114 "cmd /c ..."` / `ssh 114 "powershell -Command \"...\""` - If the user says "114" + anything about services, or just "查一下/重启一下服务" with NSSM context, that's host 114. ## How SSH to 114 actually works (read this before running anything) This is the part that bites. SSH to 114 is **non-interactive**: 1. **No session.** Each `ssh 114 "..."` is a one-shot. `stdin` is not a TTY, so you cannot open an interactive shell and type follow-ups. Run one command per invocation, or chain with `&&` / `;`. 2. **`Pseudo-terminal will not be allocated`** warnings are normal — ignore them. 3. **Bash double-quote escaping eats PowerShell `$` variables.** When you run `ssh 114 "powershell -Command \"... $_ ...\""`, bash mangles `$_` and `$var` into `\extglob` garbage, producing hundreds of errors. This is the #1 source of broken commands. - **Avoid `$_`, `$PSItem`, and any `$var` in PowerShell sent over SSH-through-bash.** - Prefer plain `cmd.exe` tools: `findstr`, `where`, `dir`, `type`, `reg query`. - If you need PowerShell, avoid pipeline `$_` (use `Where-Object`/`ForEach-Object` scriptblocks that don't reference `$_`, or filter in cmd). - For complex logic, write a `.ps1` or `.py` file to the host first (via scp or a heredoc), then run it. Don't try to cram multi-line PowerShell into a quoted `-Command`. 4. **Verify command output.** Many `nssm` subcommands print `操作成功完成` / `Set parameter ... for service ...` on success. Read what comes back before declaring done. ## Listing services (always start here when scope is unclear) ``` ssh 114 "nssm list" ``` This enumerates all NSSM-managed services on the host. If the user says "查一下服务" / "有哪些服务", run this first. ## The NSSM command reference (essentials) Full official command reference is bundled at `references/nssm-commands.md` — read it when you need exact syntax, subparameters, or less-common parameters. The everyday set: ### Lifecycle ``` nssm install [] # install nssm remove [confirm] # uninstall (confirm skips prompt) nssm start nssm stop nssm restart nssm status # 0=stopped, 1=running, etc. ``` ### Inspect config ``` nssm dump # full config as nssm set commands (great for snapshots) nssm get [] ``` ### Edit config ``` nssm set [] nssm reset [] # back to default / delete reg entry ``` Common parameters: `Application`/`AppProgram`, `AppParameters`, `AppDirectory`, `AppStdout`, `AppStderr`, `AppExit`, `AppEnvironmentExtra`, `AppEnvironment`, `AppRotateFiles`, `AppRotateBytes`, `AppRotateOnline`, `Description`, `DisplayName`, `ObjectName`, `Start`, `Type`, `DependOnService`. ### Service controls ``` nssm pause # SERVICE_PAUSE_PENDING capable nssm continue nssm rotate # online log rotation (needs AppRotateFiles + AppRotateOnline) ``` ## NSSM gotchas (these will save you) ### Gotcha 1 — `AppEnvironmentExtra` replaces, it does not append `nssm set AppEnvironmentExtra ` writes the **entire** environment block. Calling it multiple times in a row (e.g. chained with `&&`) wipes everything except the last value. The official docs confirm: > When setting an environment block with `nssm set`, each variable should be specified as a KEY=VALUE pair in a separate argument. **Correct — all variables in ONE call:** ``` nssm set AppEnvironmentExtra VAR1=v1 VAR2=v2 VAR3=v3 ``` **Wrong — only VAR3 survives:** ``` nssm set AppEnvironmentExtra VAR1=v1 && nssm set AppEnvironmentExtra VAR2=v2 && nssm set AppEnvironmentExtra VAR3=v3 ``` Before adding env vars, snapshot the current block so you can include existing entries: ``` ssh 114 "nssm get AppEnvironmentExtra" # or: reg query ...\Parameters /v AppEnvironmentExtra ``` ### Gotcha 2 — what `nssm dump` prefixes mean `nssm dump ` prints each env var with a prefix that encodes its semantics: - `:NAME=value` — **conditional**: set only if not already present in the process environment. Won't override a value inherited from the machine/user environment. - `+NAME=value` — **override**: force-set, replacing any inherited value. The raw registry (`reg query`) stores values without these prefixes; the prefix is NSSM's display convention. If you need a service-level env var to **override** a machine-level one (very common for proxies), make sure it shows as `+` in `nssm dump`, i.e. write it without a leading `:` in the `nssm set` value. ### Gotcha 3 — restart to apply env/log/path changes `nssm set` only edits the registry. The running process won't pick up `AppParameters`, `AppDirectory`, `AppEnvironmentExtra`, log paths, etc. until you **restart** the service. Snapshot logs first if the service is mid-task: ``` ssh 114 "nssm restart " ``` ### Gotcha 4 — LocalSystem vs user-account services Most NSSM services run as `LocalSystem`, which can't access network shares or the current user's profile/credentials. If a service needs LAN file access, it runs as a real account (e.g. `.\peng`). Check with `nssm get ObjectName` before assuming network access works the same way as your shell. ## Working safely on a production host 114 runs real services. Before mutating state: 1. **Snapshot first.** `nssm dump > before.txt` (or capture relevant `nssm get` output) so you have an exact rollback recipe. 2. **One change at a time**, verify output, then move on. 3. **Prefer `nssm restart`** over stop+start; it's atomic from NSSM's perspective. 4. **Tail logs** after changes: `nssm get AppStdout` / `AppStderr` to find the log paths, then read the tail for new errors. 5. **Rollback** = re-run the snapshot's `nssm set` lines, or `nssm reset` the parameter, then restart. ## When to read the bundled reference Read `references/nssm-commands.md` when you need: - Exact subparameter syntax for `AppExit`, `AppEnvironment(Extra)`, `DependOnService`, `ObjectName`, `Start`, `Type` - The full list of native vs non-standard parameters - Priority class constants for `AppPriority` - Confirmation that a parameter exists before guessing Do NOT read it for the everyday lifecycle/config commands above — those are the hot path.