Windows 下将 Hermes Agent 部署为系统服务

在 Windows 上运行 AI Agent 网关通常需要一直开着终端窗口,既不美观也不稳定。
本文介绍如何在 Windows 10/11 上,使用 NSSM (Non-Sucking Service Manager) 将 Hermes Agent 封装为系统服务,并解决 Unicode 编码、工作目录、运行账户等常见问题。

1. 安装 Hermes Agent

假设已通过官方文档完成 Hermes Agent 的安装,Python 虚拟环境位于:

1
C:\Users\<用户名>\AppData\Local\hermes\hermes-agent\venv\

启动入口为虚拟环境中的 hermes.exe

2. 安装 NSSM

使用 Windows 自带的包管理器 winget 安装:

1
winget install NSSM.NSSM --source winget

安装完成后验证:

1
nssm version

3. 配置 Windows 服务 (核心步骤)

3.1 定义路径

1
2
3
4
5
$HERMES = "$env:LOCALAPPDATA\hermes\hermes-agent\venv\Scripts\hermes.exe"
$LOGDIR = "$env:LOCALAPPDATA\hermes\logs"

# 创建日志目录
if (!(Test-Path $LOGDIR)) { mkdir $LOGDIR }

3.2 创建服务

1
nssm install hermes-gateway "$HERMES" "gateway"

注意: 参数使用 gateway 即可,无需加 run

3.3 设置工作目录

这是最关键的一步。服务的工作目录必须指向 Hermes 的数据目录,否则配置文件和状态文件无法正确加载:

1
nssm set hermes-gateway AppDirectory "$env:LOCALAPPDATA\hermes"

警告: 默认 NSSM 会将 AppDirectory 设为 C:\Users\<用户名>,这会导致 Hermes 找不到 ~/.hermes/ 下的配置。

3.4 设置日志输出

1
2
3
4
5
# 标准输出日志
nssm set hermes-gateway AppStdout "$LOGDIR\gateway-stdout.log"

# 错误输出日志
nssm set hermes-gateway AppStderr "$LOGDIR\gateway-stderr.log"

3.5 设置 UTF-8 编码环境变量

Hermes 使用 Python 编写,启动时会输出包含 emoji 和特殊 Unicode 字符的 Banner。
Windows 服务默认使用 GBK 编码,会导致 UnicodeEncodeError: 'gbk' codec can't encode character 崩溃。

必须设置环境变量强制使用 UTF-8:

1
nssm set hermes-gateway AppEnvironmentExtra "PYTHONUTF8=1" "PYTHONIOENCODING=utf-8"

注意: 必须一次性设置两个变量,分两次执行会导致后者覆盖前者。

3.6 设置崩溃自动重启

1
nssm set hermes-gateway AppRestartDelay 5000

服务崩溃后 5 秒自动重启,实现无人值守运行。

3.7 设置登录账户

默认 NSSM 服务以 LocalSystem 账户运行,无法访问当前用户目录下的配置文件。
需要改为当前 Windows 用户:

1
nssm set hermes-gateway ObjectName ".\用户名" "密码"

或者通过 GUI 界面设置:

1
nssm edit hermes-gateway
  1. 切换到 Log on (登录) 选项卡
  2. 选择 This account (此账户)
  3. 输入 Windows 用户名和密码
  4. 点击 Edit service 保存

3.8 设置开机自启

1
nssm set hermes-gateway Start SERVICE_AUTO_START

4. 启动服务与验证

1
nssm start hermes-gateway

检查服务状态:

1
nssm status hermes-gateway

输出 SERVICE_RUNNING 表示正常。

查看日志确认无异常:

1
2
3
4
5
# 查看错误日志
type "$env:LOCALAPPDATA\hermes\logs\gateway-stderr.log"

# 查看标准输出日志
type "$env:LOCALAPPDATA\hermes\logs\gateway-stdout.log"

5. 常见问题排查

5.1 Unicode 编码崩溃

症状: 服务启动后立即停止,日志中出现:

1
UnicodeEncodeError: 'gbk' codec can't encode character '\u2695' in position 12

原因: 服务使用 GBK 编码,无法输出 Hermes 启动 Banner 中的特殊字符。

解决: 参见 3.5 设置 UTF-8 编码环境变量

5.2 工作目录不正确

症状: 日志中提示配置加载失败,或者服务找不到状态文件。

原因: NSSM 默认工作目录为 C:\Users\<用户名>,不是 Hermes 的数据目录。

解决:

1
2
nssm set hermes-gateway AppDirectory "$env:LOCALAPPDATA\hermes"
nssm restart hermes-gateway

5.3 服务卡在 STOP_PENDING 或 PAUSED

症状: nssm start 返回 SERVICE_PAUSED 或无响应。

原因: 旧进程未正常退出,PID 文件残留。

解决:

1
2
3
4
5
6
7
8
# 停止服务
nssm stop hermes-gateway

# 删除残留的 PID 文件
Remove-Item "$env:LOCALAPPDATA\hermes\gateway.pid" -Force

# 重新启动
nssm start hermes-gateway

5.4 配置警告 (非错误)

启动后日志可能出现以下警告,不影响服务运行:

1
2
WARNING gateway.run: No user allowlists configured.
WARNING gateway.run: No messaging platforms enabled.

这是功能配置提示,需要在 ~/.hermes/.env 中配置 GATEWAY_ALLOW_ALL_USERS=true 或在配置文件中启用消息平台(如 Telegram、WhatsApp 等)。

完整配置参考

所有配置步骤汇总如下(PowerShell 管理员模式执行):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$HERMES = "$env:LOCALAPPDATA\hermes\hermes-agent\venv\Scripts\hermes.exe"
$LOGDIR = "$env:LOCALAPPDATA\hermes\logs"
if (!(Test-Path $LOGDIR)) { mkdir $LOGDIR }

# 创建服务
nssm install hermes-gateway "$HERMES" "gateway"

# 设置工作目录
nssm set hermes-gateway AppDirectory "$env:LOCALAPPDATA\hermes"

# 设置日志
nssm set hermes-gateway AppStdout "$LOGDIR\gateway-stdout.log"
nssm set hermes-gateway AppStderr "$LOGDIR\gateway-stderr.log"

# 设置 UTF-8 环境变量
nssm set hermes-gateway AppEnvironmentExtra "PYTHONUTF8=1" "PYTHONIOENCODING=utf-8"

# 崩溃自动重启
nssm set hermes-gateway AppRestartDelay 5000

# 设置登录账户(替换用户名和密码)
nssm set hermes-gateway ObjectName ".\用户名" "密码"

# 开机自启
nssm set hermes-gateway Start SERVICE_AUTO_START

# 启动服务
nssm start hermes-gateway

常用管理命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 停止服务
nssm stop hermes-gateway

# 重启服务
nssm restart hermes-gateway

# 删除服务
nssm remove hermes-gateway confirm

# 查看状态
nssm status hermes-gateway

# 查看完整配置
nssm dump hermes-gateway

# 打开 GUI 编辑界面
nssm edit hermes-gateway

# 实时查看错误日志
Get-Content "$env:LOCALAPPDATA\hermes\logs\gateway-stderr.log" -Wait -Tail 20