Grist 1.7.21 常用运维命令与 API 实操详解
grist-core v1.7.21 日常运维实操手册:systemd 服务管理、.grist/landing.db 文件组织探查、API Key 认证、数据读写与 CSV/XLSX 导出、备份-删除-恢复闭环(含 tar 恢复排障实录)、v1.7.20→v1.7.21 原地升级演练与回滚方案;全部命令与回显 2026-10-28 实测。
Grist 1.7.21 常用运维命令与 API 实操详解
目标:给已按《Grist 1.7.21 安装部署指南》部署好的 grist-core v1.7.21 一套拿来即用的日常运维手册——服务管理、文档存储的文件组织探查、API Key 与数据读写、导出导入、备份-删除-恢复闭环、以及一次完整的 v1.7.20 → v1.7.21 原地升级演练(含回滚方案)。本文全部命令与回显均于 2026-10-28 在实测服务器(Ubuntu 24.04,minimal 登录模式,站点管理员
admin@example.com)上执行留痕;配置项含义见《Grist 1.7.21 配置参数详解》,产品认知见 《Grist 1.7.21 介绍与选型指南》。
一、服务管理(systemd)
$ systemctl status grist --no-pager | head -8
● grist.service - Grist collaborative spreadsheet (grist-core v1.7.21)
Loaded: loaded (/etc/systemd/system/grist.service; enabled; preset: enabled)
Active: active (running)
Main PID: 1789 (bash)
...
$ systemctl is-enabled grist
enabled
- 进程形态:Main PID 由
sandbox/run.sh拉起 Node 服务(node _build/stubs/app/server/server.js),常驻内存实测约 236 MB; - 日志双轨:systemd 生命周期事件走
journalctl -u grist(Started/Stopped/Main process exited, status=143等),应用日志按单元配置落/opt/grist/grist-docs/grist-service.log; - 常规操作四件套:
systemctl restart grist # 改配置后生效,实测 8-12 秒就绪
systemctl stop grist # 冷备前使用
systemctl start grist
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/ # 就绪探测(302 即正常)
二、文档存储的文件组织(探查实测)
2.1 目录布局
/opt/grist/grist-docs/ # GRIST_DATA_DIR
├── 7x5V8ANAPJ8gXBWEiM2Dfe.grist # 每个文档一个 SQLite 文件(实测 167936 B)
├── ecNfLLMX8RCdrDiKbCbLoC.grist
├── xkS6Jbz2gPQAyW9LRKYsTS.grist
└── grist-service.log # 应用日志
/opt/grist/grist-core/landing.db # home DB:用户/组织/工作区/文档元数据
若开启过 GRIST_SQLITE_MODE=wal(见 《Grist 1.7.21 配置参数详解》 4.1 节),.grist 旁还会出现 -shm/-wal sidecar,冷备时务必停机或一并打包。
2.2 深入 .grist 内部(只读探查)
.grist 就是标准 SQLite,任何 SQLite 工具可只读打开:
$ python3 - <<'EOF'
import sqlite3
con = sqlite3.connect('file:/opt/grist/grist-docs/7x5V8ANAPJ8gXBWEiM2Dfe.grist?mode=ro', uri=True)
tabs = [r[0] for r in con.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")]
print(len(tabs), 'tables'); print('user_version =', con.execute('PRAGMA user_version').fetchone()[0])
EOF
46 tables
user_version = 9
实测 46 张表的构成:
- 用户业务表:自建表(如
Table1); - 21 张
_grist_*元数据表:_grist_Tables、_grist_Tables_column、_grist_Views、_grist_Views_section(_field)、_grist_TabBar/_TabItems/_TableViews、_grist_Pages、_grist_Cells、_grist_Attachments、_grist_ACLRules/_ACLMemberships/_ACLPrincipals/_ACLResources、_grist_Filters、_grist_Imports、_grist_Triggers、_grist_Validations、_grist_DocInfo、_grist_External_database/_External_table、_grist_REPL_Hist、_grist_Shares; - 7 张
_gristsys_*引擎表:_gristsys_Action(_step)、_gristsys_ActionHistory(_Branch)、_gristsys_Files/_FileInfo/_PluginData——这正是"任意改动可回放"的动作历史机制; PRAGMA user_version = 9为存储格式版本。
三、API Key:创建与调用
grist-core 的 REST API 支持会话与 Authorization: Bearer <API key> 两种认证。运维脚本推荐 API Key。
3.1 创建 API Key(需已登录会话)
# 先种会话(minimal 模式自动登录)
curl -s -c cj.txt "http://127.0.0.1:3000/login?next=/" -o /dev/null
# 创建 key(端点是单数 apiKey,且必须带 X-Requested-With 头)
$ curl -s -b cj.txt -X POST -H "X-Requested-With: XMLHttpRequest" \
http://127.0.0.1:3000/api/profile/apiKey
5fa4ff819ab389dc818be2da48b9ce5e4dd69998
3.2 Bearer 调用验证
$ curl -s -H "Authorization: Bearer 5fa4ff819ab389dc818be2da48b9ce5e4dd69998" \
http://127.0.0.1:3000/api/profile/user
{"id":5,"email":"admin@example.com","name":"You",...}
注意:缺 X-Requested-With: XMLHttpRequest 头的未认证请求会被拒(Unauthenticated requests require ... X-Requested-With),这是浏览器侧 CSRF 防护在 API 上的延伸;用 Bearer 时不需要该头。
四、数据读写与导出(API 实操)
4.1 写入数据(行式端点)
$ curl -s -H "Authorization: Bearer $KEY" -X POST \
http://127.0.0.1:3000/api/docs/7x5V8ANAPJ8gXBWEiM2Dfe/tables/Table1/records \
-H "Content-Type: application/json" \
-d '{"records":[{"fields":{"A":"gustavo","B":72}},{"fields":{"A":"amelia","B":88}}]}'
{"records":[{"id":1},{"id":2}]}
端点辨析(易踩坑):/tables/:tid/records 是行式(records[].fields),/tables/:tid/data 是列式(BulkColValues),负载结构完全不同,别混用。
4.2 导出 CSV / XLSX
$ curl -s -H "Authorization: Bearer $KEY" \
"http://127.0.0.1:3000/api/docs/7x5V8ANAPJ8gXBWEiM2Dfe/download/csv?tableId=Table1"
A,B,C
gustavo,72,
amelia,88,
$ curl -s -o dump.xlsx -w '%{http_code} %{size_download}\n' -H "Authorization: Bearer $KEY" \
http://127.0.0.1:3000/api/docs/7x5V8ANAPJ8gXBWEiM2Dfe/download/xlsx
200 6438
$ file dump.xlsx
dump.xlsx: Microsoft Excel 2007+ (zip)
五、备份 → 删除 → 恢复闭环(含排障实录)
5.1 停机冷备(最稳)
systemctl stop grist
cd /opt/grist && tar czf grist-backup-20261028.tar.gz grist-docs grist-core/landing.db
systemctl start grist
$ ls -l grist-backup-20261028.tar.gz
-rw-r--r-- 1 root root 1441449 Oct 28 16:16 grist-backup-20261028.tar.gz
归档覆盖两块资产:grist-docs/(文档数据)+ landing.db(元数据),1.44 MB。
5.2 删除文档模拟灾难
$ curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $KEY" \
-X DELETE http://127.0.0.1:3000/api/docs/7x5V8ANAPJ8gXBWEiM2Dfe
200
$ curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $KEY" \
"http://127.0.0.1:3000/api/docs/7x5V8ANAPJ8gXBWEiM2Dfe/download/csv?tableId=Table1"
404
API 返回 document not found,数据目录中的 .grist 文件同步消失——删除是物理删除,没有站内回收站兜底,备份是唯一安全网。
5.3 恢复
systemctl stop grist
tar xzf /opt/grist/grist-backup-20261028.tar.gz -C /opt/grist
systemctl start grist
恢复后验证:CSV 导出 200,gustavo,72,、amelia,88, 完整回归。
排障实录:首次恢复时漏了 -C /opt/grist,归档被解到当前目录(根目录)下形成 /grist-docs、/grist-core,服务读不到文件依旧 404。清理误放目录后带 -C 重解才恢复成功。经验:tar 恢复必须显式 -C 到归档时的相对基目录(本例打包时 cd /opt/grist,因此 -C /opt/grist)。
六、版本升级演练:v1.7.20 → v1.7.21 原地升级(实测)
6.1 演练环境准备
为不动生产实例,在同一台服务器上以第二组端口/目录/单元复制了一份 v1.7.20(/opt/grist/grist-upg,grist-upg.service,PORT=3100,/etc/grist-upg.env)。有构建缓存时全新构建耗时大幅下降(实测 yarn install 11.16s、install:python 7.67s、build 75.66s)。升级前基线:已过 /boot 引导、已建 API key、文档写入一行 pre-upgrade-v1720,42。
6.2 原地升级四连
$ cd /opt/grist/grist-upg
$ git checkout v1.7.21 && yarn install && yarn install:python && yarn build
...
UPGRADE-EXIT=0
$ systemctl restart grist-upg
$ cd /opt/grist/grist-upg && git describe --tags
v1.7.21
6.3 升级后验证(实测结论)
- 升级前写入的数据完好:CSV 接口 200,返回
pre-upgrade-v1720,42; - API Key 与登录会话不失效,无需重新引导;
- 整个过程业务停机窗口 =
systemctl restart的数秒。
6.4 回滚方案(已文档化)
cd /opt/grist/grist-upg
git checkout v1.7.20 && yarn install && yarn build
systemctl restart grist-upg
注意:.grist 文件格式与 home DB schema 由版本迁移控制,跨小版本回退前先做一次 tar 冷备(5.1 节方法),避免"新版本写入的数据"在旧版本上无法回放。
七、常用命令速查表
| 场景 | 命令 |
|---|---|
| 服务状态/自启 | systemctl status grist / systemctl is-enabled grist |
| 配置生效 | systemctl restart grist(8-12s 就绪) |
| 就绪探测 | curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/(302 正常) |
| 日志双轨 | journalctl -u grist -n 50 + /opt/grist/grist-docs/grist-service.log |
| 种会话 | curl -s -c cj.txt "http://127.0.0.1:3000/login?next=/" -o /dev/null |
| 建 API Key | curl -s -b cj.txt -X POST -H "X-Requested-With: XMLHttpRequest" .../api/profile/apiKey |
| 写数据(行式) | POST /api/docs/<id>/tables/<tid>/records,体 {"records":[{"fields":{...}}]} |
| 导 CSV/XLSX | GET /api/docs/<id>/download/csv?tableId=<tid> / GET /api/docs/<id>/download/xlsx |
| 删文档 | DELETE /api/docs/<docId>(物理删除,先备份) |
| 冷备 | systemctl stop grist && tar czf ... grist-docs grist-core/landing.db && systemctl start grist |
| 恢复 | systemctl stop grist && tar xzf <包> -C /opt/grist && systemctl start grist |
| 升级 | git checkout vX.Y.Z && yarn install && yarn install:python && yarn build && systemctl restart grist |
八、系列导航(完)
- 产品认知与选型:《Grist 1.7.21 介绍与选型指南》
- 源码构建、systemd/nginx 部署与离线包:《Grist 1.7.21 安装部署指南》
- 环境变量逐项实测与 PostgreSQL 切库:《Grist 1.7.21 配置参数详解》
- 本篇为系列收官:掌握服务管理、API 读写、备份恢复与升级回滚四件事,Grist 自托管的日常运维即可闭环。