Redmine 7.0 常用 CLI 命令详解

Redmine 7.0.2 命令行运维全实测:rake -T 任务族全景清单、迁移状态与回滚、默认数据装载、插件迁移与卸载、催办邮件任务端到端闭环(含收信取证)、清理四件套、rails console/runner/dbconsole,附定时运维组合与三条排障实录。

RedmineRedmineRuby运维2026/10/27

Redmine 7.0 常用 CLI 命令详解

本文为 Redmine 命令行运维篇:以 Redmine 7.0.2 实测覆盖 rake 任务族全景清单(rake -T 逐条核对)、迁移状态与回滚、默认数据装载、插件迁移、催办邮件任务端到端闭环(含收信取证)、清理四件套、rails console 与 rails runner 等控制台入口,并给出定时运维组合与三条排障实录。部署环境见 《Redmine 7.0 Docker Compose 部署实战》,配置参数见 《Redmine 7.0 配置参数详解》。全部命令与输出为 2026-10-27 实测。

一、命令行工具族总览

1.1 四个入口

Redmine 的命令行能力全部构建在 Rails 工具链上,实际可用的入口有四个(均需在应用目录 /usr/src/redmine 下执行):

入口形态用途
bundle exec rake <任务>预定义任务迁移、种子数据、清理、催办、权限清单等运维任务
bundle exec rails runner '<Ruby>'单发脚本临时查询/数据修补,跑完即退
bundle exec rails console交互式 REPL复杂操作调试,全模型可用
bundle exec rails dbconsole数据库 CLI 直连跳过 Rails 直接进 SQL(有前置条件,见 §5.3)

所有需要加载应用环境的命令都要求两个环境前提:RAILS_ENV=production 与 SECRET_KEY_BASE。后者在容器部署里由编排变量 REDMINE_SECRET_KEY_BASE 注入服务进程、命令行会话需手动桥接(根因与现象见 B2 篇排障 8.2)。本文统一采用以下执行定式(实测姿势):

$ cd /usr/src/redmine
$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake <任务名>

💡 技术拓展:rake 与 rails 命令的关系 rake 是 Ruby 世界的构建工具(对标 Make),Rails 在其上挂载了大量运维任务;rails runner/console 则是 Rails 自己的执行入口。两者在 Redmine 7.0(Rails 8.1)下可互通——rake db:migrate 与 rails db:migrate 等价。老兵习惯用 rake 跑任务、rails 跑控制台;关键在于「任务是否存在要以 rake -T 实测为准」:Redmine 7.0 已移除部分旧教程中的任务名(如 redmine:plugins:assets、redmine:info,见 §7 排障实录),照搬旧文档是命令行排障的高发雷区。

1.2 版本与环境的先行确认

任何运维动作前先确认版本与环境(实测回显):

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rails runner 'puts Redmine::VERSION'
7.0.2.stable

二、rake 任务族全景(rake -T 实测清单)

rake -T 输出即 7.0.2 的全部可用任务。以下为按功能分组的整理(描述文字取自实测输出原文,参数已核对):

迁移与数据库结构(db: 族,Rails 标准):

任务说明
db:migrate执行迁移(选项 VERSION=x、VERBOSE=false)
db:migrate:status显示迁移状态清单
db:migrate:up / db:migrate:down按版本执行单个迁移的上/下行
db:migrate:redo回滚后重做(选项 STEP=n)
db:rollback回滚上一次迁移(STEP=n 指定步数)
db:prepare / db:setup / db:reset建库/建表+种子/重建
db:seed载入种子数据
db:version当前 schema 版本号
db:encrypt / db:decrypt加密/解密库内敏感字段(SCM/LDAP 密码、TOTP 密钥),见 C1 篇 §2.5
db:encryption:init生成 Active Record 加密密钥组

Redmine 业务任务(redmine: 族):

