OpenProject 常用 CLI 命令详解
OpenProject 17.9.0 CLI 命令详解:Docker 形态 rails runner 与 rake 任务族全实测(backup:database:create 备份、setting:get/available_envs、db:migrate:status、db:sessions 维护),一体化镜像 supervisord 进程构成,双形态命令对照与包安装 openproject 包装器溯源,含每日备份 SOP 与 5 个排障实录。
OpenProject 常用 CLI 命令详解
目标:把 OpenProject 17.9.0 的命令行操作一次讲全——Docker 形态下的
rails runner、rails console与bundle exec rake任务族(备份恢复、系统设置、数据库迁移、会话维护、环境变量清单),配合一体化镜像的进程构成与容器内执行方式;同时对照包安装(deb/RPM)形态的openproject包装器命令族。全部 Docker 形态命令均在 17.9.0 一体化镜像实测,包安装命令按官方运维文档溯源收录(本文环境为 Docker 形态,未实测,已明确标注)。
一、环境信息
- OpenProject:17.9.0(Community 标准版,官方一体化镜像,部署方法见 《OpenProject Docker Compose 部署实战》)
- 实测宿主机:Ubuntu 22.04(x86_64),Docker Engine 29.9.2
- 容器内运行时:Ruby(Rails 8.1,bundler 管理)、PostgreSQL 17(内置)、memcached、supervisord(进程管理)
- 演示管理账号:
admin/q1w2e3r4 - 实测时间:2026-10-27
二、前置条件
- 实例已按部署篇启动(容器名
openproject-17.9.0-main,应用工作目录/app); - 容器内命令统一前缀(后文简写为
[op]):
docker exec openproject-17.9.0-main bash -c "cd /app && <命令>"
- Rails 命令默认跑 production 环境(镜像内置环境已设定),无需额外
-e参数。
三、命令体系总览
3.1 双形态对照
OpenProject 两种安装形态的 CLI 入口完全不同,先对齐认知:
| 形态 | 入口 | 典型写法 | 本文状态 |
|---|---|---|---|
| Docker(AIO/slim) | Rails 命令直接可用 | docker exec <容器> bash -c "cd /app && bundle exec rake ..." | 全量实测 |
| 包安装(deb/RPM) | openproject 包装器 | sudo openproject configure、sudo openproject run <命令> | 溯源收录,未实测 |
⚠️ 注意:一体化镜像里没有
openproject包装器命令——实测command -v openproject返回空(not found in AIO image)。网上流传的openproject run ...写法只适用于包安装形态,在容器内照抄会报command not found。
包安装形态的命令族(官方运维文档各章节收录:配置 reconfiguring、备份 backing-up、恢复 restoring、升级 upgrading、进程控制 control,URL 见文末参考链接):
| 命令 | 用途 | 说明 |
|---|---|---|
sudo openproject configure | 首次配置/重配置 | 交互向导,重放种子变量(见配置篇 5.9) |
sudo openproject config:set KEY=value | 写配置 | 落盘 /etc/openproject/conf.d/,改后需 configure |
sudo openproject run <命令> | 以应用环境执行任意命令 | 如 openproject run bundle exec rake ... |
sudo openproject backup / restore | 备份/恢复 | 打包数据库+附件+配置 |
sudo openproject run upgrades / postupgrades | 升级与升级后处理 | 大版本升级链 |
sudo openproject doctor | 体检 | 官方运维文档收录的诊断命令,Docker 形态不可用(实测 AIO 无此命令) |
3.2 一体化镜像进程构成(进程控制的对象)
docker exec openproject-17.9.0-main ps aux 实测回显(节选):
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 39396 15412 ? Ss 09:45 0:00 /usr/bin/python3 /usr/bin/supervisord -c /etc/supervisor/supervisord.conf -e info
postgres 204 0.0 0.1 215312 24344 ? S 09:45 0:00 /usr/lib/postgresql/17/bin/postgres -D /var/openproject/pgdata -c config_file=...
root 205 0.0 0.0 2680 1716 ? S 09:45 0:00 /bin/sh /usr/sbin/apache2ctl -DFOREGROUND
app 206 0.3 2.6 1425588 540208 ? Sl 09:45 0:17 puma 8.0.2 (tcp://0.0.0.0:8080) [app]
app 207 0.0 0.0 4496 3104 ? S 09:45 0:00 /bin/bash -e ./docker/prod/worker
app 208 0.0 0.0 4496 3104 ? S 09:45 0:00 /bin/bash ./docker/prod/hocuspocus
app 210 0.0 0.0 496116 18144 ? Sl 09:45 0:01 /usr/bin/memcached
app 216 0.4 3.1 1989416 640844 ? Sl 09:45 0:22 /app/vendor/bundle/ruby/4.0.0/bin/good_job start
解读:1 号进程是 supervisord,其下托管 PostgreSQL 17、Apache 入口、Puma 应用(容器内 8080)、GoodJob 后台任务 worker、hocuspocus 协同服务与 memcached。日常运维对进程的控制即「控制容器」+「容器内看 supervisord」两层;入口脚本(实测 docker/prod/entrypoint.sh)支持 root 前缀透传与 supervisord 启动分支,通常无需手工干预。
3.3 rake 任务族速查(实测清单)
容器内 bundle exec rake --tasks 实测输出 171 行任务,与本篇相关的关键条目:
rake backup:database:create[path_to_backup] # Creates a database dump which can be used as a backup
rake backup:database:restore[path_to_backup] # Restores a database dump created by the :create task
rake backup:allow_now # Allows user-initiated backups right away, skipping the cooldown period...
rake setting:available_envs # List the supported environment variables to override settings
rake setting:get[key] # Allow to get a Setting: rake setting:get[key]
rake setting:set # Allow to set a Setting: rake setting:set[key1=value1,key2=value2]
rake setting:set_to_env # Allow to set a Setting read from an ENV var
rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
rake db:migrate:status # Display status of migrations
rake db:seed # Load the seed data from db/seeds.rb
rake db:sessions:trim # Trim old sessions from the table (default: > 30 days)
rake db:sessions:expire[days_ago] # Expire old sessions from the sessions table
rake db:sessions:clear # Clear the sessions table
rake docs:env_vars # Regenerate the documented list of supported environment variables
四、核心命令详解
4.1 rails runner:应用内脚本的第一入口
rails runner 在完整应用环境里执行任意 Ruby,是 Docker 形态下最常用的「瑞士军刀」。实测三例:
例 1:数据面统计(与部署篇创建的数据对应):
[op] bundle exec rails runner 'puts({users: User.count, projects: Project.count, work_packages: WorkPackage.count, types: Type.count}.inspect)'
# {users: 4, projects: 3, work_packages: 39, types: 7}
例 2:配置层实况探针(三层模型辨析见配置篇 3.1):
[op] bundle exec rails runner 'cfg = OpenProject::Configuration; puts({host_name: cfg.host_name, https: cfg.https, password_min_length: cfg.password_min_length, attachments_storage_path: cfg.attachments_storage_path, rails_cache_store: cfg.rails_cache_store}.inspect)'
# (输出节选)
# {host_name: "localhost:8142", https: false, password_min_length: 10,
# attachments_storage_path: #<Pathname:/var/openproject/assets/files>, rails_cache_store: :memcache}
例 3:系统设置层读取:
[op] bundle exec rails runner 'puts({min_length: Setting.password_min_length, active_rules: Setting.password_active_rules}.inspect)'
# {min_length: 8, active_rules: ["lowercase", "numeric"]}
与 rails console 的关系:console 是交互式会话(容器里需配合管道使用),runner 是一次性执行,脚本化运维首选 runner。
4.2 备份与恢复:backup:database:create / restore
数据库备份(实测):
[op] bundle exec rake backup:database:create
docker exec openproject-17.9.0-main ls -la /app/backup/
# total 860
# drwxr-xr-x 2 root root 4096 Oct 27 10:54 .
# drwxr-xr-x 1 root root 4096 Oct 27 10:54 ..
# -rw-r--r-- 1 root root 864987 Oct 27 10:54 openproject-production-db-20261027T105454_0000.backup
产物为 pg_dump 自定义格式(--format=custom --clean --no-owner),文件名含时间戳。附件不在该任务范围内——一体化镜像的附件直接打包挂载目录 /var/lib/openproject/assets(内容 files/ git/ svn/)即可。
恢复:任务存在(backup:database:restore[path_to_backup],见 3.3 清单),会把指定 .backup 灌回数据库;因会覆盖现有数据,本文未在含生产数据的实例上执行。恢复 SOP:先停写入(docker compose stop)、恢复、再启动;演练环境建议用新容器+空库验证。
UI 备份的限制位:应用内置「管理 → 备份与恢复」功能受 OPENPROJECT_BACKUP__ENABLED(默认 true)等变量控制,新建备份令牌有 24 小时冷却期(OPENPROJECT_BACKUP__INITIAL__WAITING__PERIOD 默认 86400 秒),rake backup:allow_now 可跳过冷却(运维兜底用)。
4.3 系统设置:setting:get / setting:set / available_envs
# 读单个设置(实测)
[op] bundle exec rake 'setting:get[app_title]'
# OpenProject
# 列出全部可用环境变量及默认值(实测 324 个,输出节选)
[op] bundle exec rake setting:available_envs
# OPENPROJECT_APP__TITLE (default="OpenProject") Application title
# OPENPROJECT_ATTACHMENT__MAX__SIZE (default=5120) Attachment max. size
# OPENPROJECT_BRUTE__FORCE__BLOCK__AFTER__FAILED__LOGINS (default=20) Number of login attempts per user before assuming brute force attack
rake 'setting:set[key1=value1,key2=value2]' 与 setting:set_to_env 可批量写设置(从环境变量或键值对)——等价于管理后台修改,直接改库内 Setting,重启不丢失。运行中的实例优先用管理后台(有校验与审计);批量初始化/迁移场景用 rake 更高效。
4.4 数据库迁移与种子
# 迁移状态(实测:17.9.0 全部 up)
[op] bundle exec rake db:migrate:status | tail -3
# up 20260909140000 Add value bounds to custom fields
# up 20260910120000 Create recurring meeting historic schedules
# up 20260917165643 Create jira versions
# 升级容器镜像后自动执行迁移;手工补跑:
[op] bundle exec rake db:migrate
# 种子重放(会重放 SEED_* 变量与基础数据,慎用于已定制实例)
[op] bundle exec rake db:seed
一体化镜像升级即「换 tag 重建」,首启自动跑迁移(部署篇第十一章);slim 分离式方案有专门的 upgrade 控制面容器(官方 compose 仓库)。包安装形态对应 sudo openproject run upgrades(溯源)。
4.5 会话与缓存维护
[op] bundle exec rake db:sessions:trim # 清理 30 天前的旧会话(默认阈值)
[op] bundle exec rake db:sessions:expire[7] # 过期 7 天前的会话
[op] bundle exec rake db:sessions:clear # 清空会话表(全体强制下线,慎重)
登录风暴/会话膨胀治理用;紧急踢全站下线用 clear。缓存清理通过重启容器或 memcached 侧操作(应用侧无独立 rake 清缓存任务,见 3.3 全量清单)。
五、生产场景 SOP
5.1 每日备份(宿主机 cron + 拷出容器)
#!/bin/bash
# /opt/openproject/backup.sh —— 数据库 + 附件双备份
set -e
TS=$(date +%Y%m%d)
mkdir -p /backup/db-$TS
# 1. 数据库备份(容器内任务 → 拷出到宿主机)
docker exec openproject-17.9.0-main bash -c "cd /app && bundle exec rake backup:database:create"
docker cp openproject-17.9.0-main:/app/backup/. /backup/db-$TS/
# 2. 附件打包(挂载卷直读)
tar -czf /backup/op-assets-$TS.tgz -C /var/lib/openproject assets
# 3. 清理容器内临时产物
docker exec openproject-17.9.0-main bash -c "rm -f /app/backup/*.backup"
要点:数据库产物落在容器 /app/backup/(非挂载卷),必须 docker cp 拷出,否则随容器重建丢失;附件直接 tar 宿主机挂载目录;两路备份再加异地同步才是完整方案。
5.2 配置排障三板斧(runner 探针)
# ① 配置层(环境变量/yml 生效值)
[op] bundle exec rails runner 'puts OpenProject::Configuration.to_h.slice("host_name", "https", "password_min_length").inspect'
# ② 设置层(数据库即时值)
[op] bundle exec rails runner 'puts Setting.host_name'
# ③ 环境变量全集核对(拼写检查)
[op] bundle exec rake setting:available_envs | grep HOST
典型用法见配置篇第四章「优先级辨析」与部署篇 4.4 的密码策略实证。
5.3 升级操作顺序(AIO 形态)
cd /opt/openproject
# 1. 改 docker-compose.yml 中 image tag(如 17.9.0 → 18.0.0,浮动 tag 则 pull 最新)
docker compose pull
# 2. 先备份(4.2 数据库任务 + 5.1 附件打包)
# 3. 重建(首启自动迁移)
docker compose up -d
# 4. 迁移核验
docker exec openproject-17.9.0-main bash -c "cd /app && bundle exec rake db:migrate:status | grep down"
grep down 无输出即迁移完整;有输出按官方升级文档处理。PostgreSQL 大版本升级另有官方迁移指南(镜像入口脚本实测会检测旧数据卷 PG 版本不匹配并给出告警与迁移文档链接,如 9.6 旧路径检测、PostgreSQL 17 迁移指南 https://www.openproject.org/docs/installation-and-operations/misc/migration-to-postgresql17/ )。
六、排障实录
E1:rake backup 报 Don't know how to build task
照社区帖子执行 bundle exec rake backup 失败,rake 提示 Don't know how to build task 'backup'(backup:create 同样不存在);正确任务名是 backup:database:create(rake --tasks 实测清单见 3.3)。rake backup:database:create 才是有效命令。
E2:就绪检查 /healthz 返回 404
容器内实测 curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/healthz 返回 404——17.9.0 AIO 镜像未暴露该端点。就绪探测改用 /login(200)或带 API 密钥请求 /api/v3/projects(200,见部署篇 4.5)。
E3:容器内没有 openproject 命令
command -v openproject 实测为空。包安装的包装器不在 Docker 镜像内,全部等价操作走 docker exec <容器> bash -c "cd /app && bundle exec ...";需要 root 权限的入口操作用镜像入口的 root 透传分支。
E4:rake setting:get 无输出疑云
rake 'setting:get[host_name]' 连续两次输出为空,一度怀疑任务失效。分离 stdout/stderr 重试(> /tmp/sg.out 2>/tmp/sg.err)确认任务正常:setting:get[app_title] 正常打印 OpenProject。原因:host_name 在 Setting 表的存储值可能为空(应用回退到配置层取值),任务如实打印空串。教训:Rails 任务日志走 stderr、数据走 stdout,管道前先分离流再判断。
E5:连接池自动扩容日志误当报错
每次执行 rake 任务日志首行出现 Increasing database pool size to 17 to match max threads(INFO 级)——这是应用按 RAILS_MAX_THREADS 自动扩池的正常行为,不是错误;脚本解析输出时注意过滤 INFO 行。
七、常见问题(FAQ)
Q1:runner 里改动数据要重启应用吗? 不需要。runner/console 与 Web 进程共用同一数据库,写操作即时生效;但涉及缓存/进程内状态的变更(如改 Setting 后个别缓存值)建议等待或重启容器,避免新旧值并存。
Q2:rake 任务跑一半断开会话会怎样?
docker exec 内进程随会话断开被终止。长任务(大库备份/迁移)用 docker exec -d(后台)或 docker compose exec -T 配合 nohup,并落盘日志。
Q3:怎么确认容器内 Rails 版本/运行环境?
[op] bundle exec rails runner 'puts Rails.version; puts Rails.env';包信息看 /app/Gemfile.lock。
Q4:包安装形态的 doctor 命令 Docker 里怎么替代?
没有一对一替代。等价体检思路:进程构成看 3.2 ps aux;迁移完整性看 db:migrate:status;配置三层核对看 5.2 探针;应用日志 docker compose logs 配合管理后台「管理 → 信息」页。
Q5:附件和数据库能分开备份吗? 能,而且推荐分开:数据库走 4.2 任务(pg_dump 格式、可单库恢复),附件走 5.1 目录打包(增量可用 rsync)。两者恢复时无需严格同时点,OpenProject 按附件路径寻址,容忍短暂不一致。
八、参考链接
- 官方运维总览(备份/恢复/升级/监控/进程控制子章节):https://www.openproject.org/docs/installation-and-operations/operation/
- 官方环境变量清单生成命令说明:https://www.openproject.org/docs/installation-and-operations/configuration/environment/
- 部署实测(容器编排/初始化/备份上下文):《OpenProject Docker Compose 部署实战》
- 配置体系(三层模型/命名规则/变量详解):《OpenProject 配置参数详解》
- 产品定位与选型:《OpenProject 介绍与选型指南》