Gancio 1.28.2 常用 CLI 命令与工具详解
gancio CLI 四子命令实测全解:migrate 在 Docker 镜像内坏路径的源码级定位与替代方案、users 七子命令全生命周期回显、settings 值必须 JSON/键名/重启三大陷阱、CLI 调用模板与守护消息、data 目录备份恢复与排障工具链速查。
Gancio 1.28.2 常用 CLI 命令与工具详解
目标:Gancio 自带一个 Node.js CLI(容器内
/usr/local/bin/gancio),命令面只有migrate / start / users / settings四个子命令,但每个都有值得逐字讲清的实测行为——尤其是gancio migrate在 Docker 镜像里是一条"永远短路"的坏路径(源码级定位见第四节)。本文基于 1.28.2 镜像内源码逐文件核对(server/cli.js、server/cli/users.js、server/cli/settings.js、server/config.js、server/api/models/index.js)与运行实例实测(users 七个子命令全生命周期、settings 三大陷阱、migrate 三种参数组合、错误路径守护回显),给出逐命令手册与配套的数据管理、排障工具链。配置三层模型见《Gancio 1.28.2 配置参数详解》,部署流程见《Gancio 1.28.2 Docker Compose 部署指南》。
一、环境信息
- 实测载体:Gancio 1.28.2(Docker Compose 部署,镜像
cisti/gancio:1.28.2,运行时 Node.js v20.19.6),宿主端口 8149 → 服务端口 13120,数据目录/opt/gancio/data - 源码取证:镜像内程序目录
/home/node/server/,CLI 入口/usr/local/bin/gancio - 所有命令回显均为容器内实测逐字记录;文中测试账号
cli-test@example.com建后即删,现场仅保留 admin
二、CLI 命令面总览
2.1 入口脚本与版本横幅
容器内 gancio 就是 /usr/local/bin/gancio(带 #!/usr/bin/env node shebang 的 server/cli.js 本体),用 yargs 组装命令树。任何调用都会先打一行版本横幅,这是确认 CLI 与镜像版本一致的最快方式:
$ docker exec gancio gancio --version
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
1.28.2
横幅格式 📅 gancio - v<版本> - <description> (nodejs: <node版本>) 与启动日志横幅同源(cli.js 的 console.info),排查"CLI 与运行中服务版本不一致"时对比这两处即可。
2.2 顶层命令表(实测 --help 全量回显)
$ docker exec gancio gancio --help
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
Usage gancio <command> [options]
Commands:
gancio migrate Run database migration
gancio start Start gancio [default] [aliases: run]
gancio users Manage users
gancio settings Manage settings
Options:
--version Show version number [boolean]
-c, --config Configuration file [default: "/home/node/data/config.json"]
-h, --help Show help [boolean]
Made with ❤ by underscore hacklab - https://gancio.org
四个命令各司其职:
| 命令 | 作用 | 日常使用频率 |
|---|---|---|
start(默认,别名 run) | 启动服务(内部走 @nuxt/cli-edge 的 start --modern) | 由容器 entrypoint / restart: always 代管,手动场景少 |
migrate | 手动跑数据库迁移 | Docker 镜像内实测无效,见第四节 |
users | 账号管理七个子命令 | 高:忘密、建管理员、禁用用户全靠它 |
settings | 数据库 settings 表读写 | 高:无网页后台时用 CLI 改配置 |
yargs 开了 .recommendCommands(),打错命令会提示相近命令;.demandCommand(1, '') 使裸跑 gancio 直接执行默认命令 start。
2.3 -c/--config 的解析链
cli.js 顶部两行决定了所有配置读取行为:
process.env.cwd = process.env.GANCIO_DATA || path.resolve('./')
process.chdir(path.resolve(__dirname, '..'))
-c的默认值是path.resolve(process.env.cwd, 'config.json'),即$GANCIO_DATA/config.json(官方镜像环境变量GANCIO_DATA=/home/node/data,所以 help 里显示/home/node/data/config.json);-c的coerce函数会把解析后的绝对路径写进process.env.config_path,server/config.js的load()据此读文件;- 进程随后
chdir到包根/home/node——这个细节正是第四节 migrate 坏路径的根源。
三、start:默认启动命令
start 的实现只有一件事:require('@nuxt/cli-edge').run(['start', '--modern']),即拉起 Nuxt 生产服务。Gancio 前端是 SSR 的 Nuxt 应用,没有独立的"前端构建"CLI 步骤(镜像内已构建完毕)。
Docker 部署下你几乎不需要手动 gancio start:容器 entrypoint 就是它,配合 restart: always 自动拉起。需要手动使用的场景:
- 进程假死需要前台观察启动过程:
docker exec -it gancio gancio start可直接看到迁移、插件加载、监听横幅; - 裸机(非 Docker)安装:
gancio.org/latest.tgz解包后node server/cli.js start(或全局链接后gancio start); - 改 settings 后重启生效:Docker 下用
docker restart gancio更干净(CLI 改 settings 的回显原话:Note that a restart is needed to get the new setting)。
四、migrate:Docker 镜像内的"坏路径"(实测 + 源码定位)
4.1 现象:配置完好的实例上 migrate 永远短路
对一个早已完成 setup、服务正常运行的实例执行 gancio migrate(实测三种参数组合,结果完全一致):
$ docker exec --workdir /home/node/data gancio gancio migrate
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
> Reading configuration from: ./config.json
> Configuration file does not exists...
> Cannot run database migration before setup
显式传 -c(放在命令前后两种顺序)也一样:
$ docker exec --workdir /home/node/data gancio gancio -c /home/node/data/config.json migrate
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
> Reading configuration from: ./config.json
> Configuration file does not exists...
> Cannot run database migration before setup
且退出码为 0(RC=0)——脚本化调用时无法靠 $? 发现它没干活。
4.2 源码定位:migrate 被挂成了 builder,跑在 -c coerce 之前
cli.js 的命令注册:
.command(['migrate'], 'Run database migration', migrate) // 第三个参数是 builder!
yargs 的 command(cmd, desc, builder, handler) 签名里第三个位置是 builder(用于给子命令加参数),第四个才是 handler。migrate 函数被放在 builder 位置,于是迁移逻辑在 yargs 解析全局 -c 选项的 coerce 之前就被同步执行。此时 process.env.config_path 尚未被 coerce 写入,config.js 的 load() 落到兜底值:
const config_path = process.env.config_path || './config.json'
而进程早已 chdir 到包根 /home/node——那里只有 config.example.json,没有 config.json,于是 fs.existsSync('./config.json') 为 false,状态判定 SETUP,migrate() 打出 Cannot run database migration before setup 后直接 return。users/settings 的子命令挂在 handler 位置(builder 之后执行),coerce 已生效,所以不受影响——这解释了为什么同一实例上 gancio users list 能读到 /home/node/data/config.json 而 migrate 不能。
4.3 为什么不用担心:迁移由 start 自动完成
migrate 做的事(db.runMigrations(),umzug + sequelize storage,迁移文件在 /home/node/migrations/)在每次 start 启动流程里都会自动执行(initialize.server.js 第 32 行同样调用 db.runMigrations())。首启建库的实测回显(节选自启动日志):
2026-11-01T14:57:04.182Z debug: == 20191025133803-tags: migrated (0.006s)
2026-11-01T14:57:04.188Z debug: == 20191025134318-places: migrated (0.005s)
2026-11-01T14:57:04.195Z debug: == 20191025135631-settings: migrated (0.005s)
2026-11-01T14:57:04.201Z debug: == 20191025141447-users: migrated (0.004s)
2026-11-01T14:57:04.209Z debug: == 20191025142724-events: migrated (0.005s)
首次建库共 54 条 migrated 记录。升级场景同理:docker compose pull && docker compose up -d 后新版本启动时自动跑增量迁移(实测 1.27.0 ↔ 1.28.2 来回切换数据完好),umzug 用 SequelizeMeta 表记账,已应用的迁移不会重跑。
4.4 结论与操作口径
- Docker 部署:忘掉
gancio migrate。它不报错、不干活、退出码还是 0;需要迁移时直接重启服务(docker restart gancio)让 start 流程代跑。 migrate真正有效的场景是裸机安装且config.json放在包根(./config.json恰好能被兜底路径命中)时的离线建库。- 若你在 Docker 里看到
Cannot run database migration before setup,不代表实例没配置好,这是 4.2 的坏路径,与实例状态无关。
五、users:七个子命令全生命周期实测
5.1 子命令一览(实测 gancio users --help)
$ docker exec gancio gancio users --help
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
gancio <command>
Commands:
gancio users list List all users
gancio users enable <email> Enable an user
gancio users disable <email> Enable an user
gancio users reset-password <email> Resets the password of the given
user
gancio users set_role <email> <role> Set specified role privileges to the
given user
gancio users create <email> [password] Create an user (role could be
[role] `user`, `admin` or `editor`)
gancio users remove <email> Remove an user
Options:
--version Show version number [boolean]
-c, --config Configuration file [default: "/home/node/data/config.json"]
-h, --help Show help [boolean]
注意 disable 的描述文案写成了 Enable an user——这是上游 cli/users.js 的笔误(复制粘贴未改),不影响功能。
5.2 生命周期实测(建 → 查 → 禁 → 启 → 重置密码 → 改角色 → 删)
以下为一气呵成的实测回显(每步都是独立进程,均带横幅与配置读取行):
$ docker exec --workdir /home/node/data gancio gancio users create cli-test@example.com P@ssw0rd123 user
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
> Reading configuration from: /home/node/data/config.json
User "cli-test@example.com" created with role user
$ docker exec --workdir /home/node/data gancio gancio users list
...
1 role: admin enabled: true email: admin
2 role: user enabled: true email: cli-test@example.com
$ docker exec --workdir /home/node/data gancio gancio users disable cli-test@example.com
...
User cli-test@example.com is now disabled!
$ docker exec --workdir /home/node/data gancio gancio users enable cli-test@example.com
...
User cli-test@example.com is now enabled!
$ docker exec --workdir /home/node/data gancio gancio users reset-password cli-test@example.com
...
New password for user cli-test@example.com is '9zaxxcy3ysye'
$ docker exec --workdir /home/node/data gancio gancio users set_role cli-test@example.com editor
...
User cli-test@example.com role is now editor!
$ docker exec --workdir /home/node/data gancio gancio users remove cli-test@example.com
...
User "cli-test@example.com" succesfully removed
users list 的输出是 Tab 分隔的 id / role / enabled / email 四列,可直接管道给 awk 处理。
5.3 细节与陷阱(源码 + 实测)
-
<email>是"账号名",不一定是邮箱。Gancio 允许非邮箱形式的账号名(setup 创建的管理员账号就叫admin),CLI 按where: { email: args.email }精确匹配,写错大小写即 not found。 -
create的 role 有白名单校验,非法值直接被 yargs 拒绝(实测):$ docker exec --workdir /home/node/data gancio gancio users set_role admin superuser ... Invalid values: Argument: role, Given: "superuser", Choices: "user", "admin", "editor"三种角色权限差异:
admin全站管理,editor可管理活动/地点/标签但无系统设置,user仅提交活动。 -
reset-password只支持随机密码(helpers.randomString()),不能指定新密码;回显New password for user <账号> is '<随机串>'是唯一的取密途径,输出后不落盘,请立即记录。想设固定密码:先create(可带[password])或先reset-password再在网页端改。 -
create不带[password]时密码为空串(源码直接透传args.password),该账号无法登录,务必显式给密码。 -
用户不存在时的回显分两种(实测):
enable/disable/reset-password/set_role打User <账号> not found;remove打User "<账号>" not found!(带引号和叹号)。这些提示走 stderr/stdout 混排,脚本判断成败建议以users list复查为准。 -
create/remove 的成功提示走
console.error(stderr),list/enable 等走 stdout——重定向2>/dev/null会"吞掉"建号成功的证据。 -
CLI 操作立即对运行中的服务生效(直接写库,无需重启);禁用用户即刻阻断其登录,实测无需任何额外动作。
-
救急场景:管理员密码忘记且 SMTP 未配置(无法网页端找回)时,一条
gancio users reset-password admin即可夺回控制权;误删 admin 用gancio users create admin <密码> admin重建(部署篇 4.x 的实测路径)。
六、settings:list / get / set 三子命令
6.1 子命令与实测回显
$ docker exec gancio gancio settings --help
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
gancio <command>
Commands:
gancio settings list List all settings
gancio settings get <setting> Get value of specified setting
gancio settings set <setting> <value> Set value of specified setting
Options:
--version Show version number [boolean]
-c, --config Configuration file [default: "/home/node/data/config.json"]
-h, --help Show help [boolean]
settings list 输出数据库 settings 表全量 47 键(key: JSON值 逐行),前几行实测:
title: "Quzuo 社区日历"
description: "A shared agenda for local communities"
baseurl: "http://127.0.0.1:8149"
hostname: "127.0.0.1"
instance_timezone: "Europe/Rome"
instance_locale: "zh"
settings get <setting> 输出 <setting>: <JSON值>;键不存在时(实测):
$ docker exec --workdir /home/node/data gancio gancio settings get locale
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
> Reading configuration from: /home/node/data/config.json
Setting "locale" does not exists
6.2 陷阱一:value 必须是合法 JSON
settings set 的源码在 cli/settings.js:42 对 value 做 JSON.parse(args.value),裸串直接炸出堆栈(实测):
$ docker exec --workdir /home/node/data gancio gancio settings set title 排错测试
title
Old value: "Quzuo 社区日历"
New value: 排错测试
Note that a restart is needed to get the new setting
...
SyntaxError: Unexpected token '排', "排错测试" is not valid JSON
at JSON.parse (<anonymous>)
at Object.set [as handler] (/home/node/server/cli/settings.js:42:53)
注意回显顺序迷惑性:先打 Old/New value 和 restart 提示,最后才 JSON.parse 失败——看到 New value: 不代表写库成功。正确写法是给值再包一层 JSON 双引号:
docker exec --workdir /home/node/data gancio gancio settings set title '"新的站点标题"'
docker exec --workdir /home/node/data gancio gancio settings set allow_registration 'false'
docker exec --workdir /home/node/data gancio gancio settings set geocoding_countrycodes '["cn","it"]'
字符串要 "...",布尔/数字/数组/对象直接写 JSON 字面量。写成功后 settings get 复查(实测回显 title: "Quzuo 社区日历" 形态)。
6.3 陷阱二:键名以 settings list 为准
settings 表键名有前缀约定,直觉名往往不存在:语言是 instance_locale(不是 locale)、时区是 instance_timezone(不是 timezone)、站点名是 instance_name。改前先 settings list 或 settings get 确认键名,报 Setting "<key>" does not exists 即键名错了。
6.4 陷阱三:改完必须重启;instance_name 另有联邦警告
-
所有
set都会提示Note that a restart is needed to get the new setting(服务进程内存里缓存 settings,Docker 下docker restart gancio生效)。 -
源码对
instance_name有专属警告(cli/settings.js):Note that this will likely break current federation (all your follower / following connections will be destroyed)!联邦身份以如实例名派生,改名等于换人,改前想清楚。
七、调用姿势与守护回显
7.1 标准调用模板
CLI 读的是数据目录里的 config.json/SQLite,Docker 部署统一用:
docker exec --workdir /home/node/data gancio gancio <command>
--workdir /home/node/data保证相对路径行为与容器服务一致(GANCIO_DATA=/home/node/data时-c默认值本已正确,带上更保险);- 命令里第二个
gancio是 CLI 程序名,第一个是容器名(按官方模板container_name: gancio,自行改名则替换)。
7.2 路径错误的守护回显
users/settings 的公共初始化 _initializeDB() 检查 config.status !== 'CONFIGURED' 即退出。把 GANCIO_DATA 指到没有 config.json 的目录实测:
$ docker exec -e GANCIO_DATA=/tmp/nope --workdir /home/node/data gancio gancio users list
📅 gancio - v1.28.2 - A shared agenda for local communities (nodejs: v20.19.6)
> Reading configuration from: /tmp/nope/config.json
> Configuration file does not exists...
> Cannot run CLI before setup (are you in the correct path?)
RC=1
这条 are you in the correct path? 提示(退出码 1)就是"CLI 找不到 config.json"的标准症状:检查 -c 路径、GANCIO_DATA 变量、数据目录挂载是否齐全。与第四节 migrate 的同族消息区别:migrate 的 Cannot run database migration before setup 在 Docker 里是必然出现的坏路径,不代表配置有问题。
八、数据管理工具链
8.1 数据目录结构(容器内 /home/node/data,宿主挂载点)
data/
├── config.json # 实例配置(setup 后生成,见配置篇)
├── gancio.sqlite # SQLite 主数据库(dialect=postgresql/mariadb 时无此文件)
├── logs/ # winston 日志目录(config.log_path)
│ ├── gancio.log # 当日主日志
│ ├── gancio.YYYY-MM-DD.log # daily rotate 历史
│ └── .<hash>-audit.json # rotate 策略元数据
└── uploads/ # 活动图片等上传文件(config.upload_path)
备份 = 整个 data 目录:DB + 配置 + 上传文件三者缺一不可,只 dump SQLite 会丢图片。
8.2 备份与恢复(官方口径 + 实测演练)
官方 backup 口径就是在数据目录内打 tar:
cd /opt/gancio/data
tar -czf gancio-$(date +%Y-%m-%d-%H%M%S)-backup.tgz \
$(ls -d config.json uploads gancio.sqlite logs 2>/dev/null)
实测产物 16131 字节(含一条活动与一张占位数据的完整库)。恢复演练实测流程:
docker stop gancio
mv data data.broken # 或删掉 gancio.sqlite 模拟库损
mkdir data && tar -xzf gancio-*-backup.tgz -C data
docker start gancio
curl -s http://127.0.0.1:8149/api/events # 仍返回备份时的活动 id=1,恢复成功
恢复后首次启动会跑增量迁移(版本一致则无操作),无需手工干预——这正是第四节"迁移交给 start"的又一次佐证。
8.3 日志查看
- 服务日志:
docker logs gancio(容器 stdout,含启动横幅与迁移回显)与data/logs/gancio.log(winston 文件,daily rotate)内容同源互补,排障先看文件日志(带时间戳与级别)。 - 日志级别由
config.json的log_level控制(默认debug,生产可降info,改后重启生效)。 - CLI 子进程自带降噪:
_initializeDB()里强制config.log_level = 'error',所以users/settings执行时不会把服务端 debug 日志混进回显。
8.4 直接查库:容器内没有 sqlite3 客户端
实测 which sqlite3 为空——cisti/gancio 镜像是纯运行时,不带 sqlite3 CLI。需要裸查数据库时的三个替代:
# 1. 宿主装 sqlite3,直接开挂载文件(服务运行中慎写,读无妨)
sqlite3 /opt/gancio/data/gancio.sqlite 'SELECT id,role,is_active,email FROM "User";'
# 2. 容器内用自带的 node + sequelize 跑一次性查询
docker exec gancio node -e "
const db=require('/home/node/server/api/models/index');
db.initialize().then(()=>db.models.User.findAll())
.then(us=>{us.forEach(u=>console.log(u.id,u.role,u.is_active,u.email));return db.close()})"
# 3. 导出 SQL 转储(宿主装 sqlite3 后 .dump)
日常需求优先走 CLI(第五、六节)与 REST API,避免裸写库。
九、排障工具链速查
| 症状 | 工具/命令 | 实测判据 |
|---|---|---|
| 服务是否活着 | curl -s http://127.0.0.1:8149/api/ping | READY 后返回 OK |
| CLI 报"before setup" | 检查 -c/GANCIO_DATA/挂载 | 见 7.2;migrate 见第四节 |
| 忘管理员密码 | gancio users reset-password admin | 回显随机新密码 |
| 管理员被误删 | gancio users create admin <密码> admin | 回显 created with role admin |
| 改 settings 不生效 | docker restart gancio | CLI 原话要求重启 |
| 确认某配置值 | gancio settings get <key> | 读的是库值,重启后前端才同步 |
| 用户登不上 | gancio users list 看 enabled | is_active=false 即被禁用 |
| 升级后疑似迁移失败 | docker logs gancio | grep migrated | umzug 逐条 == <ts>-<name>: migrated |
| 联邦/订阅面检查 | GET /feed/rss、/.well-known/nodeinfo | RSS 频道标题即 title 设置值 |
| 登录接口手工验证 | POST /oauth/login(form,client_id=self) | 返回 access_token 即凭据正常 |
十、小结与互链
- Gancio CLI 命令面小而实:
users是账号急救刀,settings是库内配置的裸接口,start顺带负责全部迁移,migrate在 Docker 镜像里是坏路径可以无视。 - 使用
settings set记住三件事:值要 JSON、键名查 list、改完重启。 - 备份认 data 目录整体,恢复靠重启自动对齐 schema。
系列文档:
- 《Gancio 介绍与选型指南》——定位与同类对比
- 《Gancio 1.28.2 Docker Compose 部署指南》——从零部署与首启向导
- 《Gancio 1.28.2 配置参数详解》——环境变量/config.json/settings 表三层模型
- 同类 CLI 手册参考:《Radicale 3.9 常用 CLI 命令与运维详解》