DOCAT 常用 CLI 命令详解(docatl 与 HTTP API 实战)
docatl v1.1.1 与 curl 双路径实测 DOCAT 1.6.1 全部操作:push/tag/claim/hide/show/push-icon/rename/delete 逐条真机回显,含 CI 集成范式、备份恢复闭环演练(db.json 丢失到令牌复效)与 3 个排障实录。
DOCAT 常用 CLI 命令详解(docatl 与 HTTP API 实战)
DOCAT 的日常运维(上传文档、打标签、认领项目、删除版本、备份恢复)通过两条等价路径完成:官方命令行工具 docatl(Go 编写的独立二进制,仓库 docat-org/docatl,当前版本 v1.1.1,查询日期 2026-10-28)与原生 HTTP API(curl 即可调用)。本文基于 Ubuntu 22.04 + DOCAT 1.6.1 实测环境(Web 端口 8143,部署见 《DOCAT Ubuntu 22.04 安装部署指南》),对每条命令给出 docatl 与 curl 双写法及真机回显。
前置阅读:《DOCAT 介绍与选型指南》(组件定位)、《DOCAT 配置参数详解》(认证机制与错误码)。
一、安装 docatl
官方在 GitHub Releases 提供各平台静态二进制(v1.1.1 资产列表:docatl_1.1.1_linux_amd64 等)。Linux amd64 服务器上的安装:
# curl -sL -o /usr/local/bin/docatl https://github.com/docat-org/docatl/releases/download/v1.1.1/docatl_1.1.1_linux_amd64
# chmod +x /usr/local/bin/docatl
# docatl --help
Error: unknown flag: --version
Usage:
docatl [command]
Available Commands:
build Build a documentation artifact to push to a docat server
claim Claim a docat project
completion Generate the autocompletion script for the specified shell
delete Delete documentation from a docat server
help Help about any command
hide Hide a project version.
push Push documentation to a docat server
push-icon Push an icon for a project
rename Rename a project
show Show a hidden project version.
tag Tag an existing documentation on a docat server
Flags:
--api-key string docat Api Key
--config string config file (default "/.docatl.yaml")
-h, --help help for docatl
--host string docat hostname (e.g. https://docat.company.com:8000)
Use "docatl [command] --help" for more information about a command.
注意:v1.1.1 没有
--version旗标也没有 version 子命令(上面的回显即尝试docatl --version的真实输出),确认版本请对照下载的 release 文件名。
全局参数三个:--host(服务地址)、--api-key(认领令牌)、--config(配置文件,默认 ~/.docatl.yaml,可把 host/api-key 写进去省略每次输入)。非 80 端口的服务必须在 --host 里显式写端口(本文服务在 8143,故命令均为 --host http://127.0.0.1:8143),漏写端口时 docatl 会按默认 80 连接并报 connection refused(见第九节排障实录 2)。
二、核心工作流总览
一个文档项目从发布到下线的完整生命周期命令链:
1. 准备静态文档产物(MkDocs/Sphinx 构建,index.html 必须在 zip 根)
2. docatl push → 上传版本(可同时 --tag latest)
3. docatl tag → 追加/调整标签(latest/stable 等)
4. docatl claim → 认领项目换取令牌(每个项目仅一次)
5. docatl push-icon / rename / hide / show → 装饰与治理(需令牌)
6. docatl delete → 下线版本(需令牌)
7. 备份:tar 打包存储根(含 db.json)
准备测试文档
用 MkDocs 构建一份文档作为测试素材(任何含 index.html 的静态目录均可):
# /opt/docat-venv/bin/mkdocs build -d /tmp/site-v2
INFO - Documentation built in 0.03 seconds
# cd /tmp/site-v2 && zip -qr /tmp/getting-started-1.0.0.zip .
# ls -la /tmp/getting-started-1.0.0.zip
-rw-r--r-- 1 root root 856495 Oct 28 05:23 /tmp/getting-started-1.0.0.zip
三、push —— 上传文档版本
上传 zip 到指定项目与版本。首次上传会自动创建项目。
docatl 写法(含一步式打 latest 标签):
# docatl push /tmp/getting-started-1.0.0.zip cli-project 1.0.0 --host http://127.0.0.1:8143 --tag latest
2026/10/28 05:28:32 Successfully pushed documentation version 1.0.0 to project cli-project
2026/10/28 05:28:32 Successfully tagged version 1.0.0 of project cli-project as latest
curl 等价写法(POST 表单,字段名 file):
# curl -s -X POST -F 'file=@/tmp/getting-started-1.0.0.zip' http://127.0.0.1:8143/api/cli-project/1.0.0
{"message":"Documentation uploaded successfully"}
验证上传结果:
# curl -s http://127.0.0.1:8143/api/projects/cli-project
{"name":"cli-project","storage":"1 MB","versions":[{"name":"1.0.0","timestamp":"2026-10-28T05:28:32.223520","tags":["latest"],"hidden":false}]}
语义要点(均实测验证):
- 上传到不存在的版本号=创建,无需令牌;上传到已存在的版本号=覆盖,需令牌(401/201 对照实测见 C 篇 4.1);
- zip 根必须有
index.html,否则返回成功但附提示:Documentation uploaded successfully, but no index.html found at root of archive.; - 项目名不能使用保留字 api/doc/upload/claim/delete/help(400,实测见 C 篇错误码表)。
四、tag —— 版本打标签
标签是指向版本的符号链接(服务端实现),常用于 latest、stable。
docatl 写法:
# docatl tag getting-started 1.1.0 latest --host http://127.0.0.1:8143
2026/10/28 05:16:45 Successfully tagged version 1.1.0 of project getting-started as latest
curl 等价写法(PUT 方法):
# curl -s -X PUT http://127.0.0.1:8143/api/getting-started/1.1.0/tags/latest
{"message":"Tag latest -> 1.1.0 successfully created"}
标签重复执行是安全的切换操作(符号链接重指向),实测连续 tag 到不同版本即"版本回退":
# ls -la /var/docat/doc/getting-started/
total 16
drwxr-xr-x 4 www-data www-data 4096 Oct 28 05:23 .
drwxr-xr-x 3 www-data www-data 4096 Oct 28 05:23 ..
drwxr-xr-x 8 www-data www-data 4096 Oct 28 05:23 1.0.0
drwxr-xr-x 8 www-data www-data 4096 Oct 28 05:23 1.1.0
lrwxrwxrwx 1 www-data www-data 5 Oct 28 05:23 latest -> 1.1.0
约束:标签不能覆盖"真实版本目录"(409 Tag <标签> would overwrite an existing version!);真实版本也不能覆盖已有标签(409 Cannot overwrite existing tag with new version.)。
五、claim —— 认领项目换取令牌
docatl 写法:
# docatl claim cli-project --host http://127.0.0.1:8143
2026/10/28 05:28:47 Successfully claimed project cli-project. Store and use the following token: f406543d74dd520ad4ce4535cb5910ca
curl 等价写法(注意:1.6.1 实际是 GET 请求,官方 getting-started 文档同此写法):
# curl -s http://127.0.0.1:8143/api/demo-project/claim
{"message":"Project demo-project successfully claimed","token":"7aede69addc833b337103e1fc48ec1c8"}
关键语义(实测):
- 每个项目只能认领一次,重复认领返回 409:
{"message":"Project demo-project is already claimed!"}; - 令牌请立即妥善保存,服务端只存哈希(PBKDF2-HMAC-SHA256/10 万轮,见 db.json),遗失无法找回;
- 需要令牌的操作:覆盖上传、delete、rename、hide、show、替换已有图标;
- 不需要令牌的操作:首次上传新版本、首次设置图标、tag、一切读操作。
六、hide / show —— 版本隐藏与恢复
隐藏的版本不出现在版本下拉与搜索结果中,但直链仍可访问(便于"软下线")。
# docatl hide getting-started 1.0.0 --host http://127.0.0.1:8143 --api-key 7aede69addc833b337103e1fc48ec1c8
2026/10/28 05:16:57 Successfully hid version 1.0.0 of project getting-started
# curl -s 'http://127.0.0.1:8143/api/projects/getting-started'
{"name":"getting-started","storage":"3 MB","versions":[{"name":"1.1.0","timestamp":"2026-10-28T05:23:43.595218","tags":["latest"],"hidden":false}]}
隐藏后 1.0.0 从列表消失;带 include_hidden=true 参数可见全量:
# curl -s 'http://127.0.0.1:8143/api/projects?include_hidden=true'
{"projects":[{"name":"getting-started","logo":false,"storage":"3 MB","versions":[{"name":"1.1.0","timestamp":"2026-10-28T05:23:43.595218","tags":["latest"],"hidden":false},{"name":"1.0.0","timestamp":"2026-10-28T05:23:43.578687","tags":[],"hidden":true}]}]}
恢复显示(curl 写法):
# curl -s -X POST -H 'Docat-Api-Key: 7aede69addc833b337103e1fc48ec1c8' http://127.0.0.1:8143/api/getting-started/1.0.0/show
{"message":"Version 1.0.0 is now shown"}
七、push-icon / rename —— 图标与重命名
上传项目图标(首次无需令牌,替换需令牌;文件必须是图片类型,服务端用 libmagic 识别):
# docatl push-icon getting-started /tmp/logo.png --host http://127.0.0.1:8143 --api-key 7aede69addc833b337103e1fc48ec1c8
2026/10/28 05:16:57 Successfully pushed icon /tmp/logo.png for project getting-started
curl 等价:curl -X POST -F 'file=@logo.png' -H 'Docat-Api-Key: <token>' http://127.0.0.1:8143/api/<项目>/icon。图标落盘在项目根(/var/docat/doc/<项目>/logo)。
重命名项目(需令牌):
# docatl rename getting-started getting-started-v2 --host http://127.0.0.1:8143 --api-key 7aede69addc833b337103e1fc48ec1c8
2026/10/28 05:16:57 Successfully renamed project getting-started to getting-started-v2
curl 等价:curl -X PUT -H 'Docat-Api-Key: <token>' http://127.0.0.1:8143/api/<旧名>/rename/<新名>。重命名同时更新磁盘目录与认领记录(令牌保持有效)。
八、delete —— 删除版本(含重要坑位)
成功路径实测(无图标项目):
# docatl delete cli-project 1.0.0 --host http://127.0.0.1:8143 --api-key f406543d74dd520ad4ce4535cb5910ca
2026/10/28 05:28:47 Successfully deleted version 1.0.0 of project cli-project
# curl -s http://127.0.0.1:8143/api/projects/cli-project
{"message":"Project cli-project does not exist"}
删除最后一个版本后项目自动从列表消失。删除 latest 标签指向的版本时,死链标签会被服务端一并清理。
排障实录 1:delete 报 500 Internal Server Error(1.6.1 上游缺陷)
现象:删除设置了项目图标的项目的最后一个版本时,返回 500:
# docatl delete docatl-renamed 2.0.0 --host http://127.0.0.1:8143 --api-key 90f45f11c6f42e2387894d1831845436
2026/10/28 05:16:57 unable to delete documentation: (status code: 500) Internal Server Error
定位(journalctl -u docat-api 实录 traceback 末段):
Oct 28 05:16:57 docat-lab python[1076]: File "/opt/docat-src/docat/utils.py", line 102, in remove_docs
Oct 28 05:16:57 docat-lab python[1076]: docs.parent.rmdir()
Oct 28 05:16:57 docat-lab python[1076]: OSError: [Errno 39] Directory not empty: '/var/docat/doc/docatl-renamed'
根因:服务端删除版本后会尝试清空整个项目目录(rmdir),但"目录是否为空"的判断只检查子目录,项目图标(logo 文件)不在检查范围内——logo 文件残留导致 rmdir 失败抛 500。注意此时版本数据本身已删除成功,500 只发生在收尾清理阶段;该缺陷在 v1.6.1 存在,属上游代码问题。
规避与恢复:
# rm -f /var/docat/doc/<项目>/logo && rmdir /var/docat/doc/<项目> && echo cleaned
cleaned
最佳实践:删除整个项目前先规划图标;或接受"删最后版本会 500 + 手工清理目录"的运维口径,升级版本时关注官方对该缺陷的修复。
九、CI 流水线集成与备份恢复
9.1 CI 集成范式
DOCAT 官方 README 给出的 CI 场景一行命令(配 docatl):
# docatl push --host http://docat.internal:8143 ./docs myproject 1.2.3 --tag latest
(docatl build 可先把文档目录打包成 zip:docatl build ./site → 生成 site.zip 并提示 Push documentation with: docatl push site.zip,实测产物 850988 字节。)
纯 curl 的 CI 范式(不装 docatl 时的选择):
# curl -X POST -F "file=@docs.zip" http://docat.internal:8143/myproject/1.2.3
官方 README 该示例未带 /api 前缀是旧版接口写法;1.6.1 实测必须带
/api(本文第三节 curl 实测为证)。
9.2 备份:打包存储根
需要备份的全部状态就是 DOCAT_STORAGE_PATH 指向的目录(文档 + 认领令牌库):
# tar -czf /opt/backup/docat-full-backup.tar.gz -C /var docat
# ls -la /opt/backup/docat-full-backup.tar.gz
-rw-r--r-- 1 root root 857153 Oct 28 05:20 /opt/backup/docat-full-backup.tar.gz
# tar -tzf /opt/backup/docat-full-backup.tar.gz | head -4
docat/
docat/doc/
docat/doc/demo-renamed/
docat/doc/demo-renamed/logo
注意 tar 不要加 --dereference(会破坏 latest 等标签符号链接);cron 化建议每日凌晨全量(该目录与文档总量同量级,实测本项目 zip 包 856 KB 即备份包 857 KB)。
9.3 恢复演练:db.json 丢失 → 令牌失效 → 恢复 → 令牌复效
db.json 是令牌唯一载体,用它验证备份的完整闭环(无图标项目 restore-demo,token=c1cf37f13ff730d3f2735f492b43a28a):
第一步:正常状态下令牌有效(401 对照):
# curl -s -X DELETE http://127.0.0.1:8143/api/restore-demo/1.0.0
{"message":"Please provide a header with a valid Docat-Api-Key token for restore-demo"}
第二步:模拟 db.json 丢失,令牌校验失效:
# rm -f /var/docat/db.json
# curl -s -w ' HTTP %{http_code}\n' -X DELETE -H 'Docat-Api-Key: c1cf37f13ff730d3f2735f492b43a28a' http://127.0.0.1:8143/api/restore-demo/1.0.0
{"message":"Please provide a header with a valid Docat-Api-Key token for restore-demo"} HTTP 401
第三步:从备份恢复 db.json,令牌立即复效:
# tar -xzf /opt/backup/docat-full-backup.tar.gz -C /restore-extract
# cp /restore-extract/docat/db.json /var/docat/db.json && chown www-data:www-data /var/docat/db.json
# curl -s -w ' HTTP %{http_code}\n' -X DELETE -H 'Docat-Api-Key: c1cf37f13ff730d3f2735f492b43a28a' http://127.0.0.1:8143/api/restore-demo/1.0.0
{"message":"Successfully deleted version '1.0.0'"} HTTP 200
结论:文档数据与令牌库同目录同生命周期,全量备份即完整可恢复点;恢复后无需重启服务(令牌校验每次请求实时读库)。
排障实录 2:docatl 报 connection refused 但服务正常
现象:docatl push ... --host http://127.0.0.1(漏写端口)报:
unable to upload documentation: Post "http://127.0.0.1/api/cli-project/1.0.0": dial tcp 127.0.0.1:80: connect: connection refused
根因:docatl 对 --host 不做端口补全,非 80/443 部署必须显式写端口;本环境 Web 层监听 8143。解决:--host http://127.0.0.1:8143。
排障实录 3:官方文档 API 路径与 1.6.1 行为差异点
- 上传路由实测为
POST /api/<项目>/<版本>(无尾斜杠);带尾斜杠的请求由框架自动 307 重定向,个别客户端不发重定向后续请求时表现为"上传无响应",建议一律不带尾斜杠; - claim 为 GET 请求(见第五节);旧教程中 POST /claim 写法在 1.6.1 会 405;
- curl 上传务必用
-F file=@xxx.zip表单字段名file,用--data-binary直发 body 会因缺 multipart 字段而 422。
十、命令速查表
| 操作 | docatl | curl 等价 | 令牌 |
|---|---|---|---|
| 上传/覆盖版本 | docatl push <zip> <项目> <版本> [--tag <标签>] | POST /api/<项目>/<版本>(form: file) | 覆盖需 |
| 打标签 | docatl tag <项目> <版本> <标签> | PUT /api/<项目>/<版本>/tags/<标签> | 否 |
| 认领 | docatl claim <项目> | GET /api/<项目>/claim | - |
| 隐藏/恢复 | docatl hide/show <项目> <版本> | POST /api/<项目>/<版本>/hide 或 /show | 需 |
| 图标 | docatl push-icon <项目> <png> | POST /api/<项目>/icon(form: file) | 替换需 |
| 重命名 | docatl rename <旧> <新> | PUT /api/<项目>/rename/<新名> | 需 |
| 删除版本 | docatl delete <项目> <版本> | DELETE /api/<项目>/<版本> | 需 |
| 项目列表 | (Web 界面) | GET /api/projects[?include_hidden=true] | 否 |
| 系统统计 | (Web 界面) | GET /api/stats | 否 |
| API 文档 | - | GET /api/docs(Swagger)/ GET /api/v1/openapi.json | 否 |