Document svc.sh comprehensively and layer its help system
Why: svc.sh grew into a three-kind service manager with database operations, but its only documentation was a flat --help wall of text; the user asked for a complete usage document and a better help experience. Evidence: - docs/svc.md: 14-section manual (prerequisites, quick start, concepts and directory layout, per-command reference for service/global/db commands, deploy sources, database operations handbook, configuration layering, registry fields and event types, safety boundaries, exit codes, troubleshooting table, recipe index) — every claim cross-checked against the implementation from the previous two rounds. - Help layering: no-args and -h print a one-screen overview; --help renders the header comment reorganized into 7 labeled sections; the new "help [topic]" command deep-dives eight topics (model, deploy, lifecycle, db, dbops, config, examples, safety); usage errors now show the short overview plus a pointer to --help / help / docs/svc.md. All topics verified to render; unknown topic exits 2. - No runtime behavior changed: end-to-end db lifecycle regression (create → start → backup → status → stop → rm --purge) passes after the refactor. - Makefile help and README's documentation section point to docs/svc.md. Impact: Documentation-only plus display-layer changes; command semantics, exit codes and file formats are untouched. Maintenance note: behavior changes must now update both --help and docs/svc.md. Refs: .task/feature-svc-docs-help.md(任务卡=PR 描述)
This commit is contained in:
+382
-58
@@ -1,81 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
# svc.sh —— 本机服务管理(服务模型 v2):按提交/版本部署并启动 后端(agent) / 前端(static)
|
||||
# / 数据库(postgres) 三类服务,统一登记(svc.env + history.jsonl)、标签、配置分层、
|
||||
# 生命周期(start/stop/restart/rm)与数据库运维(换端口/备份/恢复/克隆/搬库),
|
||||
# 全程不触碰主检出与其他已启动服务。
|
||||
# svc.sh —— 本机服务管理:后端(agent) / 前端(static) / 数据库(postgres) 三类服务的
|
||||
# 部署、生命周期与数据库运维。每个服务自包含于 runtime/<name>/,登记与配置持久化
|
||||
# (svc.env + history.jsonl),全程不触碰主检出 git 状态与其他已启动服务。
|
||||
#
|
||||
# 用法:
|
||||
# scripts/svc.sh <name> [action] [参数...] # 服务级操作(name 见命名规则)
|
||||
# action:deploy(默认,agent/static)| start | stop | restart | status | logs [行数]
|
||||
# scripts/svc.sh list [--tag T] # 全服务总览(status 等价)
|
||||
# scripts/svc.sh db create <name> [参数] # 创建 PostgreSQL 服务(initdb)
|
||||
# scripts/svc.sh db dsn <name> [--reveal] [--db X] # 打印数据库连接串(默认掩码密码)
|
||||
# scripts/svc.sh db backup <name> [--db X] [--out F] # pg_dump 备份(自动自检归档)
|
||||
# scripts/svc.sh db backups <name> # 列出已有备份
|
||||
# scripts/svc.sh db restore <name> --file F [--db X] [--force] # 恢复(覆盖非空库须 --force)
|
||||
# scripts/svc.sh db clone <src> <dst> [--port P] [--password PW] [--online] # 克隆实例
|
||||
# scripts/svc.sh db copy <src> <dst> [--db X] [--force] # 跨实例搬库(双方须运行)
|
||||
# scripts/svc.sh db ls <name> # 列出实例内数据库
|
||||
# scripts/svc.sh set <name> [--port N --apply] [--tag T] # 变更登记(换端口/标签)
|
||||
# scripts/svc.sh rm <name> [--purge] # 注销服务(--purge 连数据一起删)
|
||||
# scripts/svc.sh commits [dev|release] [N] # 列出可部署提交(默认 dev,N=20)
|
||||
# scripts/svc.sh history [name] [N] # 事件历史(默认全部,最近 20 条)
|
||||
# ════════════════════ 命令一览 ════════════════════
|
||||
# scripts/svc.sh <name> [action] [参数...] 服务级:deploy(默认)|start|stop|restart|status|logs [N]
|
||||
# scripts/svc.sh list [--tag T] 服务总览(status 等价)
|
||||
# scripts/svc.sh set <name> [--port N --apply] [--tag T] 变更登记(换端口/标签)
|
||||
# scripts/svc.sh rm <name> [--purge] 注销服务(--purge 连数据目录删除)
|
||||
# scripts/svc.sh db create <name> [参数] 创建 PostgreSQL 实例(initdb)
|
||||
# scripts/svc.sh db dsn <name> [--reveal] [--db X] 连接串(默认掩码密码)
|
||||
# scripts/svc.sh db backup <name> [--db X] [--out F] 备份(pg_dump -Fc + 自检)
|
||||
# scripts/svc.sh db backups <name> 备份列表
|
||||
# scripts/svc.sh db restore <name> --file F [--db X] [--force] 恢复(覆盖非空库须 --force)
|
||||
# scripts/svc.sh db clone <src> <dst> [--port P] [--password PW] [--online] 克隆实例
|
||||
# scripts/svc.sh db copy <src> <dst> [--db X] [--force] 跨实例搬库(双方须运行)
|
||||
# scripts/svc.sh db ls <name> 实例内数据库列表
|
||||
# scripts/svc.sh db set <name> [...] 等价于 set
|
||||
# scripts/svc.sh commits [dev|release] [N] 可部署提交列表(默认 dev,N=20)
|
||||
# scripts/svc.sh history [name] [N] 事件历史(默认全部,最近 20 条)
|
||||
# scripts/svc.sh help [主题] 分主题详细帮助
|
||||
#
|
||||
# 服务模型:
|
||||
# - name:^[a-z][a-z0-9-]{0,15}$(保留字不可用);dev/prod 有默认端口,其余按名字
|
||||
# 确定性派生(8800-9099,避让已登记/监听端口),SVC_<NAME 大写>_ADDR 可覆盖
|
||||
# - 每个服务自包含于 runtime/<name>/:产物(bin/htdocs)/数据(data/pgdata)/svc.pid/
|
||||
# svc.log|pg.log/svc.env(登记+持久化配置,600)/history.jsonl(追加事件流)
|
||||
# - kind(svc.env kind=,缺省 agent,兼容旧登记):
|
||||
# agent 后端单二进制(内嵌前端);deploy 三源:local | dev[@<sha>] | release[@<v>]
|
||||
# static 前端静态服务;deploy --from dev[@sha]|local 构建 frontend dist 复制到
|
||||
# htdocs/,或 deploy --dir PATH 直接服务既有目录
|
||||
# postgres 数据库;db create 后 start/stop/restart(pg_ctl 生命周期,绝不裸杀)
|
||||
# ════════════════════ 部署来源(agent/static 的 deploy)════════════════════
|
||||
# --from local 构建当前工作区(唯一写主检出构建产物的路径,均 gitignore)
|
||||
# --from dev[@<sha>] 隔离 worktree(runtime/.worktrees/<sha>)物化该提交的
|
||||
# 子模块组合并构建,不触碰当前工作区
|
||||
# --from release[@<版本|sha>] Releases 仓制品(sha256 对 versions/<v>/manifest.json 校验)
|
||||
# --pick [dev|release] 交互式编号选提交;--dry-run 只打印部署计划
|
||||
#
|
||||
# 配置优先级(三类服务一致):命令行 > --config/--env 文件 > svc.env 持久化的上次配置
|
||||
# > SVC_<NAME>_* 系统环境变量(.svc.env 同)> 默认值。裸 start/restart 复用上次持久化
|
||||
# 配置(svc.env exec= 等),显式参数出现即覆盖。
|
||||
#
|
||||
# 常用参数(服务级):
|
||||
# --config FILE / --env FILE dotenv 配置文件(KEY=VALUE;SVC_<NAME>_ADDR/DSN/...)
|
||||
# ════════════════════ 常用参数(服务级)════════════════════
|
||||
# --config FILE / --env FILE dotenv 配置文件(KEY=VALUE;--env 为兼容别名)
|
||||
# --addr host:port / --host H / --port P 监听地址(pg=TCP,static=HTTP)
|
||||
# --tag T 标签(可重复;登记于 svc.env,list --tag 过滤)
|
||||
# --kind agent|static deploy 时指定类型(postgres 用 db create 建)
|
||||
# --from SOURCE 部署来源(见上);--dir PATH(static)直接服务目录
|
||||
# --dry-run 只打印部署计划;--pick [dev|release] 交互式选提交
|
||||
# --plugins/--dsn/--auth/--mock/--data 与 --model-* / --light-* / --tavily-keys
|
||||
# (agent 播种/运行参数)同上一版
|
||||
# -- <剩余参数> 原样透传给 agent-system serve(escape hatch)
|
||||
# db create 专属:--user U(默认 agent)--password P(缺省自动生成,db dsn --reveal 查看)
|
||||
# --db NAME(默认 agent)--auth-mode scram-sha-256|md5(默认 scram)
|
||||
# rm 专属:--purge 删除 runtime/<name>/ 整个目录(含数据与历史)
|
||||
# --tag T 标签(可重复;登记于 svc.env,list --tag 过滤)
|
||||
# --kind agent|static deploy 时指定类型(postgres 用 db create 建)
|
||||
# --dir PATH static 直接服务既有目录(不构建)
|
||||
# --plugins/--dsn/--auth/--mock/--data agent 运行参数
|
||||
# --model-base/--model-key/--model-name 与 --light-*/--tavily-keys 启动后播种设置
|
||||
# -- <剩余参数> 原样透传给 agent-system serve(escape hatch)
|
||||
# db create:--user U(默认 agent)--password P(缺省自动生成)--db NAME --auth-mode scram-sha-256|md5
|
||||
# db backup:--db X --out F db restore:--file F --db X --force
|
||||
# db clone:--port P --host H --password PW --tag T --online
|
||||
# db copy:--db X --force set:--port N --host H --apply --tag T
|
||||
#
|
||||
# 示例:
|
||||
# ════════════════════ 配置优先级 ════════════════════
|
||||
# 命令行 > --config/--env 文件 > svc.env 持久化(exec=/addr=)> SVC_<NAME>_* 环境变量
|
||||
# (.svc.env 自动加载,同层)> 默认值。裸 start/restart 复用上次启动配置;显式参数
|
||||
# 出现即覆盖。任意环境 X 的变量名:SVC_<X 大写,- → _>_ADDR/DATA/DSN/AUTH/MOCK。
|
||||
#
|
||||
# ════════════════════ 服务模型与登记 ════════════════════
|
||||
# - 服务名 ^[a-z][a-z0-9-]{0,15}$(保留字不可用);dev=8788 / prod=8787 默认端口,
|
||||
# 其余按名字确定性派生(8800-9099,避让已登记/监听端口),SVC_<NAME>_ADDR 可覆盖
|
||||
# - runtime/<name>/:bin|htdocs|data|pgdata|plugins|backups + svc.pid +
|
||||
# svc.log|pg.log + svc.env(登记+持久化配置,600)+ history.jsonl(事件流)
|
||||
# - kind:agent(后端单二进制,内嵌前端)/ static(前端静态服务)/ postgres(数据库);
|
||||
# 无 kind= 的旧登记自动视为 agent;start/restart 使用环境内产物
|
||||
#
|
||||
# ════════════════════ 示例 ════════════════════
|
||||
# scripts/svc.sh db create pg1 --port 8890 --tag core # 建库
|
||||
# scripts/svc.sh pg1 start && scripts/svc.sh db dsn pg1 # 起库 + 看 DSN
|
||||
# scripts/svc.sh prod deploy --from release@0.1.0 --tag stable
|
||||
# scripts/svc.sh prod deploy --from dev@<sha> --dsn "$(scripts/svc.sh db dsn pg1 --reveal)"
|
||||
# scripts/svc.sh ui-r4 deploy --kind static --from dev@<sha> --tag ui
|
||||
# scripts/svc.sh ui-qa deploy --kind static --dir ../some/dist
|
||||
# scripts/svc.sh set pg1 --port 8895 --apply # 换端口并重启生效
|
||||
# scripts/svc.sh db backup pg1 && scripts/svc.sh db backups pg1
|
||||
# scripts/svc.sh db clone pg1 pg2 --port 8896 # 物理克隆一套到新端口
|
||||
# scripts/svc.sh db copy pg1 pg2 --db app # 把 pg1 的 app 库搬到 pg2
|
||||
# scripts/svc.sh db restore pg2 --file <dump> --db app --force
|
||||
# scripts/svc.sh list --tag core && scripts/svc.sh history
|
||||
# scripts/svc.sh pg1 restart && scripts/svc.sh rm tmp1 --purge
|
||||
# scripts/svc.sh set pg1 --port 8895 --apply # 换端口并重启生效(登记/DSN 联动)
|
||||
# scripts/svc.sh db backup pg1 && scripts/svc.sh db backups pg1
|
||||
# scripts/svc.sh db clone pg1 pg2 --port 8896 # 物理克隆一套到新端口
|
||||
# scripts/svc.sh db copy pg1 pg2 --db app # 把 pg1 的 app 库搬到 pg2
|
||||
# scripts/svc.sh db restore pg2 --file <dump> --db app --force
|
||||
# make svc ENV=dev ARGS="--env .env.dev --port 9000"
|
||||
#
|
||||
# 安全约束:
|
||||
# ════════════════════ 安全约束 ════════════════════
|
||||
# - 只写 runtime/<name>/ 与 runtime/.worktrees/;不改主检出 git 状态、不动他人现场;
|
||||
# --from local 是唯一写主检出构建产物(bin/、node_modules/、dist/,均 gitignore)
|
||||
# 的路径,dev@sha/release/static 构建全部在隔离 worktree;
|
||||
# - 只停自己启动的进程:pidfile + /proc/<pid>/cmdline 标记双校验;postgres 走
|
||||
# pg_ctl -m fast 优雅停机,SIGKILL 不用于 postmaster;
|
||||
# - 端口被非本脚本进程占用时报错并给出占用者,不抢不杀;
|
||||
# - svc.env 含密码时权限 600;DSN 默认掩码密码(--reveal 才显示);
|
||||
# - svc.env/备份文件权限 600;DSN 默认掩码密码(--reveal 才显示);
|
||||
# - 备份/克隆只增不删;restore/copy 覆盖非空库必须显式 --force(drop 重建再恢复);
|
||||
# 备份文件在 runtime/<name>/backups/(600),随 rm --purge 一并删除;
|
||||
# 备份文件在 runtime/<name>/backups/,随 rm --purge 一并删除;
|
||||
# - 物理克隆期间源实例短暂停止(一致性要求),完成后自动复启;--online 不停源。
|
||||
#
|
||||
# 完整文档:docs/svc.md
|
||||
# <<usage-end>>
|
||||
set -euo pipefail
|
||||
|
||||
@@ -94,6 +102,320 @@ usage() {
|
||||
sed -n '2,/^# <<usage-end>>$/p' "${BASH_SOURCE[0]}" | sed '$d;s/^# \{0,1\}//'
|
||||
}
|
||||
|
||||
# usage_short:一屏速览(无参数 / -h / 用法错误时显示;完整帮助走 --help / help <主题>)。
|
||||
usage_short() {
|
||||
cat >&2 <<'EOF'
|
||||
svc.sh —— 本机服务管理:后端(agent) / 前端(static) / 数据库(postgres) 统一部署、生命周期与运维
|
||||
|
||||
常用:
|
||||
scripts/svc.sh list [--tag T] 服务总览
|
||||
scripts/svc.sh <name> deploy --from dev@<sha> 按提交部署并启动(agent/static)
|
||||
scripts/svc.sh <name> start|stop|restart|logs [N] 生命周期与日志
|
||||
scripts/svc.sh <name> status 服务详情(版本/来源/DSN 等)
|
||||
scripts/svc.sh db create pg1 --port 8890 建数据库
|
||||
scripts/svc.sh db dsn|backup|backups|restore|clone|copy|ls|set pg1 ... 数据库运维
|
||||
scripts/svc.sh set pg1 --port 8895 --apply 换端口(--tag 改标签)
|
||||
scripts/svc.sh rm pg1 [--purge] 注销(--purge 连数据删除)
|
||||
scripts/svc.sh commits [dev|release] [N] 可部署提交
|
||||
scripts/svc.sh history [name] [N] 事件历史
|
||||
|
||||
帮助:--help 完整帮助 | help [主题] 分主题(model deploy lifecycle db dbops config examples safety)
|
||||
文档:docs/svc.md
|
||||
EOF
|
||||
}
|
||||
|
||||
# HELP_TOPICS:help 的主题清单(cmd_help 与提示共用)。
|
||||
HELP_TOPICS="model deploy lifecycle db dbops config examples safety"
|
||||
|
||||
cmd_help() {
|
||||
local topic="${1:-}"
|
||||
case "$topic" in
|
||||
""|topics|list)
|
||||
cat >&2 <<EOF
|
||||
svc.sh 分主题帮助(scripts/svc.sh help <主题>;完整 --help;文档 docs/svc.md)
|
||||
|
||||
model 服务模型:命名、目录布局、svc.env 字段、history 事件、pidcheck
|
||||
deploy 部署:三来源(local/dev@sha/release@v)、--pick、--dry-run、static --dir
|
||||
lifecycle 生命周期:start/stop/restart/logs/status、set 变更、rm 注销
|
||||
db 数据库服务:create/start/dsn/ls/set(换端口)
|
||||
dbops 数据库运维:backup/backups/restore/clone/copy
|
||||
config 配置分层:优先级、--config 文件、SVC_* 环境变量、播种参数
|
||||
examples 配方:常见场景的完整命令序列
|
||||
safety 安全约束与边界
|
||||
EOF
|
||||
return 0 ;;
|
||||
model)
|
||||
cat >&2 <<'EOF'
|
||||
【model】服务模型与登记
|
||||
|
||||
服务名:^[a-z][a-z0-9-]{0,15}$(小写字母开头,可含数字与连字符,≤16 位)。
|
||||
保留字不可用作服务名:status list add set db rm create dsn commits history
|
||||
deploy stop start restart logs help version。
|
||||
|
||||
目录布局(每个服务自包含,互不串版本):
|
||||
runtime/<name>/
|
||||
bin/agent-system agent 产物(deploy 复制就位)
|
||||
htdocs/ static 前端产物(--dir 模式则登记外部目录)
|
||||
data/ agent 数据目录(SQLite 与工件;--data 可改)
|
||||
pgdata/ postgres 数据目录(initdb 产物)
|
||||
plugins/ agent 插件(随 deploy 复制)
|
||||
backups/ pg_dump 备份(0600)
|
||||
svc.pid pidfile(只停 cmdline 校验通过的进程)
|
||||
svc.log | pg.log 日志(postgres 用 pg.log)
|
||||
svc.env 登记 + 持久化配置(dotenv,600)
|
||||
history.jsonl 事件流(append-only,一行一个 JSON)
|
||||
|
||||
svc.env 字段:
|
||||
kind agent|static|postgres(旧登记无此键视为 agent)
|
||||
env 服务名
|
||||
pid 最近启动的 pid
|
||||
addr 监听地址 host:port(持久化——下次 start 复用)
|
||||
tags 标签(逗号分隔)
|
||||
source 部署来源(local@<sha> | dev@<sha> | release@<版本> | dir@<路径> |
|
||||
postgres@local | clone@<名>)
|
||||
version 产物版本串(agent-system version 输出)
|
||||
started 最近启动时间
|
||||
pidcheck 进程判定标记(agent=二进制路径、postgres=pgdata 路径、static=--directory)
|
||||
exec agent 上次完整启动参数(裸 start/restart 复用;显式参数出现即重建)
|
||||
user/password/dbname/authmode/pgdata postgres 专属(密码 600 保存)
|
||||
htdocs static 专属
|
||||
|
||||
history.jsonl 事件(scripts/svc.sh history 查看):
|
||||
create db create / 物理克隆登记
|
||||
deploy begin|ok|fail(含来源)
|
||||
start ok|fail|warn(fail 含原因:进程即退/健康检查超时)
|
||||
stop ok|fail
|
||||
set 登记变更(addr 旧 → 新)
|
||||
backup ok|fail(文件与大小)
|
||||
restore ok|fail(库、文件、表数)
|
||||
clone ok|fail(物理/在线)
|
||||
copy ok|fail
|
||||
rm 注销(purge 与否)
|
||||
|
||||
端口规则:dev 默认 127.0.0.1:8788、prod 127.0.0.1:8787;其余按名字确定性派生
|
||||
(8800-9099,与已登记端口/监听端口冲突时递增扫描);SVC_<NAME>_ADDR 显式覆盖。
|
||||
EOF
|
||||
return 0 ;;
|
||||
deploy)
|
||||
cat >&2 <<'EOF'
|
||||
【deploy】部署与启动(agent / static;省略 action 即 deploy)
|
||||
|
||||
语法:scripts/svc.sh <name> deploy [--kind agent|static] [--from 源] [参数...]
|
||||
|
||||
部署来源(--from,默认 local):
|
||||
local 构建当前工作区(make build / make frontend),产物复制到
|
||||
服务目录。注意:这是唯一会写主检出构建产物(bin/、
|
||||
node_modules/、dist/——均 gitignore)的路径。
|
||||
dev[@<sha>] 在隔离 worktree(runtime/.worktrees/<sha>)检出该提交,
|
||||
递归物化子模块组合(精确落位 gitlink),make build/frontend,
|
||||
产物复制后回收 worktree。子模块对象缺失时需先 git fetch。
|
||||
release[@<版本|sha>] 取 Releases 仓 build/<v>/agent-system(+plugins),
|
||||
sha256 对 versions/<v>/manifest.json 校验,不符即拒绝。
|
||||
--pick [dev|release] 交互式编号选择(需 TTY;列表与提示走 stderr)
|
||||
--dry-run 只打印部署计划不执行
|
||||
|
||||
行为细节:
|
||||
- deploy 前自动停止旧实例(只停自己 pidfile+cmdline 校验的进程)
|
||||
- agent 启动后等健康检查(20s),随后按 --model-*/--tavily-keys 播种设置(幂等)
|
||||
- 旧版本产物不认识 --dsn/--auth 时自动省略(探测 serve 用法)并提示
|
||||
- static 的 release 源不支持(制品内嵌前端);--dir PATH 可直接登记并服务
|
||||
既有目录(不构建、不复制,source=dir@<路径>)
|
||||
- deploy 全程事件入 history.jsonl(begin/ok/fail)
|
||||
|
||||
示例:
|
||||
scripts/svc.sh prod deploy --from release@0.1.0 --tag stable
|
||||
scripts/svc.sh prod deploy --from dev@73b2802 --dry-run
|
||||
scripts/svc.sh ui-r4 deploy --kind static --from dev@73b2802
|
||||
scripts/svc.sh ui-qa deploy --kind static --dir ../frontend/dist
|
||||
EOF
|
||||
return 0 ;;
|
||||
lifecycle)
|
||||
cat >&2 <<'EOF'
|
||||
【lifecycle】生命周期与登记变更
|
||||
|
||||
scripts/svc.sh <name> start 启动(agent/static/postgres 分别分派;已在运行则提示)
|
||||
scripts/svc.sh <name> stop 停止(agent/static: TERM→KILL;postgres: pg_ctl -m fast)
|
||||
scripts/svc.sh <name> restart 停止 + 启动(裸 restart 复用上次配置)
|
||||
scripts/svc.sh <name> logs [N] 跟随日志(默认 50 行起;如 svc.sh pg1 logs 200)
|
||||
scripts/svc.sh <name> status 单服务详情(kind/状态/地址/来源/版本/标签/DSN/目录)
|
||||
scripts/svc.sh list [--tag T] 全服务表格:NAME KIND STATE PID ADDR SOURCE TAGS
|
||||
scripts/svc.sh history [name] [N] 事件历史(首参为纯数字时视为条数)
|
||||
|
||||
变更登记(不动进程,除 --apply):
|
||||
scripts/svc.sh set <name> --tag T... 三类服务通用,合并去重
|
||||
scripts/svc.sh set <pg名> --port N [--host H] 未运行:直接改登记
|
||||
scripts/svc.sh set <pg名> --port N --apply 运行中:停止→改登记→重启
|
||||
- 运行中的 postgres 改端口必须 --apply(防止登记与实际监听不一致)
|
||||
- agent/static 换端口用 restart --port N(进程与登记同步更新)
|
||||
- 新端口会先校验:未被其他服务登记占用且未在监听
|
||||
|
||||
注销:
|
||||
scripts/svc.sh rm <name> 停止并移除登记(目录/数据/历史保留)
|
||||
scripts/svc.sh rm <name> --purge 连 runtime/<name>/ 整个目录一起删除
|
||||
EOF
|
||||
return 0 ;;
|
||||
db)
|
||||
cat >&2 <<'EOF'
|
||||
【db】数据库服务:创建 / 连接 / 换端口
|
||||
|
||||
scripts/svc.sh db create <name> [--port P] [--host H] [--user U] [--password P]
|
||||
[--db NAME] [--auth-mode scram-sha-256|md5] [--tag T...]
|
||||
initdb 到 runtime/<name>/pgdata(目录 700,密码文件即用即删);
|
||||
默认用户/库均为 agent,缺省密码自动生成(db dsn --reveal 查看);
|
||||
只登记不启动——scripts/svc.sh <name> start 启动。
|
||||
scripts/svc.sh <name> start|stop|restart
|
||||
pg_ctl 生命周期:start 带 -p <port> -k <环境目录>(socket 不落 pgdata)、
|
||||
listen_addresses 随 --host;首次启动自动创建登记库(已存在则跳过);
|
||||
就绪判定 pg_isready;stop 用 -m fast 优雅回写,失败退 SIGTERM,绝不 KILL。
|
||||
scripts/svc.sh db dsn <name> [--reveal] [--db X]
|
||||
连接串 postgresql://user:pass@host:port/db;默认掩码密码(stdout 纯净可组合)。
|
||||
scripts/svc.sh db ls <name>
|
||||
实例内数据库列表(须运行中)。
|
||||
scripts/svc.sh db set <name> [...] / scripts/svc.sh set <name> [...]
|
||||
换端口/主机/标签:见 help lifecycle(运行中改端口需 --apply)。
|
||||
|
||||
连接其他服务:DSN 可直接组合进 agent 部署——
|
||||
scripts/svc.sh prod deploy --from dev@<sha> --dsn "$(scripts/svc.sh db dsn pg1 --reveal)"
|
||||
(旧版本产物不识别 --dsn 时会自动省略并提示。)
|
||||
|
||||
密码管理:密码明文存 runtime/<name>/svc.env(600);--password 未给时自动生成
|
||||
(head -c 18 /dev/urandom)。auth-mode 默认 scram-sha-256(pg_hba 全线)。
|
||||
EOF
|
||||
return 0 ;;
|
||||
dbops)
|
||||
cat >&2 <<'EOF'
|
||||
【dbops】数据库运维:备份 / 恢复 / 克隆 / 搬库
|
||||
|
||||
备份:
|
||||
scripts/svc.sh db backup <name> [--db X] [--out FILE]
|
||||
pg_dump -Fc 走 TCP(实例须运行中)→ 默认 runtime/<name>/backups/<UTC时间戳>-<库>.dump
|
||||
(目录 700、文件 600);完成后 pg_restore --list 自检归档,失败即删。
|
||||
scripts/svc.sh db backups <name>
|
||||
列出备份(时间 / 大小 / 文件名)。
|
||||
|
||||
恢复(唯一可能覆盖数据的操作,非空库必须 --force):
|
||||
scripts/svc.sh db restore <name> --file F [--db X] [--force]
|
||||
目标实例须运行中;F 须为合法 pg_dump 归档(先自检);
|
||||
目标库不存在→建库后恢复;存在但空→直接恢复;存在且非空→拒绝(--force 才
|
||||
DROP WITH (FORCE) + 重建 + 恢复);完成后回显表数。
|
||||
|
||||
克隆(整实例,绑定新端口):
|
||||
scripts/svc.sh db clone <src> <dst> [--port P] [--host H] [--password PW] [--tag T] [--online]
|
||||
默认物理克隆:短暂停止源(一致性)→ cp -a pgdata(剔除 postmaster.pid/.opts)→
|
||||
登记目标(新端口:--port 或派生;用户/库/认证继承,密码可换;标签继承+可加;
|
||||
source=clone@<src>)→ 自动复启源。目标不自动启动(提示 start 命令)。
|
||||
--online:不停源,dump/restore 逻辑复制源登记库到目标——要求目标已
|
||||
db create + start。
|
||||
|
||||
搬库(单库、跨实例):
|
||||
scripts/svc.sh db copy <src> <dst> [--db X] [--force]
|
||||
双方都须运行中;--db X 同时命名源与目标库(默认取源登记库);
|
||||
目标库非空须 --force(语义同 restore)。
|
||||
|
||||
注意:备份/克隆只增不删;备份随 rm --purge 一并删除;所有操作入 history.jsonl。
|
||||
EOF
|
||||
return 0 ;;
|
||||
config)
|
||||
cat >&2 <<'EOF'
|
||||
【config】配置分层与持久化
|
||||
|
||||
优先级(高 → 低):
|
||||
1. 命令行参数(--port/--dsn/--tag/...)
|
||||
2. --config FILE(或 --env FILE,兼容别名;=FILE 写法亦可)
|
||||
3. svc.env 持久化(addr=、exec=——上次启动的实际参数)
|
||||
4. SVC_<NAME>_* 环境变量与 .svc.env(自动加载,同层)
|
||||
5. 默认值(dev=8788 / prod=8787 / 其余派生端口)
|
||||
|
||||
dotenv 格式:KEY=VALUE,支持 # 注释、成对引号、export 前缀;只识别合法变量名,
|
||||
不 source 执行文件内容。建议 .env.dev/.env.prod 等加入 gitignore。
|
||||
|
||||
环境变量(X 为服务名大写,- → _):
|
||||
SVC_X_ADDR / SVC_X_DATA / SVC_X_DSN / SVC_X_AUTH / SVC_X_MOCK
|
||||
SVC_RELEASES_DIR Releases 仓路径(默认 ../Agent-System-Releases)
|
||||
SVC_PG_BIN postgres 工具链 bindir(默认 pg_config --bindir 探测)
|
||||
SVC_MODEL_BASE/KEY/NAME 主模型(agent 启动健康后播种)
|
||||
SVC_LIGHT_BASE/KEY/NAME 轻量模型
|
||||
SVC_TAVILY_KEYS Tavily 密钥池
|
||||
播种幂等:设置持久化在 agent 数据目录,播过一次后续启动无需再传。
|
||||
|
||||
持久化语义:
|
||||
- deploy/start 成功后把当前态写入 svc.env(600)
|
||||
- 裸 start/restart 复用 exec=(上次完整参数);任何显式参数(或 --config 文件、
|
||||
SVC_* 变量)出现即整体重建参数
|
||||
- tags 随每次登记合并去重,跨重启保留
|
||||
EOF
|
||||
return 0 ;;
|
||||
examples)
|
||||
cat >&2 <<'EOF'
|
||||
【examples】常见配方
|
||||
|
||||
① 起一套演示后端(当前工作区构建):
|
||||
scripts/svc.sh dev deploy --mock
|
||||
② 建库 + 后端连库:
|
||||
scripts/svc.sh db create pg1 --port 8890
|
||||
scripts/svc.sh pg1 start
|
||||
scripts/svc.sh prod deploy --from dev@<sha> \
|
||||
--dsn "$(scripts/svc.sh db dsn pg1 --reveal)"
|
||||
③ 按提交部署 + 回退:
|
||||
scripts/svc.sh commits dev # 看可部署提交
|
||||
scripts/svc.sh v1 deploy --from dev@73b2802 --tag test
|
||||
scripts/svc.sh v1 deploy --from release@0.1.0 # 回退到发布版本
|
||||
④ 双版本对比(同机并行):
|
||||
scripts/svc.sh a deploy --from dev@<shaA> --port 8801
|
||||
scripts/svc.sh b deploy --from dev@<shaB> --port 8802
|
||||
⑤ 前端静态服务:
|
||||
scripts/svc.sh ui deploy --kind static --from dev@<sha> # 构建并服务 dist
|
||||
scripts/svc.sh ui2 deploy --kind static --dir ../frontend/dist # 直接服务目录
|
||||
⑥ 备份 → 改坏数据 → 恢复:
|
||||
scripts/svc.sh db backup pg1
|
||||
... (随意操作)
|
||||
scripts/svc.sh db restore pg1 --file runtime/pg1/backups/<最新>.dump --force
|
||||
⑦ 克隆一套隔离环境(不动原库):
|
||||
scripts/svc.sh db clone pg1 pg1test --port 8896
|
||||
scripts/svc.sh pg1test start
|
||||
scripts/svc.sh qa deploy --from dev@<sha> --dsn "$(scripts/svc.sh db dsn pg1test --reveal)"
|
||||
⑧ 把开发库搬到 prod 实例:
|
||||
scripts/svc.sh db copy pgdev pgprod --db app --force
|
||||
⑨ 换端口:
|
||||
scripts/svc.sh set pg1 --port 8895 --apply
|
||||
⑩ 总览与追溯:
|
||||
scripts/svc.sh list --tag test
|
||||
scripts/svc.sh history pg1 50
|
||||
EOF
|
||||
return 0 ;;
|
||||
safety)
|
||||
cat >&2 <<'EOF'
|
||||
【safety】安全约束与边界
|
||||
|
||||
写入边界:
|
||||
- 只写 runtime/<name>/ 与 runtime/.worktrees/(构建 worktree,用后即收);
|
||||
- 不改主检出 git 状态;--from local 是唯一写主检出构建产物(bin/、node_modules/、
|
||||
dist/——均 gitignore)的路径;
|
||||
- rm --purge 只删 runtime/<name>/,且要求服务已登记。
|
||||
|
||||
进程边界:
|
||||
- 只停"自己 pidfile + /proc cmdline 标记双校验"都通过的进程;
|
||||
- postgres 走 pg_ctl -m fast,失败退 SIGTERM,SIGKILL 不用于 postmaster;
|
||||
- agent/static:TERM 优雅退出,10s 未退才 KILL。
|
||||
|
||||
端口边界:
|
||||
- 被非本脚本进程占用:报错并给出占用者,不抢不杀;
|
||||
- 显式选端口(--port / set --port / clone --port)会同时查登记与监听;
|
||||
- 派生端口在 8800-9099 内避让已登记与监听端口。
|
||||
|
||||
秘密与数据:
|
||||
- svc.env(含 DB 密码)与备份文件权限 600;数据/环境目录 700;
|
||||
- DSN 默认掩码密码,--reveal 才显示;
|
||||
- restore/copy 覆盖非空库必须显式 --force;备份/克隆只增不删;
|
||||
- dotenv 解析不执行文件内容(防注入)。
|
||||
EOF
|
||||
return 0 ;;
|
||||
*)
|
||||
c_err "未知帮助主题:$topic(可选:$HELP_TOPICS;总览:scripts/svc.sh help)"
|
||||
return 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# load_env_file FILE:dotenv 安全解析——逐行 KEY=VALUE 赋值(剥 export 前缀与成对
|
||||
# 引号,忽略注释/空行/非法行),不 source 执行文件内容。
|
||||
load_env_file() {
|
||||
@@ -165,7 +487,7 @@ parse_args() {
|
||||
--auth-mode) need_value "$@"; CLI_DB_AUTH="$2"; shift 2 ;;
|
||||
--) shift; CLI_EXTRA="$*"; break ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) c_err "未知参数:$1"; usage; exit 2 ;;
|
||||
*) c_err "未知参数:$1"; usage_short; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
@@ -1710,7 +2032,7 @@ cmd_history() {
|
||||
# ---- main ----
|
||||
|
||||
main() {
|
||||
[ $# -ge 1 ] || { usage; exit 2; }
|
||||
[ $# -ge 1 ] || { usage_short; exit 2; }
|
||||
# 预扫 --config/--env(FILE 与 =FILE 两种写法,可出现在任意位置)。
|
||||
local svc_envfile="" pre=()
|
||||
while [ $# -gt 0 ]; do
|
||||
@@ -1725,7 +2047,9 @@ main() {
|
||||
[ -f "$ROOT/.svc.env" ] && load_env_file "$ROOT/.svc.env"
|
||||
[ -n "$svc_envfile" ] && load_env_file "$svc_envfile"
|
||||
case "$1" in
|
||||
-h|--help|help) usage; exit 0 ;;
|
||||
-h) usage_short; exit 0 ;;
|
||||
--help) usage; exit 0 ;;
|
||||
help) shift; cmd_help "$@"; exit $? ;;
|
||||
esac
|
||||
case "$1" in
|
||||
list|status)
|
||||
|
||||
Reference in New Issue
Block a user