TrailBase 命令与运维实战:trail CLI 子命令、REST API 调用、备份恢复与升级(v0.35.6 实测)
TrailBase v0.35.6 运维全景:trail CLI(admin/user/backups/openapi/schema/migration)实测、认证 API 登录刷新与 JWT 三令牌、curl 完成 REST 记录 CRUD 与过滤分页、Admin API 双头认证、内置备份与 SQLite 冷备、升级替换二进制流程。
TrailBase 命令与运维实战:trail CLI 子命令、REST API 调用、备份恢复与升级(v0.35.6 实测)
目标:给 TrailBase 运维者一套可直接复制的操作手册——
trailCLI 全部子命令、curl 调认证与记录 API、备份恢复三条路径、升级替换二进制的标准流程。全部命令与回显为 2026-10-28 在 Ubuntu 22.04.5 LTS + TrailBase v0.35.6 + systemd 托管环境实测(示例管理员admin@localhost/q1w2e3r4,服务监听 8090)。安装与配置基础见本专栏 《TrailBase 安装部署实战》与 《TrailBase 配置详解》两篇。
一、trail CLI 全景
1.1 子命令清单
$ trail --help
Commands:
run Starts the HTTP server
schema Export JSON Schema definitions
openapi Export OpenAPI definitions
migration Creates new empty migration file
admin Manage admin users (list, demote, promote)
user Manage users. Unlike the admin UI this will also let you change admin users
email Programmatically send emails
components Manage WASM components
backups Manage backups
mcp Starts a local MCP server connected to a running TrailBase server @[ADDRESS]
运维最常用的是 admin、user、backups 三个;run 之外的所有子命令都是离线执行(直接读 depot),与运行中的服务共享同一套 SQLite 文件。全局参数 --depot 需指向服务所在的数据目录,例如 /var/lib/trailbase/traildepot。
1.2 Shell 补全
$ trail --shell-completion=bash | sudo tee /usr/share/bash-completion/completions/trail
支持 bash/zsh/fish/elvish/powershell 五种 shell。
二、用户与令牌管理命令
2.1 admin:管理员清单与升降权
$ trail --depot /var/lib/trailbase/traildepot admin list
id email username created updated
70241e53-8496-431a-a067-28696227d617 admin@localhost admin Single(2026-10-28T02:27:38Z) Single(2026-10-28T02:31:07Z)
$ trail --depot ... admin promote <USER> # 普通用户升级为管理员
$ trail --depot ... admin demote <USER> # 管理员降级
2.2 user:密码、邮箱、会话失效
trail user 的子命令:change-password、change-email、change-username、add(直接添加已验证用户)、delete、verify、invalidate-session(强制用户重新登录)、mint、import、export。改密码实测:
$ trail --depot /var/lib/trailbase/traildepot user change-password admin@localhost 'q1w2e3r4'
Updated password for '70241e53-8496-431a-a067-28696227d617'
2.3 user mint:离线签发令牌(实测)
不经过 HTTP 直接为指定用户签发 JWT,适合脚本/调试:
$ trail --depot /var/lib/trailbase/traildepot user mint admin@localhost
auth: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJjQ1FlVTRTV1F4cWdaeWhwWWlmV0Z3PT0iLCJpYXQiOjE3OTMxNTUyNzEsImV4cCI6MTc5MzE5ODQ3MSwidHlwZSI6MSwiYWRtaW4iOnRydWUsInByb3ZpZGVyIjowLCJlbWFpbCI6ImFkbWluQGxvY2FsaG9zdCIsInVzZXJuYW1lIjoiYWRtaW4iLCJjc3JmX3Rva2VuIjoiUVVrVUE2OXhSUTJFWmF5bWh0Z0pCRExyIn0.RmoZk8flwH..."
🔄: "no-session"
解码该 JWT:exp - iat = 43200,即 CLI 签发的令牌固定 12 小时有效。user export 则输出全量用户 JSON(含 argon2id 密码哈希,注意保密):
$ trail --depot /var/lib/trailbase/traildepot user export
Found 1 users.
{"email":"admin@localhost","verified":true,"id":"70241e53-...","username":"admin","password_hash":"$argon2id$v=19$m=19456,t=2,p=1$...","admin":true,...}
三、认证 API 与 REST 记录 CRUD(curl 实测)
3.1 登录:/api/auth/v1/login 签发三令牌
$ curl -s -X POST http://127.0.0.1:8090/api/auth/v1/login \
-H 'Content-Type: application/json' \
-d '{"email_or_username":"admin@localhost","password":"q1w2e3r4"}'
{"auth_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJjQ1Fl...","refresh_token":"IlRAbzg4Tab...","csrf_token":"YxkW4TjhlXTh5c5H7pV6h3hu"}
要点:请求字段名是 email_or_username(不是 email,写错会得到 401);响应三个令牌各司其职——auth_token(短期 JWT,默认 1 小时)、refresh_token(30 天,可换新 JWT)、csrf_token(Admin API 必带)。JWT 头为 {"typ":"JWT","alg":"EdDSA"},payload 含 admin: true 与 csrf_token claim。
3.2 刷新与状态校验(实测)
$ curl -s -X POST http://127.0.0.1:8090/api/auth/v1/refresh \
-H 'Content-Type: application/json' \
-d '{"refresh_token":"<refresh_token>"}'
{"auth_token":"eyJ0eXAi...","csrf_token":"..."} # HTTP 200,换发新 JWT
实测若不带 JSON 请求体会得到 415 与提示 Expected request with 'Content-Type: application/json';GET /api/auth/v1/status 带 Authorization: Bearer 返回 200 并附最新令牌,适合做网关健康探测。
3.3 记录 API 全流程 CRUD
前置条件:STRICT 表 notes 已建、记录 API 已在 config.textproto 注册(acl_world: 2 匿名只读,acl_authenticated: 15 登录全权,见 《TrailBase 配置详解》篇 4.3)。带令牌请求统一加头:
AT=$(curl -s -X POST http://127.0.0.1:8090/api/auth/v1/login \
-H 'Content-Type: application/json' \
-d '{"email_or_username":"admin@localhost","password":"q1w2e3r4"}' \
| python3 -c 'import json,sys;print(json.load(sys.stdin)["auth_token"])')
创建(匿名 403 / 带令牌 200,对照实测):
$ curl -s -w ' HTTP:%{http_code}\n' -X POST http://127.0.0.1:8090/api/records/v1/notes \
-H 'Content-Type: application/json' -d '{"title":"anon"}'
HTTP:403
$ curl -s -w ' HTTP:%{http_code}\n' -X POST http://127.0.0.1:8090/api/records/v1/notes \
-H "Authorization: Bearer $AT" -H 'Content-Type: application/json' \
-d '{"title":"第一篇笔记","body":"TrailBase CRUD 实测"}'
{"ids":["1"]} HTTP:200
读取单条:
$ curl -s http://127.0.0.1:8090/api/records/v1/notes/1
{"id":1,"title":"第一篇笔记","body":"TrailBase CRUD 实测","owner":null,"created_at":1793155083}
更新(匿名 403 / 带令牌 200)与删除(带令牌 200):
$ curl -s -o /dev/null -w '%{http_code}\n' -X PATCH http://127.0.0.1:8090/api/records/v1/notes/1 \
-H "Authorization: Bearer $AT" -H 'Content-Type: application/json' -d '{"body":"已更新"}'
200
$ curl -s -o /dev/null -w '%{http_code}\n' -X DELETE http://127.0.0.1:8090/api/records/v1/notes/1 \
-H "Authorization: Bearer $AT"
200
3.4 列表查询:filter / count / cursor(实测)
列表接口支持 filter、排序、count 分页计数与游标翻页。实测注意:URL 带 [ ] 时 curl 会把它当 glob 模式解析并静默失败,必须加 -g(--globoff):
$ curl -sg 'http://127.0.0.1:8090/api/records/v1/notes?filter[title]=note-a'
{"cursor":"3guFb8FzWd8MPeKnmQJ7QoOAKMmMC6gDmWQvJZA=","records":[{"id":2,"title":"note-a","body":"","owner":null,"created_at":1793155109}]}
$ curl -sg 'http://127.0.0.1:8090/api/records/v1/notes?filter[id][$gte]=2&count=1' | head -c 260
{"cursor":"C8-1yDKrJ8Aq8ty_czZw4_zTR323yTfyxlJWRzs=","total_count":2,"records":[{"id":3,"title":"note-b",...},{"id":2,"title":"note-a",...}]}
过滤语法是 serde_qs 风格:等值 filter[title]=x、范围 filter[id][$gte]=2、组合 filter[$and][0][col0]=v0&filter[$and][1][col1]=v1、判空 filter[col][$is]=!NULL。注意 JSON 数组式写法(filter=[{...}])会得到 400 Invalid query。
四、备份与恢复
4.1 Admin API:触发与列出备份(实测)
Admin API 需 Authorization: Bearer + CSRF-Token 双头(取法见 3.1 与 《TrailBase 配置详解》篇 5.3):
$ curl -s -X POST http://127.0.0.1:8090/api/_admin/backups/trigger \
-H "Authorization: Bearer $AT" -H "CSRF-Token: $CS" -H 'Content-Type: application/json' -d '{}'
{"backups":[{"timestamp":1793155252}]} HTTP:200
$ curl -s http://127.0.0.1:8090/api/_admin/backups -H "Authorization: Bearer $AT" -H "CSRF-Token: $CS"
{"backups":[{"timestamp":1793155252}]}
备份落到 depot 内 <depot>/backups/<时间戳>/,实测包含三库的一致性快照:
logs.db main.db session.db
配套管理接口:DELETE /api/_admin/backups/delete、POST /api/_admin/backups/restore(恢复需重启生效)。也可在 Admin UI 的 Backups 页面点击操作。
4.2 trail backups CLI(实测)
$ trail --depot /var/lib/trailbase/traildepot backups trigger
Backup succeeded.
$ trail --depot /var/lib/trailbase/traildepot backups list
Found 2 backups
1793155260: @2026-10-28 02:41:00 UTC ("/var/lib/trailbase/traildepot/backups/1793155260")
1793155252: @2026-10-28 02:40:52 UTC ("/var/lib/trailbase/traildepot/backups/1793155252")
定时备份:内置 Backup 任务默认 @daily 且 enabled: false(GET /api/_admin/jobs 实测),可在 config.textproto 的 jobs {} 或 Admin UI 中开启;更省心的做法是外部 cron 调 trail backups trigger 并异地同步 backups/ 目录。
4.3 SQLite .backup 冷备(实测)
与运行中实例并发安全的方式还有 SQLite 在线备份命令:
$ sqlite3 /var/lib/trailbase/traildepot/data/main.db ".backup '/var/lib/trailbase/cold-main.db'"
$ ls -la /var/lib/trailbase/cold-main.db
-rw-r--r-- 1 root root 81920 Oct 28 02:41 /var/lib/trailbase/cold-main.db
一个真实的坑:对冷备副本执行 PRAGMA integrity_check 会报 unknown function: is_uuid()——TrailBase 的表 CHECK 约束用了应用自定义 SQL 函数,纯 sqlite3 CLI 没有注册这些函数;不影响数据本体读写,校验时应以 trail backups trigger 的产物为准或忽略该报错。恢复冷备:停服务 → 用备份文件覆盖 data/ 下对应库 → 起服务。
4.4 备份策略建议
| 手段 | 频率 | 恢复粒度 | 备注 |
|---|---|---|---|
trail backups trigger(cron) | 每日 | 库级快照 | 官方一致性好,脚本化最简单 |
| depot 全目录异地同步 | 每小时级 | 含 secrets/config/migrations | 换机整体恢复最省事 |
SQLite .backup | 灵活 | 单库 | 需自行覆盖三个库文件 |
五、升级与回滚
5.1 标准升级流程(实测验证)
# 1. 记录当前版本与数据快照
trail --version # trail v0.35.6-0-gaca78520 (2026-10-27)
trail --depot /var/lib/trailbase/traildepot backups trigger
# 2. 下载新版并校验 SHA-256(与安装篇 2.2 相同流程,见 [《TrailBase 安装部署实战》](https://www.quzuo.net/document/9fOtaMqSGfUY))
cd /opt && curl -fL -o trailbase_new.zip \
https://github.com/trailbaseio/trailbase/releases/download/v<新版>/trailbase_v<新版>_x86_64_linux.zip
sha256sum trailbase_new.zip # 记录进台账
# 3. 替换二进制(保留旧版用于回滚)
sudo cp /usr/local/bin/trail /usr/local/bin/trail.v0.35.6.bak
unzip -o trailbase_new.zip && sudo install -m 0755 ./trail /usr/local/bin/trail
# 4. 重启并确认
sudo systemctl restart trailbase
systemctl is-active trailbase # active
trail --version # 新版本号
本次实测执行了同版本替换演练:重启后 systemctl is-active 返回 active,记录 API 复测 200,业务无感知。跨版本升级时 TrailBase 启动阶段会自动对三个库跑迁移(首次启动日志里那串 V1__initial、U2__... 就是迁移序列),迁移文件同时落盘到 migrations/。
5.2 版本落点确认
当前运行的精确版本写死在 <depot>/metadata.textproto:
last_executed_version: "v0.35.6-0-gaca78520"
巡检时对比 trail --version 与该值即可确认升级是否生效。回滚 = 停服务 → install 回旧二进制 → 起服务;注意若新版已执行过 schema 迁移,直接回滚旧二进制可能遇到新表结构,所以升级前 4.1 的备份必须先做。
六、日常巡检清单
- 服务状态:
systemctl is-active trailbase+journalctl -u trailbase -n 50(关注Error/WARN); - 健康检查:业务面
curl :8090/api/auth/v1/status,管理面curl :8090/_/admin/api/healthz; - 令牌体系:Admin API 调不通先查 CSRF 双头(《TrailBase 配置详解》篇 5.3);
- 磁盘:
du -sh <depot>(重点logs.db与uploads/,日志默认 7 天自动清理); - 备份:
trail backups list确认每日快照连续,且异地副本存在; - 版本:
trail --version对照metadata.textproto,关注 Release 更新(2026-10-28 时最新稳定版 v0.35.6)。