将 Anyy 作为常驻服务运行
Anyy 是一个常驻、本地优先的个人助理。你既可以直接在终端里运行它,也可以 让它始终在线,从而在没有打开任何终端时仍能接收消息、执行计划任务。本页是把 Anyy 作为常驻服务运行、以及管理网关生命周期的权威参考。
如果你还没有安装 Anyy,请先阅读安装。
前台运行 vs 常驻运行
Anyy 有两种运行方式:
- 前台运行 —— 你在终端里运行
anyy。TUI 可能仅为当前会话启动一个临时的 进程内网关。关闭终端后网关随之停止,于是入站消息和计划任务都不再被处理。这非常 适合体验功能和一次性的工作。 - 常驻运行 —— 一个轻量的后台服务让网关在重启和注销后依然运行。一旦你接入了消息 渠道,或依赖提醒、cron、心跳等功能,就需要这种方式。即便没有打开任何终端,你的 助理也能保持在线、随时可达。
安装 Anyy 本身绝不会自行启动后台服务,而一条普通的 anyy 命令在未经
询问的情况下也绝不会安装服务。转为常驻是你通过 anyy gateway start 做出的
明确选择(或者在 anyy setup 过程中接受相应提示)。
需要常驻网关的功能:
- 在没有打开终端时接收渠道消息(例如微信)
- 由网关托管的 cron、提醒、心跳和后台任务
- 任何期望运行时持续可用的客户端
网关生命周期
网关(gateway) 是常驻运行时,负责托管渠道、后台任务,以及其他 Anyy 命令
所对接的本地 RPC 接口。Anyy 会通过一个很小的命令组替你管理它 —— 你无需直接
调用 systemctl、launchctl 或 init 脚本:
anyy gateway start [--home PATH]
anyy gateway restart [--home PATH]
anyy gateway status [--home PATH]
anyy gateway stop [--home PATH]
各子命令的作用:
start—— 确保后台服务已为所解析的 home 安装,然后启动它。如果服务已在运行, 则为一次空操作并报告成功。它会等待网关变为可达,然后才报告Gateway: running。restart—— 刷新并重启服务。如果尚不存在服务,则安装并启动一个,而不是直接 报错。stop—— 停止正在运行的服务(服务定义仍保留安装状态,因此下次开机或start会再次拉起它)。status—— 报告服务与运行时状态,且没有任何副作用。它绝不会安装、启动或 重启任何东西。
这些命令只管理所解析 home 的 Anyy 服务,并不是一个通用的服务管理器。
服务定义始终启动同一个受监管的入口,并显式传入所解析的 home:
<home>/bin/anyy __gateway --home <home>
__gateway 是服务所使用的内部受监管运行时入口。你不要手动运行它 —— 请使用
anyy gateway start。
使用哪个 home
所解析的 home 目录按以下优先级确定:
--home PATH标志ANYY_HOME环境变量- 默认值 —— 普通用户安装为
~/.anyy,以 root 运行时为/root/.anyy(当没有以其他方式解析出 home 时,/root/.anyy是内置的回退值)
所有服务定义、运行时套接字、会话、状态,以及 Anyy 自身的日志都存放在这个 home 之下。
作为服务运行
anyy gateway start 会自动选择正确的宿主服务管理器:
| 宿主 | 服务管理器 | 生成的定义 |
|---|---|---|
| macOS | launchd 用户 代理 | ~/Library/LaunchAgents/com.anyy.anyy.plist |
带 systemctl 的 Linux | systemd 用户 单元 | ~/.config/systemd/user/anyy.service |
OpenWrt(存在 /etc/openwrt_release) | procd init 脚本 | /etc/init.d/anyy |
在其他任何宿主上,你会得到可操作的提示,而不是悄无声息地失败:
Background service is not supported on this host yet.
Use anyy gateway start on macOS, systemd user Linux, or procd hosts.
在每个平台上推荐的方式都是 anyy gateway start —— 它会写入正确的定义、启用它、
启动它,并验证网关是否可达。下面的各平台小节展示了 Anyy 生成的确切定义(以及
用于系统级安装的随仓库附带的参考模板),让你清楚磁盘上会落下什么内容。
Linux (systemd)
在带 systemctl 的 Linux 宿主上,anyy gateway start 会在
~/.config/systemd/user/anyy.service 安装并启用一个 systemd 用户单元。这是
默认方式,无需 root。生成的单元为:
[Unit]
Description=Anyy Gateway service
After=network-online.target
[Service]
Type=simple
ExecStart="/home/you/.anyy/bin/anyy" "__gateway" "--home" "/home/you/.anyy"
WorkingDirectory=/home/you/.anyy
Restart=on-failure
[Install]
WantedBy=default.target
通过 Anyy 管理它:
anyy gateway start
anyy gateway status
anyy gateway stop
系统级(root)单元
如果某台宿主上助理应以 系统 服务、在 root 下运行(例如一台始终在线的家庭服务器),
仓库附带了一个参考 系统 单元。逐字复现自 deploy/linux/anyy.service:
[Unit]
Description=Anyy Gateway native Linux resident
Documentation=https://github.com/Mai8304/Anyy
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
Environment=ANYY_HOME=/root/.anyy
WorkingDirectory=/root/.anyy
ExecStart=/root/.anyy/bin/anyy __gateway --home /root/.anyy
ExecReload=/bin/kill -USR1 $MAINPID
Restart=always
RestartSec=3
TimeoutStopSec=60
KillSignal=SIGTERM
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
安装 系统 单元需要 root。把该文件复制到
/etc/systemd/system/anyy.service,然后以 root 身份运行:
sudo systemctl daemon-reload
sudo systemctl enable --now anyy.service
该单元假定安装根目录为 /root/.anyy。它所假定的安装布局记录在
deploy/linux/README.md 中。anyy gateway 命令管理的是按用户的服务,而非这个
系统单元 —— 系统单元请使用 systemctl 管理。
macOS (launchd)
在 macOS 上,anyy gateway start 会安装一个 launchd 用户代理。仓库中
不附带任何静态 plist —— 生成的用户代理是唯一的 macOS 服务工件,而
anyy gateway start 是安装它的受支持方式。位于
~/Library/LaunchAgents/com.anyy.anyy.plist 的生成定义为:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.anyy.anyy</string>
<key>ProgramArguments</key>
<array>
<string>/Users/you/.anyy/bin/anyy</string>
<string>__gateway</string>
<string>--home</string>
<string>/Users/you/.anyy</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>WorkingDirectory</key>
<string>/Users/you/.anyy</string>
</dict>
</plist>
RunAtLoad 让它在登录时启动,KeepAlive 在它退出时将其重新拉起。通过 Anyy
管理它 —— 你无需触碰 launchctl:
anyy gateway start
anyy gateway status
anyy gateway stop
这是一个按用户的 LaunchAgent,因此它在你登录期间运行。仓库不附带系统级的
LaunchDaemon。如果你需要助理在登录之前就运行,请自行编写一个包裹
anyy gateway start 的 LaunchDaemon(这是一个手动的、由用户自行提供的示例,
而非随仓库附带的工件):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.example.anyy.boot</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/anyy</string>
<string>gateway</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
在 /Library/LaunchDaemons 下安装 LaunchDaemon 需要 root。
OpenWrt
OpenWrt 是一种受支持的 Linux 宿主,而不是独立的路由器产品。Anyy 通过
/etc/openwrt_release 检测到它,anyy gateway start 会在 /etc/init.d/anyy
安装一个 procd init 脚本。生成的脚本为:
#!/bin/sh /etc/rc.common
START=95
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command '/root/.anyy/bin/anyy' '__gateway' '--home' '/root/.anyy'
procd_set_param respawn
procd_close_instance
}
仓库还附带了一个内容更完整的参考 init 脚本,带有显式的 respawn 上限与日志设置。逐字
复现自 deploy/openwrt/etc/init.d/anyy:
#!/bin/sh /etc/rc.common
START=95
STOP=10
USE_PROCD=1
ANYY_HOME="${ANYY_HOME:-/root/.anyy}"
start_service() {
procd_open_instance
procd_set_param env ANYY_HOME="$ANYY_HOME"
procd_set_param command /root/.anyy/bin/anyy __gateway --home /root/.anyy
procd_set_param respawn 3600 5 5
procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
}
reload_service() {
procd_send_signal anyy
}
OpenWrt 服务以 root 身份运行。请通过 Anyy 管理服务
(anyy gateway start / stop / status)。如果你要手动安装附带的参考脚本,
请把它复制到 /etc/init.d/anyy,赋予可执行权限,然后执行
/etc/init.d/anyy enable 和 /etc/init.d/anyy start。
开机自启与存活检查
服务一旦安装,每个宿主都会自动让网关保持存活:
- macOS(launchd 用户代理) ——
RunAtLoad在登录时启动它;KeepAlive在它退出 时重新拉起。 - Linux(systemd 用户单元) ——
WantedBy=default.target与Restart=on-failure在它崩溃时将其重启。若要让用户服务在你注销后仍继续运行,请启用一次 lingering:sudo loginctl enable-linger $USER。 - OpenWrt(procd) ——
procd_set_param respawn会重启进程;附带的参考脚本使用respawn 3600 5 5(仅当一小时内崩溃 5 次后才放弃)。 - Linux 系统单元(
deploy/linux/anyy.service)——Restart=always搭配RestartSec=3以及WantedBy=multi-user.target,在开机时启动它并保持运行。
网关还会运行一个心跳(heartbeat),记录自身的存活情况。用以下命令查看:
anyy heartbeat status
anyy heartbeat status --json
日志与状态
最快的健康检查是 anyy status,它会汇总网关及其各子系统:
◆ Anyy status
Gateway stopped
Profile default
...
◆ Subsystems
Gateway listener —
Cron unavailable
Heartbeat unavailable
...
若专门想看服务与运行时视图,请使用 anyy gateway status:
◆ Gateway
Status not installed
Service launchd user service
Home /Users/you/.anyy
Socket /Users/you/.anyy/anyy.sock
Status 一行区分了你关心的几种情况:running、running manually(前台网关,但未安装
服务)、not running、not installed,以及(当命令二进制比运行中的进程更新时)
running an older Anyy —— 此时的下一步是 anyy gateway restart。
各宿主的日志位置。这里有两条彼此独立的输出流:在每个宿主上,Anyy 的运行时
都会把自身的应用日志写入 <home>/logs/;而服务管理器会单独捕获进程的
stdout/stderr —— 生成的用户服务并不会把这部分输出重定向到 <home>/logs/。
- macOS / launchd —— Anyy 把自身日志写入
<home>/logs/。launchd 用户代理 会把进程的 stdout/stderr 捕获到 launchd 自己的日志位置,而非<home>/logs/。 - Linux / systemd 用户 —— Anyy 把自身日志写入
<home>/logs/。systemd 用户 单元的 stdout/stderr 由 journald 捕获(journalctl --user -u anyy)。systemd 参考 系统 单元设置了StandardOutput=journal/StandardError=journal,因此其 进程输出进入系统 journal(journalctl -u anyy)。 - OpenWrt / procd —— Anyy 把自身日志写入
<home>/logs/。附带的参考脚本设置了stdout 1/stderr 1,因此 procd 会把进程输出转发到 syslog(logread)。
更新常驻安装
用 anyy update 更新程序(完整流程见更新)。当涉及常驻服务时,
更新是感知网关的:
- 如果 Anyy 服务已安装且在运行,更新会重启它,并验证网关报告了新版本
- 如果服务已安装但已停止,它会报告
Gateway: not running - 如果网关以手动方式运行、没有对应服务,它会报告
Gateway: running manually,且不会 失败 - 如果不存在任何网关或服务,它会报告
Gateway: not installed
anyy update 绝不会安装服务 —— 这始终是一个明确的选择。如果你在
anyy gateway status 中看到版本不一致(运行中的进程比命令旧),重启网关以采用
新的构建:
anyy gateway restart
卸载服务
若要停止并移除常驻服务及程序,同时保留你的全部数据(配置、密钥、会话、日志、状态、 记忆、技能、渠道数据):
anyy uninstall --keep-data --yes
若要移除一切,包括 home 目录及全部数据:
anyy uninstall --full --yes
不带模式标志运行 anyy uninstall 会进入交互式提示;--yes / -y 标志会跳过
确认,并要求同时给出 --keep-data 或 --full。
两种模式都会在动到程序文件之前,先移除归 Anyy 所有的服务定义(launchd plist、
systemd 用户单元或 procd init 脚本),因此不会残留孤立的服务。若只想停止服务而不卸载
任何东西,请改用 anyy gateway stop。
如果你安装了附带的 系统 单元(deploy/linux/anyy.service)或手动的
LaunchDaemon,anyy uninstall 并不会管理它 —— 那个是用 root 在 Anyy 之外
安装的。请自行将其停用,例如:sudo systemctl disable --now anyy.service。