Habitica v5.52.0 常用 CLI 命令与工具详解

Habitica v5.52.0 自托管运维命令手册:systemd 服务管理、npm/gulp 构建测试脚本族、REST API 注册/登录/四类任务/cron 实操、MongoDB 备份恢复闭环与数据形态巡检、BullMQ 邮件队列运维,全部命令 Ubuntu 22.04 实测附回显。

HabiticaHabitica任务管理2026/10/28

Habitica v5.52.0 常用 CLI 命令与工具详解

目标:整理 Habitica v5.52.0 自托管日常运维的命令与工具箱——systemd 服务管理、npm 脚本族与 gulp 构建任务、REST API 用户/任务/每日结算的命令行操作、MongoDB 备份恢复闭环与数据形态巡检、Redis 队列运维,全部命令在 Ubuntu 22.04 服务器的 v5.52.0 环境实测并附回显。安装与配置参数背景分别见本专栏安装指南篇与配置详解篇。

一、环境信息

本篇实测环境:

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64);Habitica v5.52.0(commit 12091ca)
  • 服务形态:systemd 单元 habitica-web,入口 /opt/habitica/website/transpiled-babel/index.js(NODE_ENV=production,WEB_CONCURRENCY=1)
  • 依赖组件:Node.js v20.20.2 / MongoDB v7.0.45(单节点副本集 rs)/ Redis v8.10.3
  • 服务地址:http://10.89.71.10:3000(本机内网 IP,读者替换)
  • 演示账号:habadmin / q1w2e3r4(注册流程见 4.2 节,apiToken 见 4.3 节)
  • 工作目录:/opt/habitica(下文命令默认在此执行)

💡 说明:Habitica 没有自带的管理 CLI(不同于 NodeBB 的 ./nodebb 命令族),日常运维由三部分组成:systemd 管进程、npm/gulp 管构建与测试、REST API + 数据库工具管业务数据。本篇按这三条线展开。

二、服务进程管理(systemd)

2.1 启停与状态

