跳转到内容

输出格式

每个命令都支持 -o / --output 来控制输出格式。该标志在全局注册,因此读取、写入、删除以及其他所有子命令都会一致地遵循它。根据实际用途选择合适的格式:阅读或脚本编写。如需用于电子表格,请参阅 CSV 导出。

默认格式,针对人类阅读优化。

终端窗口
redmine issues list --project myproject
ID TRACKER STATUS PRIORITY SUBJECT
123 Bug Open High Fix login timeout
124 Feature Open Normal Add dark mode
兼容 jq

JSON 输出可与 jq 配合用于即席分析:

终端窗口
# IDs of all open bugs
redmine issues list --tracker Bug -o json | jq '.[].id'
# Count issues by status
redmine issues list --project myproject -o json \
| jq 'group_by(.status.name) | map({status: .[0].status.name, count: length})'

CLI 不再提供 csv 输出格式。请改用内置 --jq 的 @csv 从 JSON 输出生成 CSV,这样还可以自行选择列:

终端窗口
# ID and subject of every issue, one CSV row each
redmine issues list --project myproject -o json --jq '.[] | [.id, .subject] | @csv'
# With a header row, nested fields, and all pages
redmine issues list --project myproject --limit 0 -o json \
--jq '["ID", "Status", "Subject"], (.[] | [.id, .status.name, .subject]) | @csv'

@csv 会为字符串加引号并转义其中的双引号;数字原样输出,null 变为空字段。如需制表符分隔,请使用 @tsv。写入文件或管道时值不会被修改,因此以 =、+、- 或 @ 开头的单元格在电子表格应用中打开时可能被当作公式执行。直接输出到终端时,--jq 的字符串结果(包括 @csv 和 @tsv 行)中的控制字符会被中和:转义序列显示为可见文本(ESC 显示为 ^[),因此精心构造的主题无法操纵终端;JSON 结果则不受影响。

-o csv 会在发送任何请求之前报错,并提示改用 @csv。配置文件中的 output_format: csv 或 REDMINE_OUTPUT_FORMAT=csv 会回退为表格格式并打印一条警告;如果命令通过 -o 或 --jq 指定了格式,则使用该格式且不打印警告。csv 不区分大小写。

-o json 会在 stdout 上产生两种顶层结构:

  1. 原始资源:用于获取或返回数据的命令 (例如 issues list、issues get、project create 等)。输出内容就是 API 返回的资源对象,或者资源对象数组。

  2. 动作信封:用于那些没有自然响应体的变更类命令 (例如 issues close、issues delete、issues assign、wiki delete、memberships delete 等)。该信封结构稳定且精简:

    {
    "ok": true,
    "action": "deleted",
    "resource": "project",
    "id": "demo",
    "message": "Project \"demo\" deleted"
    }

    ok 表示该命令是否实际改变了状态。某些命令即使成功执行,但没有内容需要变更,也可能返回相同结构且 ok: false,并附带说明性的 message。

    action 的取值集合很小且刻意保持稳定:created、updated、deleted、closed、reopened、assigned、unassigned、commented、logged、user_added、user_removed、logged_in、logged_out、switched、installed、opened、uploaded、archived、unarchived、watched、unwatched、related、unrelated。

启用 -o json(或 --jq)后,如果命令执行失败,CLI 会将结构化错误信封以单行 JSON 写到 stderr(始终是 stderr 的最后一行),stdout 保持为空,并以非零状态码退出:

{"error":{"message":"Resource not found.","code":"not_found"}}

code 来自一组稳定且有限的值:not_found、auth_failed、forbidden、validation_failed、conflict、server_error、jq_invalid、jq_failed、status_not_applied、timeout、already_exists、unknown。校验错误和冲突错误还会包含 details 数组,其中列出 Redmine 返回的各项错误信息。当 CLI 在发送任何请求之前就拒绝某个参数时(例如项目标识符或 wiki 页面标题不是单个 URL 路径段,如 ../users/2),也会使用不带 details 的 validation_failed。timeout 表示连接服务器或等待其响应超时(参见英文文档 Timeouts and limits);already_exists 表示下载目标已存在且未指定 --clobber。jq_invalid 表示 --jq 表达式为空或格式错误,命令未执行;jq_failed 表示命令本身已成功(写操作已经发生,请勿重试),只是 --jq 表达式在处理其输出时失败;例外是 redmine api -i 收到失败响应(4xx/5xx)时,消息为 --jq failed on the error response: ...,此时请求本身已失败。status_not_applied 表示 Redmine 接受了工单更新,却静默保留了原状态(参见英文文档 Status changes are verified)。其 details 列出允许的状态;如果请求还包含其他变更,还会提示这些变更可能已经生效。

  • 机器可读输出(JSON、表格行)始终写入 stdout。
  • 面向人的信息(非 JSON 模式下的成功确认、警告、进度 spinner、更新检查提示)始终写入 stderr。
  • 错误始终写入 stderr:普通模式下为 Error: ... 文本,JSON 模式下为 JSON 错误信封。失败时 stdout 为空。
  • 例外:redmine api 遇到 4xx 或 5xx 响应时,会把响应(响应体,使用 -i 时还包括状态和响应头)打印到 stdout 并以退出码 1 退出;设置 --silent 时不输出任何内容,但同样以退出码 1 退出。只有在 JSON 模式且未使用 -i 或 --silent 时,失败才会作为错误信封写入 stderr。

这种分离是稳定的。脚本可以安全地把 stdout 重定向到文件,或者直接通过管道传给 jq,而不必担心状态提示混入输出。

在配置文件中设置默认格式:

~/.redmine-cli.yaml
output_format: table

-o 标志始终会覆盖单次命令的默认格式。