Skip to content

✨ 新增 sctl service:把 serve 注册为用户级系统服务 - #11

Open
lonelyman0108 wants to merge 1 commit into
mainfrom
feat/service
Open

lonelyman0108 wants to merge 1 commit into
mainfrom
feat/service

Conversation

@lonelyman0108

Copy link
Copy Markdown
Collaborator

背景

sctl serve 只能在前台运行。文档让用户“交给系统服务管理器”,但没有提供工具;手写的服务定义也容易和 CLI 的数据目录、监听地址对不上。Spec:docs/specs/2026-10-23-service.md。

改动

  • sctl service install|uninstall|start|stop|restart|status
    • macOS:launchd LaunchAgent(~/Library/LaunchAgents/com.scriptscat.sctl.plist)
    • Linux:systemd 用户单元(~/.config/systemd/user/sctl.service,按绝对路径 enable)
    • Windows:当前用户登录时触发的计划任务(XML 定义;取消 72 小时运行上限和电池条件;StopExisting)
    • 都不需要管理员权限
  • install 固化本次调用实际生效的 --data-dir(转成绝对路径,包括来自 SCTL_DATA_DIR 的)、--listen-address 和非默认的 --log-level。二进制路径优先用 PATH 里的同一个文件,Homebrew 升级后服务不会失效。
  • 隐藏参数 serve --service:日志只写 <data dir>/logs,stderr 只留给运行时崩溃信息;Windows 上进程独占控制台时脱离它。
  • 判断 daemon 是否起来:要求健康检查通过,且控制令牌与操作前不同(daemon 绑定端口后才写新令牌)。这样另一个 daemon 占着端口时不会误报成功。install 前和 start 前,只要已有 daemon 能连上(包括其他数据目录的 daemon),就不再启动服务。
  • 新增 control.Address() / control.Healthy(),logging.Setup 增加 toStderr 参数。
  • 文档:cli.md 新增 “Background service” 一节;mcp.md、architecture.md、两份 README、skills/sctl 同步更新。

验证

  • go build/vet ./...(含 GOOS=windows)、go test ./... -race 通过;golangci-lint 在 darwin/linux/windows 三个平台上都是 0 issues。
  • macOS launchd 真机验证(隔离数据目录与端口),步骤与结果:
    • install:daemon 可连,plist 内容正确
    • 进程运行 10 秒以上后 kill -9:1 秒内被拉起
    • stop / start / restart:都正常,restart 后 pid 变化
    • 运行中重复 install:覆盖定义并重启
    • 服务模式下 service.stderr.log 为 0 字节,日志只写 sctl.log
    • uninstall 幂等;未安装时 start 退出码 3
    • 前台 daemon 占着端口:install 被拒绝;已安装时 start 报告已在运行、不启动服务,restart 退出码 3,不误报成功
  • 真机发现:二进制放在 ~/Documents 下时,launchd 启动的进程会被 macOS 隐私保护(TCC)卡住,cli.md 已写明。

未验证 / 已知限制

  • Linux systemd 和 Windows 任务计划程序没有真机验证,只有单元测试覆盖定义内容和命令序列。
  • Windows 的 RestartOnFailure 是否能拉起启动后才崩溃的 daemon 没有确认;文档如实写了,建议崩溃后用 sctl service start。
  • 与 brew services 二选一(同一个端口),文档已说明。

已按 review 修正:waitDaemon 误报成功、安装前检查依赖令牌、schtasks 吞错误、/End 与 /Run 的竞态、bootstrap 重试窗口太短、XDG_CONFIG_HOME 不一致、ProcessType=Background、uninstall 报告不准、--log-level 帮助文字过时。

sctl serve 只能前台运行,文档让用户自己配置服务管理器却不提供工具,手写定义还容易
和 CLI 的数据目录、监听地址对不上。

- sctl service install|uninstall|start|stop|restart|status:macOS launchd LaunchAgent、
  Linux systemd --user、Windows 登录触发的计划任务,不需要管理员权限
- install 固化当前生效的 --data-dir(绝对路径)、--listen-address、非默认 --log-level;
  二进制优先用 PATH 里的同一文件,Homebrew 升级后不失效
- 隐藏参数 serve --service:日志只写文件;Windows 上脱离独占的控制台
- 等 daemon 时以控制令牌变化识别新进程;安装前和 start 前遇到已在运行的 daemon 时不启动服务
- schtasks / launchctl 只把非零退出当作“不存在”,命令本身无法运行时如实报错
- spec:docs/specs/2026-10-23-service.md
@CodFrm

CodFrm commented Oct 23, 2026

Copy link
Copy Markdown
Member

是只适配了linux么?mac/windows是不是也要处理一下

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants