Etherpad 3.3.9 常用 CLI 命令与工具详解
Etherpad 3.3.9 三类工具实测:启动参数、bin 运维脚本(插件装卸/pad 检查删除导出)与 HTTP API 1.3.1 全量端点(含 API 版本分级、错误码实测)。
Etherpad 3.3.9 常用 CLI 命令与工具详解
目标:系统梳理 Etherpad 3.3.9 的三类操作工具——服务启动命令行参数、内置 bin/ 运维脚本(插件管理、pad 检查/删除/导出)与 HTTP API——并逐条实测给出真实回显,全部命令已在 Ubuntu 22.04 实测通过(2026-10-22,Etherpad 3.3.9 + PostgreSQL 15,部署形态见《Etherpad 3.3.9 Docker Compose 部署指南》)。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- Etherpad:3.3.9(官方 Docker 镜像部署,安装路径
/opt/etherpad-lite,工作目录/opt/etherpad) - 数据库:PostgreSQL 15(
etherpad库,store单表 KV 存储) - API key:
fKQy4G837VScLPnBeDTogEbl0fj41grIpmt6f9qsY(测试实例,配置方式见部署指南 4.3 节) - 服务端口:
8134(映射服务内 9001),服务内认证模式AUTHENTICATION_METHOD=apikey
二、工具概览
Etherpad 3.3.9 的运维操作分三类,作用面各不相同:
| 工具类别 | 入口 | 典型用途 |
|---|---|---|
| 服务启动命令行 | run.sh / node node/server.ts + 启动参数 | 指定自定义 settings/credentials/sessionkey/APIKEY 文件启动 |
| bin/ 运维脚本 | /opt/etherpad-lite/bin/*.ts(约 20 个,node + tsx 运行) | 插件装卸、pad 检查/删除/导出/压缩、数据库迁移 |
| HTTP API | http://<host>:8134/api/<版本>/<函数> | 程序化建/读/写/删 pad、聊天、作者、统计 |
💡 说明:bin 脚本依赖 tsx 加载器,统一在安装目录的
src子目录下以node --require tsx/cjs ../bin/<脚本>.ts方式运行——直接在根目录执行会报Cannot find module 'tsx/cjs'(tsx 安装在 src/node_modules 下)。以运行服务的账号(如etherpad)身份执行即可。
三、前置条件
# 确认服务在跑、API key 可读
curl -s http://127.0.0.1:8134/health
cat /opt/etherpad/data/APIKEY.txt
实测输出:
{"status":"pass","releaseId":"3.3.9"}
fKQy4G837VScLPnBeDTogEbl0fj41grIpmt6f9qsY
四、服务启动命令行参数
启动参数由服务端 src/node/utils/Cli.ts 解析,共 4 个文件位置覆盖参数(源码实测确认,无 --help 输出——传 --help 时按正常流程启动服务):
| 参数 | 简写 | 作用 |
|---|---|---|
--settings <路径> | -s | 覆盖默认 settings.json 位置 |
--credentials <路径> | 无 | 覆盖 credentials.json 位置(数据库凭据独立文件) |
--sessionkey <路径> | 无 | 覆盖会话密钥文件位置 |
--apikey <路径> | 无 | 覆盖 APIKEY.txt 位置 |
实测验证 --apikey 参数生效(用自定义路径的 key 文件启动):启动日志出现 Api key file read from: "<自定义路径>" 即生效;文件不存在时服务端自动生成随机 key 并写出到该路径(源码行为:Api key file "..." not found. Creating with random contents.)。
源码包部署用 bin/run.sh 启动。run.sh 内置 root 拦截:以 root 运行时要求交互确认,实测输出:
You shouldn't start Etherpad as root!
Please type 'Etherpad rocks my socks' (or restart with the '--root'
argument) if you still want to start it as root:
按提示输入 Etherpad rocks my socks(或追加 --root 参数)即放行。生产建议以专用低权限账号(如 etherpad)运行。
五、bin 运维工具详解
5.1 plugins.ts —— 插件管理
子命令三件套:ls/list(列出)、install/i(安装,支持 --github、--path 指定来源)、rm/remove(卸载)。先查当前插件清单:
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/plugins.ts ls
实测输出(节选):
[2026-10-21T17:29:36.711] [INFO] settings - Installed plugins are: ep_etherpad-lite
[2026-10-21T17:29:36.721] [INFO] plugins - pnpm --version: 12.4.2
安装 ep_comments_page(评论侧栏插件):
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/plugins.ts install ep_comments_page
实测输出(节选):
[INFO] plugins - check installed plugins for migration
[INFO] settings - Installing plugin from registry: ep_comments_page
[INFO] plugins - pnpm --version: 12.4.2
验证安装结果与落盘:
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/plugins.ts ls
cat /opt/etherpad-lite/var/installed_plugins.json
实测输出:
[INFO] settings - Installed plugins are: ep_plugin_helpers, ep_comments_page, ep_etherpad-lite
{"plugins":[{"name":"ep_plugin_helpers","version":"0.6.9"},{"name":"ep_comments_page","version":"11.1.31"},{"name":"ep_etherpad-lite","version":"3.3.9"}]}
要点:依赖插件(ep_plugin_helpers)自动随装;插件实体落到插件目录(src/plugin_packages),清单落 var/installed_plugins.json;安装后需重启服务加载新插件。
卸载:
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/plugins.ts rm ep_comments_page
实测输出(节选):
[INFO] settings - Uninstalling plugin: ep_comments_page
⚠️ 排障实录:服务器直连 npm registry 失败时报
Error: Failed to get package 'ep_headerview' Response error 404 Not Found(经代理后 404 为插件真实不存在;直连超时则表现为连接错误)。出口受限的服务器先给执行环境注入代理再安装:export http_proxy=http://<代理IP>:<端口> https_proxy=同值。插件名以官方插件索引(https://static.etherpad.org/index.html)为准。
5.2 checkPad.ts / checkAllPads.ts —— pad 完整性检查
检查单个 pad 的修订链完整性:
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/checkPad.ts persist-test
实测输出(节选):
[INFO] settings - Checking if persist-test exists
[INFO] settings - Finished checking pad.
全库扫描(逐 pad 报 OK/损坏):
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/checkAllPads.ts
实测输出(节选):
[INFO] settings - Pad persist-test: OK
[INFO] settings - Finished.
5.3 deletePad.ts —— 删除单个 pad
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/deletePad.ts mixedcase99
实测输出:
Deleted pad { code: 0, message: 'ok', data: null }
⚠️ 排障实录:首次执行报
Error: ENOENT: no such file or directory, open '/opt/etherpad-lite/settings.json.docker'——该脚本族(deletePad/extractPadData 等)通过测试工具链src/tests/container/loadSettings.js读取settings.json.docker。解决:cp /opt/etherpad-lite/settings.json /opt/etherpad-lite/settings.json.docker后重跑即成功。此文件属一次性排障产物,无需持久化。
5.4 extractPadData.ts —— 导出 pad 全量数据
把一个 pad 的正文、修订、作者等全部数据库键导出为 dirty 格式 .db 文件(用于跨环境复现问题或单 pad 迁移):
cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/extractPadData.ts persist-test
实测输出(节选收尾):
[INFO] settings - finished
输出文件生成在执行时的工作目录(src)下:
ls -la /opt/etherpad-lite/src/persist-test.db
实测输出:
-rw-r--r-- 1 etherpad root 890 Oct 21 17:31 /opt/etherpad-lite/src/persist-test.db
⚠️ 排障实录:该脚本依赖
dirty模块(dirty 格式数据库驱动),Docker 官方镜像未预装,首次运行报Error: Cannot find module 'dirty'。解决:cd /opt/etherpad-lite/bin && pnpm add dirty(注意装到bin目录而非src——脚本在 bin/ 下,Node 模块解析止步于 bin/node_modules;装到 src 无效,本机实测验证)。
5.5 其余 bin 工具速查
同一运行方式(cd src && node --require tsx/cjs ../bin/<脚本>.ts),按用途归类:
| 脚本 | 用途 |
|---|---|
compactPad.ts / compactAllPads.ts / compactStalePads.ts | 压缩修订历史,回收存储空间(单 pad/全库/陈旧 pad) |
rebuildPad.ts / repairPad.ts | 从 changeset 重建 pad 正文 / 修复损坏 pad |
migrateDB.ts / migrateDirtyDBtoRealDB.ts | 数据库间迁移(含 DirtyDB 迁正式库) |
importSqlFile.ts | 导入 SQL 文件 |
createUserSession.ts | 为指定作者创建登录会话(配合访问控制) |
deleteAllGroupSessions.ts | 清空分组会话 |
checkPad.ts 系列 | 见 5.2 |
六、HTTP API 实测主线
6.1 认证方式
- API key 模式(
AUTHENTICATION_METHOD=apikey):请求带apikey参数即可,官方同时接受api_key、authorization三个参数名(任选其一,源码实测确认); - sso 模式(默认):不启用 APIKEY.txt,HTTP API 走 OIDC 令牌;curl 直调报错实测:
curl -s "http://127.0.0.1:8134/api/1/createPad?padID=demo1"
实测输出:
{"code":4,"message":"no or wrong API Key","data":null}
key 错误同理返回 code 4。key 校验为常数时间比较(防时序攻击,源码注释确认)。
6.2 API 版本与函数分级(关键实测发现)
API 版本查询:
curl -s http://127.0.0.1:8134/api
实测输出:
{"currentVersion":"1.3.1"}
URL 中的版本号决定可用函数集:/api/1/ 只有 v1 基础函数;/api/1.3.1/ 才有全量函数。实测对照(同一函数不同版本路径):
curl -s "http://127.0.0.1:8134/api/1/listAllPads?apikey=$KEY"
curl -s "http://127.0.0.1:8134/api/1.3.1/listAllPads?apikey=$KEY"
实测输出:
{"code":3,"message":"no such function","data":null}
{"code":0,"message":"ok","data":{"padIDs":["apidemo","persist-test"]}}
排障提示:遇到 {"code":3,"message":"no such function"} 先检查 URL 版本路径,再怀疑函数不存在。
6.3 pad 生命周期端点(创建/读写/版本)
KEY=$(cat /opt/etherpad/data/APIKEY.txt)
B="http://127.0.0.1:8134/api/1.3.1"
创建 pad(返回一次性删除令牌 deletionToken,用于无账号删除 pad):
curl -s "$B/createPad?apikey=$KEY&padID=apidemo&text=hello%20api"
实测输出:
{"code":0,"message":"ok","data":{"deletionToken":"31689af77cb42957cd5e5c28b88145798fd2c347e9f6b7fdd8ac344f74d92a3c"}}
重复创建同名 pad 返回 code 1:
{"code":1,"message":"padID does already exist","data":null}
写文本(POST 表单):
curl -s -X POST "$B/setText?apikey=$KEY&padID=apidemo" -d 'text=line1%0Aline2%0Aline3'
实测输出:
{"code":0,"message":"ok","data":null}
读文本:
curl -s "$B/getText?apikey=$KEY&padID=apidemo"
实测输出:
{"code":0,"message":"ok","data":{"text":"line1\nline2\nline3\n"}}
读 HTML(富文本形态):
curl -s "$B/getHTML?apikey=$KEY&padID=apidemo"
实测输出:
{"code":0,"message":"ok","data":{"html":"<!DOCTYPE HTML><html><body>rev2 content<br></body></html>"}}
版本数与最后编辑时间:
curl -s "$B/getRevisionsCount?apikey=$KEY&padID=apidemo"
curl -s "$B/getLastEdited?apikey=$KEY&padID=apidemo"
实测输出:
{"code":0,"message":"ok","data":{"revisions":1}}
{"code":0,"message":"ok","data":{"lastEdited":1792603950370}}
只读 ID 与反查:
curl -s "$B/getReadOnlyID?apikey=$KEY&padID=apidemo"
curl -s "$B/getPadID?apikey=$KEY&roID=r.4800fb390418296b3ea1fe4fca6c4704"
实测输出:
{"code":0,"message":"ok","data":{"readOnlyID":"r.4800fb390418296b3ea1fe4fca6c4704"}}
{"code":0,"message":"ok","data":{"padID":"apidemo"}}
6.4 聊天、作者与统计端点
# 追加聊天消息
curl -s -X POST "$B/appendChatMessage?apikey=$KEY&padID=apidemo" -d 'text=hello%20from%20api'
# 读聊天历史
curl -s "$B/getChatHistory?apikey=$KEY&padID=apidemo"
# 创建作者
curl -s -X POST "$B/createAuthor?apikey=$KEY" -d 'name=tester'
# 实例统计
curl -s "$B/getStats?apikey=$KEY"
实测输出:
{"code":0,"message":"ok","data":null}
{"code":0,"message":"ok","data":{"messages":[{"text":"hello from api","time":1792604006921,"userId":null,"userName":null}]}}
{"code":0,"message":"ok","data":{"authorID":"a.ooP4hVODnEX3BVXn"}}
{"code":0,"message":"ok","data":{"totalPads":2,"totalSessions":0,"totalActivePads":0}}
6.5 删除 pad 与错误码总表
curl -s "$B/deletePad?apikey=$KEY&padID=apidemo"
实测输出:
{"code":0,"message":"ok","data":null}
对不存在 pad 执行删除/读取返回 code 1(本机先用 bin 脚本删除 mixedcase99 后再用 API 删同一 pad 的实测):
{"code":1,"message":"padID does not exist","data":null}
错误码汇总(全部实测命中):
| code | 含义 | 实测触发方式 |
|---|---|---|
| 0 | 成功 | 正常调用 |
| 1 | 业务错误(pad 不存在/已存在等) | 读/删不存在的 pad;重复 createPad |
| 3 | 函数不存在 | URL 版本路径下无此函数(如 /api/1/listAllPads) |
| 4 | 认证失败 | 缺 apikey / key 错误 / sso 模式未带令牌 |
七、注意事项
- bin 脚本统一
cd /opt/etherpad-lite/src后执行(tsx 解析依赖 src/node_modules),并以运行服务的账号(如etherpad)身份执行; - 插件装卸后需重启服务进程才能加载/卸载前端资源;
- HTTP API 的写操作(setText/setHTML)会直接产生新修订,与网页编辑等效,注意与在线用户并发编辑的相互覆盖;
deletePad不可逆;带 deletionToken 的无账号删除走deletePad端点时以 token 参数代替 apikey 身份;- API 逐函数参数表见官方文档 https://docs.etherpad.org/api.html(与 1.3.1 函数表一致,查询日期 2026-10-22)。
八、常见问题
Q1:bin 脚本报 Cannot find module 'tsx/cjs'
在错误目录执行导致。统一 cd /opt/etherpad-lite/src && node --require tsx/cjs ../bin/<脚本>.ts。
Q2:deletePad/extractPadData 报找不到 settings.json.docker
脚本族走测试配置加载器。cp settings.json settings.json.docker(在 /opt/etherpad-lite 下)后重跑(见 5.3 排障实录)。
Q3:extractPadData 报 Cannot find module 'dirty'
镜像未预装该模块。cd /opt/etherpad-lite/bin && pnpm add dirty(必须装在 bin 下,见 5.4 排障实录)。
Q4:插件安装 404 或连接失败
插件名以官方索引为准(404 即名字不存在,如 ep_headerview);连接失败先给执行环境配代理(见 5.1 排障实录)。
Q5:API 返回 no such function
URL 版本路径低于函数引入版本。统一用 /api/1.3.1/(见 6.2 实测)。
九、参考链接
- 官方 HTTP API 文档:https://docs.etherpad.org/api.html (查询日期 2026-10-22)
- 官方插件索引:https://static.etherpad.org/index.html (查询日期 2026-10-22)
- bin 脚本源码目录:https://github.com/ether/etherpad/tree/HEAD/bin (查询日期 2026-10-22)
- 站内延伸:《Etherpad 介绍与选型指南》《Etherpad 3.3.9 Docker Compose 部署指南》《Etherpad 3.3.9 配置参数详解》