任务说明
redmine:load_default_data装载默认配置数据(追踪器/状态/角色/权限)
redmine:plugins / redmine:plugins:migrate插件迁移(两者等价,后者语义更明确)
redmine:plugins:test 及子任务运行插件测试套件(functionals/integration/system/ui/units)
redmine:attachments:prune清理上传后一天未关联的孤儿附件
redmine:attachments:move_to_subdirectories附件从根目录迁入子目录结构
redmine:attachments:update_digests重算附件 SHA256 摘要
redmine:tokens:prune清理过期令牌(会话/自动登录/API 临时令牌)
redmine:users:prune清理超期未激活的注册用户
redmine:watchers:prune清理失效的 watcher 关联
redmine:send_reminders发送临近截止 Issue 的催办邮件(默认 7 天窗口)
redmine:permissions列出全部权限及对应 controller/action
redmine:fetch_changesets从配置的代码仓库拉取变更集
redmine:email:read / receive_imap / receive_pop3邮件转 Issue:读 stdin/IMAP/POP3
redmine:migrate_from_mantis / redmine:migrate_from_trac从 Mantis/Trac 一键迁移

辅助(tmp:/time: 等):tmp:clear(清缓存与 socket)、tmp:create、time:zones(列出时区)。

这份清单的用法是「先查后跑」:任何老教程任务先在此表(或直接 rake -T)确认存在,再执行。

三、迁移类任务实测

3.1 迁移状态:db:migrate:status

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake db:migrate:status

database: redmine

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     001             Setup
   up     002             Issue move
   up     003             Issue add note
 ...
   up     20260319170822  Add index to users login
   up     20260320090000  Ensure default issue start date to creation date is stored in db
   up     20260520164915  Add private by default to trackers

(节选:首尾各三条,全表约两百条。)状态列全部 up 表示 schema 与迁移链一致——升级后必看项;若出现 down 行,说明有迁移未执行,db:migrate 补跑即可。

3.2 手动执行与回滚

升级插件/版本失败时常用三条(实测可用,参数语义见 §二 表格):

# 执行迁移(增量)
$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production bundle exec rake db:migrate

# 回滚最近 1 个迁移
$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production bundle exec rake db:rollback STEP=1

# 重做(回滚后再执行)
$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production bundle exec rake db:migrate:redo STEP=1

⚠️ 生产库回滚有数据风险:down 方法可能删表删列。执行前先做数据库备份(B2 篇第六章的 pg_dump 流程),并核对目标迁移的 down 实现。

四、Redmine 业务任务实测

4.1 默认数据装载:redmine:load_default_data

首次部署必跑(行为差异与坑位分析见 B2 篇 §3.2 与排障 8.1),实测回显:

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake redmine:load_default_data
Default configuration data loaded.

重复执行时任务检测到数据已存在会询问是否跳过;非交互场景(自动化脚本)预先设置 REDMINE_DEFAULT_LANGUAGE=zh 环境变量可免确认直接装载中文默认数据。

4.2 插件迁移:redmine:plugins:migrate

插件安装四步法的第③步(完整流程见 C1 篇 §6.3)。实测以 RedMica UI extension v0.6.0 为例——该插件无迁移脚本,任务静默成功:

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake redmine:plugins:migrate
$ echo $?
0

带迁移的插件会在此打印逐条迁移回执(与首次部署的迁移日志同构)。卸载插件的回滚用版本参数:

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake redmine:plugins:migrate VERSION=0

VERSION=0 把插件表结构回滚到零(删插件表),之后删除插件目录并重启。不回滚直接删目录会留下孤儿表。

4.3 催办邮件:redmine:send_reminders(端到端闭环)

任务按「7 天窗口 + 未关闭 + 已指派」筛选 Issue,向受派人有邮箱的记录发送催办。实测闭环分三步:

第一步:空跑不发信。演示库三条 Issue 均无截止日期,任务 exit=0 无输出、无邮件——符合筛选逻辑,此为基线。

第二步:构造目标。把 Issue #2 置为「明天截止 + 指派给 admin」(REST API PUT /issues/2.json,due_date=2026-10-28、assigned_to_id=1,均实测 204)。重跑任务,实测回显(节选 ActiveJob 投递日志):

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake redmine:send_reminders
I, [2026-10-27T10:37:31.693347 #147]  INFO -- : [ActiveJob] [Mailer::DeliveryJob]
 [0d9765aa-b160-473d-b905-9928eac5cfdb] Performing Mailer::DeliveryJob (Job ID:
 0d9765aa-b160-473d-b905-9928eac5cfdb) from Inline(mailers) ... with arguments:
 "Mailer", "reminder", "deliver_now", {args: [#<GlobalID:0x... @uri=#<URI::GID
 gid://redmine-app/User/1>>, [#<GlobalID:0x... @uri=#<URI::GID
 gid://redmine-app/Issue/2>>], 7]}
I, [2026-10-27T10:37:32.207530 #147]  INFO -- : [ActiveJob] Enqueued
 Mailer::DeliveryJob ... with arguments: "Mailer", "reminder", "deliver_now", ...

日志显示投递对象 User/1、内容 Issue/2、窗口 7 天。SMTP 侧收信取证(实测):

To: admin@dummy.invalid
Subject: 1 issue(s) due in the next 7 days

第三步:窗口语义。任务参数 days 可调窗口(如 14 天),无参数时默认 7 天(日志中的 7 即窗口值)。

此任务的定时运维组合见第六章。

4.4 清理四件套

四个清理任务实测全部静默成功(无可清理对象时零输出,exit=0):

$ for t in redmine:attachments:prune redmine:tokens:prune \
      redmine:users:prune redmine:watchers:prune; do
    SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production bundle exec rake $t
  done
$ echo $?
0

各自的清理对象与触发条件(依据任务描述与实现语义):

任务清理对象条件
attachments:prune上传后未挂到任何对象的临时附件超过 1 天
tokens:prune过期的会话/自动登录/API 令牌过期时间已到
users:prune注册后未激活的账号超过宽限期
watchers:prune对已无权查看的对象的 watcher 记录权限失效

四件套均设计为幂等、可反复执行,是 cron 定时运维的标准成员。attachments:prune 的对应面是 attachments:move_to_subdirectories(老版本附件目录结构升级用)与 attachments:update_digests(附件摘要算法迁移到 SHA256 用)。

4.5 权限清单:redmine:permissions

排权限矩阵时的速查任务(实测回显,节选前若干条):

$ SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
    bundle exec rake redmine:permissions
Permission Name - controller/action pairs
:add_documents - documents/new, documents/create, documents/add_attachment, attachments/upload
:add_issue_notes - issues/edit, issues/update, journals/new, attachments/upload
:add_issue_watchers - watchers/new, watchers/create, watchers/append, watchers/autocomplete_for_user, watchers/autocomplete_for_mention
:add_issues - issues/new, issues/create, attachments/upload
:close_project - projects/close, projects/reopen
:delete_issues - issues/destroy
...

左列是权限符号名(角色配置接口/脚本中使用的标识),右列是对应的控制器动作——做 API 对接或自定义角色审计时按此表对齐。

五、控制台与数据库直连

5.1 交互式控制台:rails console

全模型可用的 REPL,管道方式实测(非交互场景喂脚本):

$ echo 'puts "console版本: #{Redmine::VERSION}"' \
    | SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
      bundle exec rails console
console版本: 7.0.2.stable

典型用法:数据修补前先在 console 验证(Issue.where(...) 检查命中范围),确认后再落 update_all;两步都在 RAILS_ENV=production 下执行,务必先备份。

5.2 单发脚本:rails runner

不用进 REPL 的等价形态,本文全部验证均用它完成(如 §1.2 版本确认、C1 篇邮件装载检查)。runner 与 console 的选择原则:一次性动作用 runner,多步探查用 console。

5.3 数据库直连:rails dbconsole(实测受限)

dbconsole 设计为按 database.yml 直接拉起数据库 CLI(本环境即 psql),实测报错:

$ echo 'SELECT count(*) FROM projects;' \
    | SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production \
      bundle exec rails dbconsole
Couldn't find database client: psql. Check your $PATH and try again.

官方应用运行时不内置 psql/mysql 客户端,dbconsole 无法开箱即用。两条替代路径:在应用侧补装 postgresql-client 包后再用;或直接在数据库服务侧执行 SQL(B2 篇第六章备份实测采用的姿势,pg_dump/psql 均在数据库服务侧运行)。

六、定时运维组合

Redmine 无内置调度器,上述任务按业务节奏组合进 cron/systemd timer 即构成日常运维闭环(容器部署下在宿主机以定时任务驱动,任务清单与参数见前文各节):

# /etc/cron.d/redmine-maintenance(示例节奏,按团队规模调整)
# 每日 02:10 清理孤儿附件与过期令牌
10 2 * * * root cd /usr/src/redmine && SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production bundle exec rake redmine:attachments:prune redmine:tokens:prune
# 每个工作日 08:30 发送催办邮件
30 8 * * 1-5 root cd /usr/src/redmine && SECRET_KEY_BASE=$REDMINE_SECRET_KEY_BASE RAILS_ENV=production bundle exec rake redmine:send_reminders
# 每周日 03:00 数据库与附件备份(配合 B2 篇第六章流程)
0 3 * * 0 root /usr/local/bin/redmine-backup.sh

组合原则:清理类放低峰期、催办类放工作日上午、备份类独立时段且保留滚动窗口。邮件任务依赖第四章的 SMTP 配置;SECRET_KEY_BASE 在定时任务环境里同样必须显式提供。

七、排障实录

实录一:rake redmine:info 不存在。 想按记忆敲 rake redmine:info 查版本,实测报:

rake aborted!
Don't know how to build task 'redmine:info' (See the list of available tasks with `rake --tasks`)
Did you mean?  redmine:plugins

Redmine 7.0.2 无此任务。版本查询用 rails runner 'puts Redmine::VERSION'(实测输出 7.0.2.stable,§1.2)。教训:任务名一律以 rake -T 实测清单为准(§二),rake 的 Did you mean? 提示往往直接指出正确任务。

实录二:rake redmine:plugins:assets 在 7.0 已移除。 按老教程执行插件安装第四步报:

rake aborted!
Don't know how to build task 'redmine:plugins:assets' (See the list of available tasks with `rake --tasks`)
Did you mean?  redmine:plugins:test
               redmine:plugins:test:ui
               redmine:plugins:migrate

7.0 起插件静态资产由 Rails 资产管线处理,安装流程收缩为「放置 → bundle install → plugins:migrate → 重启」三步半(C1 篇 §6.3 实测全流程)。旧教程的 assets 步骤直接跳过。

实录三:send_reminders 跑了但没人收到邮件。 任务 exit=0 却无投递日志。逐层定位:① rake -T 确认任务存在且执行成功;② 核对筛选条件——催办只发给「7 天内截止、状态未关闭、且已指派(assigned_to)」的 Issue,实测演示库三条 Issue 既无 due_date 也无受派人,被任务正确跳过;③ 补齐 due_date + assigned_to_id 后任务输出 ActiveJob 投递日志、SMTP 侧收到 1 issue(s) due in the next 7 days(§4.3 闭环)。教训:这类「静默正确」的任务,排障从其筛选前置条件查起,而不是先怀疑配置。


小结:Redmine 7.0 的命令行运维核心是「一表两入口」——rake -T 实测任务清单(§二)加 runner/console 两个 Ruby 入口。迁移看 db:migrate:status,清理靠四件套,催办走 send_reminders 定时,插件安装/卸载用 plugins:migrate 与 VERSION=0。所有命令的前置(应用目录 + 两个环境变量)与执行定式见 §1.1,配置层的对应关系见 C1 篇。