sudo systemctl start habitica-web
systemctl is-active habitica-web mongod redis-server
active
active
active
systemctl status habitica-web --no-pager | head -12
● habitica-web.service - Habitica Web Server
     Loaded: loaded (/etc/systemd/system/habitica-web.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2026-10-28 07:40:05 UTC; 15s ago
   Main PID: 8645 (node)
      Tasks: 18 (limit: 19553)
     Memory: 160.4M
        CPU: 1.894s
     CGroup: /system.slice/habitica-web.service
             ├─8645 /usr/bin/node /opt/habitica/website/transpiled-babel/index.js
             └─8652 /usr/bin/node /opt/habitica/website/transpiled-babel/index.js

状态解读:WEB_CONCURRENCY=1 时进程树为 1 主 + 1 worker——主进程(Main PID 8645)只负责 cluster 监控与 worker 重拉,HTTP 流量在 worker(8652)上;内存统计 160.4MB 是两进程合计。停用、重启与开机自启:

sudo systemctl stop habitica-web && systemctl is-active habitica-web
inactive
sudo systemctl restart habitica-web && systemctl is-active habitica-web
active
systemctl is-enabled habitica-web
enabled

改配置后的标准生效动作(新开 shell 逐条执行):

sudo systemctl daemon-reload && sudo systemctl restart habitica-web

2.2 日志查看(journalctl)

journalctl -u habitica-web --no-pager -n 20

实测默认情况下只有 systemd 的启停生命周期行(Started/Stopped habitica-web.service),看不到应用日志——生产模式 winston 默认无 Console transport(配置详解篇 6.3 节)。排障时给单元临时加环境变量开启:

sudo systemctl edit habitica-web

写入:

[Service]
Environment=ENABLE_CONSOLE_LOGS_IN_PROD=true
sudo systemctl daemon-reload && sudo systemctl restart habitica-web

之后 journalctl -u habitica-web -f 可实时看到文本+JSON 双格式应用日志。排障结束建议移除该覆盖(sudo systemctl revert habitica-web)恢复静默。

2.3 手动前台启动(对照与应急)

systemd 之外,应急排查可直接前台运行(能看到 winston 的 no-transports 提示与 worker 崩溃堆栈):

sudo -u habitica env NODE_ENV=production node website/transpiled-babel/index.js

开发态另有两个 npm 启动脚本(源码 package.json scripts 实查):npm start(node --watch ./website/server/index.js,带文件监听自动重启,运行源码目录并实时挂 @babel/register 转译)与 npm run debug(附加 --inspect 暴露调试端口)。注意开发态入口跑的是 website/server/ 源码,生产 systemd 单元跑的是 website/transpiled-babel/ 预转译产物,两套入口共用同一份 config.json。

2.4 worker 崩溃循环的识别

worker 异常退出时主进程自动重拉,日志特征是 worker:xxxx disconnect! new worker:yyyy fork 循环出现。配置详解篇实测的三个崩溃根因(PAYPAL_MODE/FLAG_REPORT_EMAIL/GOOGLE_CLIENT_ID/SECRET 缺失)均以此形态表现。快速判别:

ps -ef | grep 'transpiled-babel' | grep -v grep | wc -l
4

数值应稳定为 WEB_CONCURRENCY + 1;若 PID 短时间内持续变化,即崩溃循环,优先查配置。

三、构建与测试命令(npm 脚本族)

3.1 常用脚本一览

源码 package.json 的 scripts 字段(v5.52.0 实查)中与运维相关的子集:

命令实际执行用途
npm startnode --watch ./website/server/index.js开发态启动(源码+实时转译+watch)
npm run debugnode --watch --inspect ./website/server/index.js开发态启动+调试端口
npm run client:buildcd website/client && npm run build前端生产构建(vite build)
npm run client:devcd website/client && npm run serve前端开发服务(vite dev)
npm run linteslint 全仓 + 客户端 lint(带 --fix)代码风格修复
npm run lint-no-fixeslint 全仓 + 客户端 lint(只查不改)代码风格检查
npm run client:unitcd website/client && npm run test:unit前端单元测试(vitest)
npm run test:api-v3 等gulp test:api-v3 族API 集成测试(gulp 驱动)
npx gulp build:prodBabel 预转译 + 内容缓存生产构建(后端)
npx gulp sprites:compile雪碧图编译素材变更后重建

3.2 前端构建(client:build 实测)

cd /opt/habitica && sudo -u habitica npm run client:build

输出节选(实测):

vite v6.4.1 building for production...
transforming...
rendering chunks...
✓ built in 8.74s

产物落在 website/client/dist/(实测 93MB),生产模式由服务端直接托管该目录。改前端源码或升级版本后重跑即可。

3.3 后端预转译(gulp build:prod 实测)

cd /opt/habitica && sudo -u habitica env NODE_ENV=production npx gulp build:prod

输出节选(实测):

[07:31:42] Finished 'build:babel' after 6.7 s
[07:31:42] Finished 'build:cache' after 5.08 s
[07:31:42] Finished 'build:prod' after 7.16 s

产出 website/transpiled-babel/(服务端)与 website/common/transpiled-babel/(公共逻辑)。必须带 NODE_ENV=production——gulpfile 按该变量选择 prod/dev 分支,漏带则不产出转译目录。升级 Habitica 版本后必须重跑本命令再重启服务。

3.4 代码检查(lint-no-fix 实测)

cd /opt/habitica && sudo -u habitica npm run lint-no-fix

输出节选(实测,耗时约 1-2 分钟):

✖ 542 problems (0 errors, 542 warnings)
  0 errors and 37 warnings potentially fixable with the `--fix` option.

v5.52.0 源码基线本身携带 542 条 warning、0 error——这是上游代码的固有状态(命令退出码非 0 也源于此),修改自定义代码后对比 warning 增量即可判断自己是否引入问题。需要自动修复用 npm run lint(带 --fix)。

3.5 前端单元测试(client:unit 实测)

cd /opt/habitica && sudo -u habitica npm run client:unit

结果摘要(实测):

 Test Files  5 failed | 27 passed | 2 skipped (34)
      Tests  174 passed | 5 skipped (179)

174 个用例全部通过;5 个测试文件失败属上游基线状态(文件级 setup 依赖导致,用例本身无失败),升级后同样以「用例通过数」为对照基线。API 集成测试族(npm run test:api-v3 等)依赖完整数据库环境且会动测试库,本篇未全量执行,仅实测了上述前端单测,特此说明。

四、用户与认证:命令行操作 API

Habitica 的业务操作走 REST API(/api/v3 与 /api/v4,v4 为 v3 的路由代理与部分端点覆盖)。命令行交互用 curl + 两个认证头:x-api-user(用户 ID)与 x-api-key(API Token)。

4.1 注册用户(排障实录:保留词拦截)

curl -s -X POST http://10.89.71.10:3000/api/v4/user/auth/local/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"habadmin","password":"q1w2e3r4","email":"admin@example.com","confirmPassword":"q1w2e3r4"}' | head -c 200
{"success":true,"data":{"auth":{"local":{"email":"admin@example.com","username":"habadmin","lowerCaseUsername":"habadmin","has_password":true}, ...

⚠️ 排障实录:用户名 admin 实测被拒——{"success":false,"error":"BadRequest","message":"Usernames may not contain restricted words."}。服务端保留词库 website/server/libs/bannedWords.js 收录了 admin 等词,校验为整词边界正则(libs/user/validation.js:11),故 habadmin 这类复合词可通过。密码强度仅要求长度,q1w2e3r4(8 位)实测可注册,生产请用强口令。

4.2 登录获取 apiToken

curl -s -X POST http://10.89.71.10:3000/api/v4/user/auth/local/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"habadmin","password":"q1w2e3r4"}'
{"success":true,"data":{"id":"118ccfe6-2c4d-46be-9f9e-3b2d345d55d5","apiToken":"<32位UUID>","newUser":false,"username":"habadmin"},"appVersion":"5.52.0"}

v4 登录响应极简:id 即认证用户 ID(x-api-user),apiToken 即认证密钥(x-api-key)。两者也可在 Web 端「设置 → API」页查看。Web 端管理员/普通用户权限差异由站内_roles_控制,命令行 API 默认以账号自身权限执行。

4.3 带认证头查询用户(实测)

U=118ccfe6-2c4d-46be-9f9e-3b2d345d55d5
T=<你的apiToken>
curl -s http://10.89.71.10:3000/api/v4/user -H "x-api-user: $U" -H "x-api-key: $T" | \
  python3 -c "import json,sys; u=json.load(sys.stdin)['data']; s=u['stats']; print('name:',u['profile']['name'],'| lvl:',s['lvl'],'| hp:',s['hp'],'| xp:',s['exp'],'| gold:',s['gp'])"
name: habadmin | lvl: 1 | hp: 50 | xp: 0 | gold: 0

认证头错误时的实测表现(用于判断排障方向):

curl -s http://10.89.71.10:3000/api/v4/user -H "x-api-user: $U" -H "x-api-key: wrong-token" | head -c 120
{"success":false,"error":"NotAuthorized","message":"Not authorized to access data."}

4.4 限流注意

开启限流后(配置详解篇 7.3 节实测:v4 桶 200 点、未认证请求按 IP 每次扣 5 点),命令行批量脚本要注意扣点节奏,桶耗尽会收到 429 与 Retry-After 头;注册与登录接口单次扣 10 点。

五、任务管理:四类任务的命令行操作

Habitica 的核心数据模型是四类任务:habit(习惯,可加减分)、daily(每日,cron 结算)、todo(待办,完成即删入历史)、reward(奖励,消耗金币兑换)。

5.1 创建四类任务(实测)

curl -s -X POST http://10.89.71.10:3000/api/v4/tasks/user \
  -H "x-api-user: $U" -H "x-api-key: $T" -H 'Content-Type: application/json' \
  -d '{"text":"喝水打卡","type":"habit"}' | head -c 150
{"success":true,"data":{"_id":"fb97e550-b89d-4daa-b836-46a65e015b5c","text":"喝水打卡","type":"habit",...

其余三类同接口换 type:daily(可带 everyX/frequency 周期字段)、todo、reward(带 value 金币价)。实测创建记录:

habit  | fb97e550-b89d-4daa-b836-46a65e015b5c | 喝水打卡
daily  | 6433db21-f813-47e9-ac67-5e9c0e2cca53 | 早睡
todo   | b04e34e1-638e-4442-ba88-4d767894baed | 读完一章书
reward | 6a39de4f-38b9-444f-80dd-137f1f1141c0 | 看剧30分钟 (value: 10)

列表查询(注意 v4 返回扁平数组):

curl -s http://10.89.71.10:3000/api/v4/tasks/user -H "x-api-user: $U" -H "x-api-key: $T" | \
  python3 -c "
import json,sys
for t in json.load(sys.stdin)['data']:
    print(t['type'],'|',t['text'],'| value:',round(t.get('value',0),2),'| completed:',t.get('completed'))
"
habit | 喝水打卡 | value: 0.0 | completed: None
daily | 早睡 | value: 0 | completed: False | streak: 0
todo | Join Habitica (Check me off!) | value: 0 | completed: False
reward | 看剧30分钟 | value: 10

💡 说明:已完成的 todo 不出现在默认列表(实测:完成「读完一章书」后该任务从返回中消失),需要查历史时用完成态过滤参数或直接查库(第六节)。

5.2 Habit 加减分(实测数值反馈)

curl -s -X POST http://10.89.71.10:3000/api/v4/tasks/fb97e550-b89d-4daa-b836-46a65e015b5c/score/up \
  -H "x-api-user: $U" -H "x-api-key: $T"

响应 data 为更新后的 exp(实测 6:1 级角色 habit 加分得 6 经验)。随即查用户数值验证:

lvl 1 hp 50 xp 6 gp 1 mp 11

减分(坏习惯):

curl -s -X POST http://10.89.71.10:3000/api/v4/tasks/fb97e550-b89d-4daa-b836-46a65e015b5c/score/down \
  -H "x-api-user: $U" -H "x-api-key: $T"

实测 hp 50 → 49(坏习惯扣血)。

5.3 Todo 完成与 Reward 兑换(实测)

完成 todo(score/up 即勾选完成):

curl -s -X POST http://10.89.71.10:3000/api/v4/tasks/b04e34e1-638e-4442-ba88-4d767894baed/score/up \
  -H "x-api-user: $U" -H "x-api-key: $T"

实测数值变化:xp 6 → 12、gp 1 → 2(todo 给经验+金币且额度高于 habit)。兑换 reward 用 score/down(消费金币):

curl -s -X POST http://10.89.71.10:3000/api/v4/tasks/6a39de4f-38b9-444f-80dd-137f1f1141c0/score/down \
  -H "x-api-user: $U" -H "x-api-key: $T"
{"success":false,"error":"NotAuthorized","message":"Not Enough Gold"}

⚠️ 排障实录:金币不足时实测返回 401 Not Enough Gold(当时仅 2 金币,奖励标价 10)。这是业务校验而非故障——先完成足量 habit/todo 攒金币,或把 reward 的 value 调低(PUT /api/v4/tasks/:id 改值)后再兑换。

5.4 每日结算 cron(实测)

curl -s -X POST http://10.89.71.10:3000/api/v4/cron -H "x-api-user: $U" -H "x-api-key: $T" | head -c 150
{"success":true,"data":{},"notifications":[{"type":"ACHIEVEMENT","data":{"achievement":"completedTask","icon":"achievement-completedTask","message":"...

cron 结算成功并随响应下发成就通知(首次完成任务获得 completedTask 成就)。cron 的跨天结算规则(未完成 daily 扣血、Boss 伤害等)由 CRON_SAFE_MODE/CRON_SEMI_SAFE_MODE 控制,语义与源码位置见配置详解篇第九节。

六、MongoDB 运维:数据形态与备份恢复

6.1 数据形态巡检(mongosh)

用户文档核心字段(认证与数值统计):

mongosh --quiet --eval 'const u=db.getSiblingDB("habitica").users.findOne({"auth.local.username":"habadmin"},{_id:0,"auth.local.username":1,"auth.local.email":1,"stats.lvl":1,"stats.hp":1,"stats.gp":1}); printjson(u)'
{
  auth: {
    local: { email: 'admin@example.com', username: 'habadmin' }
  },
  stats: { hp: 49, gp: 2, lvl: 1 }
}

任务文档(tasks 集合,四类同集合以 type 区分):

mongosh --quiet --eval 'const t=db.getSiblingDB("habitica").tasks.findOne({type:"habit"},{_id:0,text:1,type:1,value:1,userId:1}); printjson(t)'
{
  type: 'habit',
  text: '喝水打卡',
  value: 4.255940168063077e-7,
  userId: '118ccfe6-2c4d-46be-9f9e-3b2d345d55d5'
}

value 是 habit 的动态难度值(连减趋近 0、连加回升),也是金币/经验结算的输入。任务通过 userId 关联用户。

6.2 备份恢复闭环(mongodump → drop → mongorestore 实测)

备份(副本集连接串与 config.json 的 NODE_DB_URI 一致):

mongodump --uri 'mongodb://localhost:27017/habitica?replicaSet=rs&directConnection=true' --out /tmp/dump1

输出节选(实测):

2026-10-28T08:00:45.843+0000	done dumping `habitica.webhooks` (0 documents)
2026-10-28T08:00:45.843+0000	done dumping `habitica.tags` (0 documents)
2026-10-28T08:00:45.843+0000	done dumping `habitica.chats` (2 documents)
du -sh /tmp/dump1/habitica
108K	/tmp/habitica 备份目录实测大小

(108K,含 users/tasks 等 9 个集合的 bson 与索引元数据。)演练完整恢复闭环——先记录基线、删库、再恢复、后验证:

mongosh --quiet --eval 'db.getSiblingDB("habitica").dropDatabase()'
{ ok: 1, dropped: 'habitica' }
mongosh --quiet --eval 'print(db.getSiblingDB("habitica").users.countDocuments({}))'
0
mongorestore --uri 'mongodb://localhost:27017/?replicaSet=rs&directConnection=true' /tmp/dump1

输出节选(实测):

2026-10-28T08:00:56.904+0000	9 document(s) restored successfully. 0 document(s) failed to restore.
mongosh --quiet --eval 'print("restored users:", db.getSiblingDB("habitica").users.countDocuments({}))'
restored users: 1

恢复后 API 侧端到端验证(原认证头直接可用,证明凭据与数据完整回归):

restore后 API: True habadmin

⚠️ 注意:mongorestore 的 URI 库名留空(restore 到 dump 内记录的原库名);备份计划建议每日 cron 执行 mongodump 并保留多份,恢复演练(drop → restore)务必先做一次完整备份。

七、Redis 运维:队列与键巡检

7.1 基本巡检

redis-cli ping
PONG
redis-cli info keyspace | head -4

(db0 的 keys 数量随运行时长增长,主要来自限流桶与会话数据。)

7.2 邮件队列(BullMQ)键族(实测)

触发一次密码重置后(POST /api/v4/user/reset-password,需 SESSION_SECRET_KEY 正确与 WORKER_REDIS_URL 已配,见配置详解篇 7.1/8.2 节),队列键族实测:

redis-cli --scan --pattern 'bull:emails:*' | sort
bull:emails:1
bull:emails:2
bull:emails:events
bull:emails:id
bull:emails:marker
bull:emails:meta
bull:emails:wait
redis-cli llen bull:emails:wait
1

wait 为待消费列表;单条任务本体是 hash(bull:emails:<id>),看任务类型与载荷:

redis-cli hget bull:emails:2 name
redis-cli --no-raw hget bull:emails:2 data | head -c 300
reset-password
{"emailType":"reset-password","to":[{"name":"habadmin","email":"admin@example.com",...}],"variables":[{"name":"BASE_URL","content":"http://10.89.71.10:3000"},{"name":"PASSWORD_RESET_LINK","content":"http://..."}]}

⚠️ 说明:自托管单机默认没有邮件 worker 消费该队列,任务会滞留(接口成功但邮件不发)。llen bull:emails:wait 即积压量监控点;积压属预期还是故障取决于是否部署了官方邮件 worker(配置详解篇第八节)。另有 bull:DeleteUsers:* 队列族承载账号删除任务。

八、参考链接