Zammad 常用 CLI 命令详解
Zammad 7.2.2 三层命令面逐条实测:zammad 包装器全子命令树、systemd 服务管理、rake/rails 高频任务(索引重建/数据库/系统报告)与 rails r 实战脚本(密码重置/API Token),含排障实录。
Zammad 常用 CLI 命令详解
目标:系统整理 Ubuntu 22.04 包安装形态下 Zammad 7.2.2 的三层命令面——
zammad包装器、systemd 服务单元、Rails/Rake 任务——并把运维高频操作(服务管理、日志、搜索索引重建、数据库任务、管理员密码重置、API Token 创建等)逐条跑通「命令 → 实测回显 → 结果验证」。本文全部命令与回显均在 Zammad 7.2.2 实测环境(Ubuntu 22.04 包安装,安装过程见《Ubuntu 22.04 安装 Zammad 指南》)执行通过(2026-10-21)。
一、环境信息
本章给出本文所有命令的实测环境基线,读者在相近环境(Ubuntu 20.04/24.04 包安装)下可对号入座。
- 操作系统:Ubuntu 22.04 (jammy),x86_64
- Zammad 版本:7.2.2-1792508402.43c767a.ubuntu22(官方 packager.io stable 仓库安装,
zammad run rails r "puts Version.get"实测回显;上游最新稳定版 2026-10-21 复查仍为 7.2.2,7.3.0 尚处 alpha 预发布,见《Zammad 7.2.2 介绍与选型指南》) - Elasticsearch:9.5.5(搜索索引后端)
- PostgreSQL:14.24(业务数据库
zammad) - Redis:6.0.16(缓存与会话后端)
- Nginx:1.18.0(反向代理,Web 入口 80 端口)
- 安装路径:
/opt/zammad/,配置目录/etc/zammad/,日志目录/var/log/zammad/ - 运行用户:
zammad(uid 999) - 示例管理员账号:
admin/ 密码q1w2e3r4(邮箱admin@lab.local,首次向导创建,密码策略实测结论见《Ubuntu 22.04 安装 Zammad 指南》第六章)
💡 说明:本文主线命令均在 root(或
sudo)环境执行;zammad run系列命令无论由谁发起,实际都会降权到zammad用户执行(实测验证见 4.2 节)。
二、工具概览
本章先建立 Zammad 命令面的全景认知:包安装形态下,Zammad 的运维命令分布在三层,各自解决不同问题,混用是新手最常见的出错来源。
| 层次 | 命令入口 | 管什么 | 典型场景 |
|---|---|---|---|
| 包装器层 | /usr/bin/zammad | 应用级封装:以 zammad 用户跑 Rails/Ruby、看日志、设环境变量、重启服务 | 日常运维首选入口 |
| 服务管理层 | systemctl | 进程生命周期:状态、启停、开机自启、journal 日志 | 排障、确认服务健康 |
| 应用任务层 | zammad run rails/rake <task> | 数据与索引:迁移、种子、搜索索引重建、系统报告 | 升级、索引异常、巡检 |
三层的分工与依赖关系:
- 包装器层是官方推荐的应用入口(
/usr/bin/zammad由包安装生成,pkgr 工具链打包),它解决两个关键问题:一是降权——Zammad 不允许以 root 运行 Rails 进程,zammad run自动切换到zammad用户并加载/etc/default/zammad与/etc/zammad/conf.d/的环境变量;二是跨发行版一致——restart、scale等子命令在内部转译为对应发行版的 systemctl 调用,命令形态不随发行版变化。 - 服务管理层是 systemd 原生能力。包安装为 Zammad 注册了一组 systemd 单元(详见第五章),
zammad restart底层就是调 systemctl,但当你需要systemctl status、journalctl -u这类细粒度排障时,必须直接面对 systemctl。 - 应用任务层是 Ruby on Rails 框架的 rake 任务体系。Zammad 的数据面操作(数据库迁移、搜索索引、系统报告、翻译同步)全部以 rake 任务形式提供,且必须通过
zammad run包装执行——直接以 root 跑/opt/zammad/bin/rails会因运行用户与环境变量不对而失败。
💡 技术拓展:Rails 应用的任务入口有
rake与rails两套形态(rake db:migrate与rails db:migrate)。Rails 5 起官方推荐rails形态(它先加载 Rails 环境再分发任务,能感知应用上下文),rake形态仍兼容。本文实测两种形态在 Zammad 7.2.2 下等价可用(对比验证见 6.2 节),行文统一采用官方文档使用的zammad run rails <task>形态。
三、前置条件
本章列出具实测命令的前提检查项,全部满足后后续章节命令可直接照做。
- Zammad 已完成包安装并跑通初始化:本文命令基于「官方仓库在线安装 + 首次设置向导已完成」的实例(
zammad服务 active、Web 可访问)。从零安装见《Ubuntu 22.04 安装 Zammad 指南》。 - 以 root 或具备 sudo 权限的用户登录服务器:包装器与 systemctl 操作均需 root 权限(写
/etc/zammad/conf.d/、调 systemctl)。 - 确认服务在跑:
systemctl is-active zammad
实测回显:
active
- 确认应用版本(本文所有回显基于该版本):
zammad run rails r "puts Version.get"
实测回显:
7.2.2-1792508402.43c767a.ubuntu22
⚠️ 注意:若
zammad命令提示不存在,说明包装器未安装(通常只出现在手工解包场景),包安装(apt/yum)默认都会生成/usr/bin/zammad。
四、zammad 包装器命令详解
本章逐条实测 /usr/bin/zammad 包装器的全部子命令。先看总览,再按「执行入口 → 日志 → 配置 → 伸缩 → 重启」的运维动线逐个展开。
4.1 命令总览(usage 全文)
不带任何参数执行 zammad,包装器会打印完整用法说明并以退出码 64 结束——这份 usage 就是包装器的「官方命令清单」,逐字照录如下:
zammad
实测回显(完整):
Usage:
zammad run COMMAND [options]
zammad scale TYPE=NUM
zammad logs [--tail|-n NUMBER]
zammad config:get VAR
zammad config:set VAR=VALUE
zammad config:unset VAR
zammad configure
zammad reconfigure
zammad restart
Details:
zammad configure [-f FILE|-]
* If using an installer:
This command will launch the installer wizard.
You can pass the installer seed file as argument or on STDIN.
* Without installer:
This will execute the configure script at /opt/zammad/packaging/scripts/configure (if any).
A file containing environment variables can be given as argument or on STDIN (-f -), and will be saved in the /etc/zammad/conf.d folder.
zammad reconfigure
This command allows to reconfigure the application. Only useful if using an installer.
zammad restart [process]
This will restart the application (or the given process), in a distribution-independent manner.
对 usage 的逐项解读:
| 子命令 | 功能 | 本章小节 |
|---|---|---|
run COMMAND | 以 zammad 用户执行任意命令(Rails 控制台、rake 任务、单行脚本) | 4.2–4.5 |
scale TYPE=NUM | 调整某类进程的实例数 | 4.8 |
logs | 聚合查看应用日志 | 4.6 |
config:get/set/unset | 读写环境变量配置 | 4.7 |
configure | 安装器向导(或执行包的 configure 脚本) | 4.9 |
reconfigure | 重新配置(仅安装器场景有效) | 4.9 |
restart [process] | 重启全部或指定进程 | 4.9 |
⚠️ 注意:usage 里没有
status子命令。实测输入zammad status会得到与上面完全相同的 usage 输出并以退出码 64 退出——状态检查要走 systemctl(排障实录见 4.10 节,服务状态检查方法见 5.2 节)。
包装器启动时加载的环境文件是 /etc/default/zammad(定义应用路径与运行身份),内容实测如下:
cat /etc/default/zammad
实测回显(完整):
# Generated by pkgr
export APP_HOME="/opt/zammad"
export APP_NAME="zammad"
export APP_SAFE_NAME="zammad"
export APP_GROUP="zammad"
export APP_USER="zammad"
export APP_WIZARDS=""
export APP_RUNNER_TYPE="systemd"
export APP_RUNNER_CLI="systemctl"
export PORT=${PORT:=6000}
export HOME="/home/zammad"
逐项说明:APP_HOME(应用根目录 /opt/zammad)、APP_USER/APP_GROUP(降权目标 zammad:zammad)、APP_RUNNER_CLI(包装器转译 systemctl 的依据,确认本环境为 systemd 托管)、PORT(内部基线端口,默认 6000,与 Puma 实际监听的 3000 不同,后者由 systemd 单元模板单独指定)、HOME(zammad 用户家目录)。
4.2 zammad run:以应用身份执行任意命令
zammad run 是整个命令面中使用频率最高的入口:它把 COMMAND 放到「zammad 用户 + 应用环境变量 + production 环境」的完整上下文里执行。无论是跑 Rails 控制台、rake 任务还是一段 Ruby,都要经过它。
先验证它的降权行为——让 Rails 打印当前进程的 uid 与用户名:
zammad run rails r "require 'etc'; puts Process.uid; puts Etc.getpwuid(Process.uid).name"
实测回显:
999
zammad
uid 999 对应 zammad 用户,证明即使以 root 发起,zammad run 内部也完成了降权。这正是「Zammad 拒绝 root 运行」约束下的标准做法:永远通过 zammad run 执行应用侧命令,不要手工 su - zammad 再拼环境变量。
zammad run 最常用的三个通道(后续小节逐一展开):
| 通道 | 形态 | 用途 |
|---|---|---|
| 单行 Ruby | zammad run rails r "<Ruby 代码>" | 快速查询/修改数据,自动化脚本 |
| 交互控制台 | zammad run console | 交互式探索与调试(pry) |
| rake 任务 | zammad run rails <task> / zammad run rake <task> | 官方预置的运维任务 |
4.3 zammad run rails r:单行 Ruby 运维脚本
rails r(runner)把一段 Ruby 代码放进完整 Rails 环境执行,是免交互的数据操作通道。查一个配置项:
zammad run rails r "puts Setting.get('product_name')"
实测回显:
Quzuo Lab Helpdesk
(product_name 是本实例在首次向导中设置的组织名,该参数的完整实测见《Zammad 7.2.2 配置参数详解》第四章。)
统计类查询同样一行搞定:
zammad run rails r "puts User.count"
zammad run rails r "puts Ticket.count"
实测回显(两条分别执行):
3
1
更多实战脚本(管理员查询、密码重置、Token 创建)集中在第七章。
4.4 zammad run console:交互式控制台(pry)
需要多步探索、反复试错时用交互控制台。它加载 production 环境的完整应用上下文,交互 shell 是 pry:
zammad run console
实测进入后的头部回显(随后执行一条查询并退出):
Loading production environment (Rails 8.0.5.1)
[1] pry(main)> Setting.get('product_name')
[1] pry(main)> exit
逐行说明:Loading production environment (Rails 8.0.5.1) 表示已加载 production 环境(Zammad 7.2.2 基于 Rails 8.0.5.1);[1] pry(main)> 是 pry 的提示符,可直接调用任何模型与 Setting;exit 退出。
⚠️ 注意:在非交互管道里喂入代码时,pry 会对回显做 TTY 检测,命令结果的打印可能不显示(
tput相关告警同理)。非交互场景请改用 4.3 节的rails r,它在管道下输出行为完全确定。
4.5 zammad run rails routes 与 dbconsole
routes 打印全部 HTTP 路由表,用于确认某 API 端点是否存在及其控制器(API 全集见《Zammad 7.2.2 介绍与选型指南》对 API 能力的概述):
zammad run rails routes
实测回显(头部节选,实际输出数百行):
Prefix Verb URI Pattern Controller#Action
init GET /init(.:format) init#index
app GET /app(.:format) init#index
root GET / init#index
POST|PUT|DELETE|OPTIONS / errors#routing
api_v1_activity_stream GET /api/v1/activity_stream(.:format) activity_stream#show
api_v1_ai_agents GET /api/v1/ai_agents#index
api_v1_ai_agents_search GET|POST /api/v1/ai_agents/search(.:format) ai_agents#search
(输出节选——实测首部 8 行;实际表很宽,终端下可配合 grep api_v1_ticket 过滤目标端点。)
dbconsole(简写 db)直接打开业务数据库的命令行客户端(本环境为 PostgreSQL 的 psql),并按 config/database.yml 自动带上连接参数。执行一条 SQL 验证:
zammad run rails dbconsole
进入 psql 后输入 SQL 与退出命令:
SELECT count(*) FROM users;
\q
实测回显:
count
-------
3
(1 row)
与 4.3 节 User.count 的结果 3 一致,两条通道可互为验证。
4.6 zammad logs:日志聚合查看
zammad logs 一次性聚合展示三路日志:应用主日志 /var/log/zammad/production.log、搜索索引重建日志 /var/log/zammad/searchindex-rebuild.log、以及 systemd journal 中 zammad 服务的输出(Puma 启动信息等)。默认每个文件展示尾部若干行,--tail N(或 -n N)控制行数:
zammad logs --tail 3
实测回显(节选,三个日志源依次出现):
==> /var/log/zammad/production.log <==
I, [2026-10-21T06:43:04.887813#11034-91224] INFO -- : execute Channel.fetch_async (try_count 0)...
I, [2026-10-21T06:43:04.888195#11034-91224] INFO -- : ended Channel.fetch_async took: 0.001650461 seconds.
I, [2026-10-21T06:43:12.675907#11034-90680] INFO -- : ProcessScheduledJobs running...
==> /var/log/zammad/searchindex-rebuild.log <==
I, [2026-10-21T04:22:39.626531#8322-2944] INFO -- : Using Zammad's file store as Rails cache store.
There was an error trying to connect to Redis.
#<Redis::CannotConnectError: Failed to connect to localhost:6379 (ECONNREFUSED) (redis://localhost:6379)>
Oct 21 04:30:02 zammad[11030]: Puma starting in single mode...
Oct 21 04:30:02 zammad[11030]: * Puma version: 8.0.2 ("Into the Arena")
Oct 21 04:30:02 zammad[11030]: * Listening on http://127.0.0.1:3000
(输出节选——实测首尾;中间的 journal 段与 production.log 后续行省略。)
三点解读:
- 每段开头的
==> 文件路径 <==标明日志来源,tail -f式的连续查看可对单个文件直接tail -f /var/log/zammad/production.log。 - searchindex-rebuild.log 里出现 Redis 连接失败属历史残留:那是本实例早期(Redis 未就绪时)一次重建尝试的记录,时间戳 04:22 早于当前会话;当前 Redis 已正常(production.log 中任务调度持续输出即可佐证)。读到旧报错先看时间戳,不要被历史日志误导——这是日志聚合命令最典型的误读场景。
- journal 段显示 Puma 监听
127.0.0.1:3000,对外 80 端口由 Nginx 反代(架构见《Zammad 7.2.2 介绍与选型指南》)。
4.7 zammad config:get / config:set / config:unset:环境变量配置
这一组子命令管理的是进程环境变量(如 Ruby GC 参数、RAILS_LOG_TO_STDOUT),落盘位置为 /etc/zammad/conf.d/ 目录——注意它与数据库里的业务配置(Setting 体系)是两套体系:环境变量影响进程行为,Setting 影响业务功能(后者见《Zammad 7.2.2 配置参数详解》)。
先读一个内置变量:
zammad config:get PORT
实测回显:
6000
写入一个测试变量并查看落盘文件:
zammad config:set TEST_CLI_DEMO=hello
cat /etc/zammad/conf.d/other
实测回显(config:set 本身无输出;other 文件内容如下):
export MALLOC_ARENA_MAX="2"
export RUBY_GC_MALLOC_LIMIT="1077216"
export RUBY_GC_MALLOC_LIMIT_MAX="2177216"
export RUBY_GC_OLDMALLOC_LIMIT="2177216"
export RUBY_GC_OLDMALLOC_LIMIT_MAX="3000100"
export RAILS_LOG_TO_STDOUT=""
export TEST_CLI_DEMO="hello"
逐项解读:文件里前 6 行是包安装预置的 Ruby 内存分配器(glibc malloc arena)与 GC 调优参数——这是 Zammad 官方为 Ruby 进程做的性能默认值,非特殊性能问题不要动;最后一行 export TEST_CLI_DEMO="hello" 就是刚才 config:set 追加的。读回验证:
zammad config:get TEST_CLI_DEMO
实测回显:
hello
删除测试变量并确认:
zammad config:unset TEST_CLI_DEMO
zammad config:get TEST_CLI_DEMO
实测回显(unset 无输出;get 一个不存在的变量无输出且退出码为 1):
(无输出,退出码 1)
⚠️ 注意:
config:set修改的是环境变量文件,已运行进程不会自动重载,改完需要zammad restart才对新启动的进程生效。
4.8 zammad scale:进程实例伸缩
scale 调整某类进程的 systemd 实例数(基于 /usr/share/zammad/scaling/systemd/ 下的单元模板实例化)。先试一个幂等操作——把 web 进程设为 1 实例(当前就是 1):
zammad scale web=1
实测回显:
Nothing to do.
Nothing to do. 说明目标状态与当前一致,无需变更。scale 不带参数时静默退出(退出码 0,无输出)。
可伸缩的进程类型就是第五章 systemd 单元清单中的五类:web(HTTP 服务)、websocket(长连接推送)、worker(后台任务调度)、rake/console(按需拉起的临时实例类型)。小规模部署保持默认 1 实例即可;当单实例 CPU 持续打满时,可 zammad scale web=2 横向加实例(每个实例是一个独立 systemd 单元 zammad-web-1、zammad-web-2,以此类推)。
4.9 zammad restart / configure / reconfigure
restart 重启应用进程组,可全量重启,也可只重启指定进程(web、websocket、worker 之一):
zammad restart web
systemctl is-active zammad-web
实测回显(restart 静默完成,退出码 0;验证命令输出):
active
全量重启同样静默:
zammad restart
实测回显:无输出,退出码 0。重启后用 systemctl is-active zammad 验证回到 active(实测通过)。
⚠️ 注意:
restart执行期间(通常数秒到十几秒)Web 界面会短暂不可用,脚本化重启建议在restart之后轮询systemctl is-active直到恢复再继续。
configure 与 reconfigure 属于安装器(Linux 一键安装脚本)场景的命令:有安装器时 configure 启动配置向导(可从文件或标准输入传入种子变量),无安装器时它转而执行 /opt/zammad/packaging/scripts/configure(若存在)。本环境是 apt 包安装、无安装器且包内无 configure 脚本,实测两条命令均静默成功(无输出,退出码 0)——包安装用户无需关心这两个命令。
4.10 排障实录:zammad status 不是有效子命令
排查服务状态时,直觉会敲 zammad status(很多同类工具确实有该子命令),但 Zammad 包装器没有这个子命令:
zammad status
实测回显(完整 usage,同 4.1 节):
Usage:
zammad run COMMAND [options]
zammad scale TYPE=NUM
zammad logs [--tail|-n NUMBER]
zammad config:get VAR
zammad config:set VAR=VALUE
zammad config:unset VAR
zammad configure
zammad reconfigure
zammad restart
...
退出码实测为 64(usage 的固定退出码)。
定位过程:从 4.1 节 usage 全文可见子命令清单里没有 status;包装器脚本头部(/usr/bin/zammad 由 pkgr 生成)确认 APP_RUNNER_TYPE="systemd",状态查询归 systemctl 管。
解决方案:状态检查一律用 systemctl(完整用法见第五章):
systemctl is-active zammad
实测回显:
active
五、systemd 服务管理
包装器只覆盖「重启」这一类生命周期操作;状态细查、单服务启停、开机自启、journal 日志都要直接面对 systemd。本章给出 Zammad 包注册的完整单元清单与高频 systemctl 操作。
5.1 服务单元清单与架构
systemctl list-units 'zammad*' --no-pager --no-legend
实测回显(完整):
zammad-web-1.service loaded active running zammad-web-1.service
zammad-web.service loaded active running zammad-web.service
zammad-websocket-1.service loaded active running zammad-websocket.service
zammad-websocket.service loaded active running zammad-websocket.service
zammad-worker-1.service loaded active running zammad-worker-1.service
zammad-worker.service loaded active running zammad-worker.service
zammad.service loaded active running zammad.service
单元命名与架构解读:
| 单元 | 角色 |
|---|---|
zammad.service | 汇总单元(不含进程),聚合下面三组,systemctl is-active zammad 查的是它 |
zammad-web.service + zammad-web-1.service | HTTP 服务(Puma,监听 127.0.0.1:3000);-1 是第 1 实例,scale web=N 会增减 -N 实例 |
zammad-websocket.service + zammad-websocket-1.service | WebSocket 长连接服务(会话推送) |
zammad-worker.service + zammad-worker-1.service | 后台任务调度器(邮件收取、定时任务、通知发送) |
💡 技术拓展:这种「基础单元 +
-N实例单元」的组合是 systemd 模板单元思想的手工应用(同族方案还有@模板单元如zammad-web@1.service,以及 socket 激活)。pkgr 选择显式-N命名是为了让zammad scale能用确定的单元名直接 start/stop 对应实例。对本运维而言只需记住:实例数交给zammad scale管,单元本身不要手工增删。
依赖组件 PostgreSQL、Redis、Elasticsearch、Nginx 各自独立单元(postgresql、redis-server、elasticsearch、nginx),不在 zammad* 命名空间内,全链路巡检时要一并检查。
5.2 状态检查与进程验证
三个状态命令的分工与实测回显:
systemctl is-active zammad
实测回显:
active
(单值结论,适合脚本判断;可能的取值还有 inactive、failed。)
systemctl status zammad-web
实测回显(头部节选):
● zammad-web.service - Zammad web
Loaded: loaded (/etc/systemd/system/zammad-web.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2026-10-21 12:29:57 CST; 2h 30min ago
Main PID: 11030 (puma)
Tasks: 9 (limit: 4650)
Memory: 250.0M
CPU: 33.655s
CGroup: /system.slice/zammad-web.service
└─11030 puma 8.0.2 (tcp://127.0.0.1:3000) [Zammad]
(输出节选——实测首部;进程列表段省略。)可以看到 web 服务的二进制是 Puma 8.0.2、监听 tcp://127.0.0.1:3000、开机自启已启用(enabled)。
全链路健康验证(Web 入口可达性):
curl -sI http://127.0.0.1/ | head -1
实测回显:
HTTP/1.1 200 OK
5.3 单服务重启与日志
改配置后往往只需重启单个服务而非全量 zammad restart(例如只动了 Nginx 配置就只 reload Nginx):
systemctl restart zammad-web
systemctl is-active zammad-web
实测回显:
active
journal 方式查看单个服务的实时日志(与 zammad logs 相比,journal 能看到进程启动期的标准输出,如 Puma 横幅):
journalctl -u zammad-web --since "10 minutes ago" --no-pager
实测回显(节选):
Oct 21 04:30:02 zammad[11030]: => Run `bin/rails server --help` for more startup options
Oct 21 04:30:02 zammad[11030]: Puma starting in single mode...
Oct 21 04:30:02 zammad[11030]: * Puma version: 8.0.2 ("Into the Arena")
Oct 21 04:30:02 zammad[11030]: * Ruby version: ruby 3.4.9 (2026-03-11 revision 76cca827ab) +YJIT +PRISM [x86_64-linux]
Oct 21 04:30:02 zammad[11030]: * Min threads: 5
Oct 21 04:30:02 zammad[11030]: * Max threads: 30
Oct 21 04:30:02 zammad[11030]: * Environment: production
Oct 21 04:30:02 zammad[11030]: * PID: 11030
Oct 21 04:30:02 zammad[11030]: * Listening on http://127.0.0.1:3000
(输出节选——实测首部;启动完成后的运行期日志省略。)从回显可直接读到运行时关键值:Ruby 3.4.9(启用 YJIT)、Puma 线程池 5–30、production 环境。
六、常用 rake / rails 任务详解
数据面运维(迁移、索引、报告)以 rake 任务提供,全部经 zammad run 执行。本章按「清单 → 数据库 → 搜索索引 → 系统报告 → 其他」展开,每个任务给出实测回显。
6.1 查看任务清单(rails -T)
rails -T 列出全部可用任务及一句话描述,是任务名的权威来源:
zammad run rails -T
实测回显(zammad 命名空间节选,完整清单 100+ 行):
bin/rails zammad:bootstrap:init # Initializes a Zammad instance for the first time
bin/rails zammad:bootstrap:reset # Resets a Zammad instance and reinitializes it
bin/rails zammad:db:init # Initializes (creates, migrates and seeds) the DB
bin/rails zammad:db:max_connections # Calculates recommended max_connections value for PostgreSQL
bin/rails zammad:db:rebuild # Clears the Cache and reloads the Settings
bin/rails zammad:db:reset # Truncates and seeds the database, clears the cache and reloads the settings
bin/rails zammad:searchindex:configured # Is the search index backend configured?
bin/rails zammad:searchindex:create # Create all search indexes
bin/rails zammad:searchindex:rebuild[worker] # Full re-creation of all search indexes and re-indexing of all data
bin/rails zammad:searchindex:refresh # Refresh all search indexes
bin/rails zammad:store:move_files # Move files/attachments from one store provider to another
bin/rails zammad:store:verify_files # Verify files/attachments checksums
bin/rails zammad:system_report # Fetches the system report
bin/rails zammad:translations:sync # Synchronize latest translations from i18n/*.po to the database
(输出节选——实测经 grep "zammad:" 过滤后的首尾部;zammad:package:*、zammad:email_parser:*、zammad:ci:* 等子族从略,读者以本机 rails -T 输出为准。)
关键差异解读:zammad:db:* 族动数据库(高危),zammad:searchindex:* 族动 Elasticsearch(可安全重跑),zammad:bootstrap:reset 会清空全部数据重新初始化(仅测试环境用)。本章后续小节只展开运维高频且低危的任务。
6.2 数据库任务
数据库任务覆盖版本确认与容量规划。先看当前库的 schema 版本号(判断升级是否完成迁移的依据):
zammad run rails db:version
实测回显:
database: zammad
Current version: 20261009130000
迁移状态明细(每个迁移文件是否已应用):
zammad run rails db:migrate:status
实测回显(首尾节选,完整输出约 300 行):
database: zammad
Status Migration ID Migration Name
--------------------------------------------------
up 20120101000001 Create base
up 20120101000010 Create ticket
up 20150979000001 Update timestamps
...
up 20261006120000 Add alternative fqdn setting
up 20261009130000 Alternative fqdn frontend
解读:全部迁移 up 且末行 Migration ID 与 6.2 第一个任务的 Current version 一致(20261009130000),说明 schema 完整无欠账;升级后若出现 down 状态迁移即欠迁移。
zammad:db:max_connections 按实际进程数推荐 PostgreSQL 的 max_connections 值。注意它是交互式任务,会依次询问三类进程数量(Web 实例数 → cron 并发数 → 其他 rails 进程并发数),直接回车取默认值即可。非交互管道下会因读不到 stdin 报错(排障实录见 9.2 节),这里用管道预喂三个默认值(1、0、0):
printf "1\n0\n0\n" | zammad run rails zammad:db:max_connections
实测回显:
Connections pool size: 50
How many web server instances/pods do you have? (DEFAULT=1) WEB_CONCURRENCY=0
ZAMMAD_PROCESS_SESSIONS_JOBS_WORKERS=0
ZAMMAD_PROCESS_SCHEDULED_JOBS_WORKERS=0
ZAMMAD_MANAGE_SESSIONS_JOBS_WORKERS=0
ZAMMAD_PROCESS_DELAYED_JOBS_WORKERS=0
ZAMMAD_PROCESS_DELAYED_AI_JOBS_WORKERS=0
ZAMMAD_PROCESS_DELAYED_COMMUNICATION_INBOUND_JOBS_WORKERS=0
Do you have any cronjobs running Zammad, how many run concurrently? (DEFAULT=0) Do you have any other processes running Zammad via rails command, how many run concurrently? (DEFAULT=0) Total Zammad processes: 3
Recommended PostgreSQL max_connections value: 150
解读:任务先报出每个 Zammad 进程的连接池大小(50,含 6 类 worker 池变量),按「Web 实例 1 + cron 0 + 其他 0」汇总为 3 个进程,最终给出建议值 150。该值与官方安装文档要求 PostgreSQL max_connections 至少 150 吻合,扩容实例后应重跑本任务重新校准(多实例部署的容量规划见《Zammad 7.2.2 介绍与选型指南》硬件参考节)。
补充验证:rake 与 rails 两种入口等价(对照 2 章末尾的技术拓展说明):
zammad run rake db:version
实测回显:
database: zammad
Current version: 20261009130000
与 zammad run rails db:version 输出完全一致。
6.3 搜索索引任务
搜索索引(Elasticsearch)是 Zammad 全文搜索的底座,索引异常(改配置、ES 重装、数据不同步)后的标准动作就是本节任务。先确认索引后端是否已配置:
zammad run rails zammad:searchindex:configured
实测回显:无输出,退出码 0 表示已配置(未配置时退出码非 0)——这个任务用退出码而非文本回答问题,脚本判断应写 zammad run rails zammad:searchindex:configured && echo "configured" 之类的形式。
轻量刷新(把数据库增量同步进索引,秒级):
zammad run rails zammad:searchindex:refresh
实测回显:
Refreshing all indexes... done.
全量重建(删掉全部索引重新创建并回灌数据,数据量大时耗时数分钟到数小时):
zammad run rails zammad:searchindex:rebuild
实测回显(本实例数据量小,全程 6.6 秒;头尾节选):
Dropping indexes... done.
Deleting pipeline... done.
Creating indexes... done.
Creating pipeline... done.
Reloading data...
- AI::Agent...
done in 0 seconds.
- AI::ProviderConnection...
done in 0 seconds.
- AI::TextTool...
done in 0 seconds.
- AuditLog...
done in 0 seconds.
- Chat::Session...
done in 0 seconds.
- CoreWorkflow...
done in 0 seconds.
- Cti::Log...
done in 0 seconds.
- Group...
done in 0 seconds.
...
- Ticket...
done in 0 seconds.
- Trigger...
done in 0 seconds.
- User...
done in 0 seconds.
- Webhook...
done in 0 seconds.
解读:流程为「删索引 → 删管道 → 建索引 → 建管道 → 逐模型回灌」,回灌清单覆盖全部可索引模型(Ticket、User、Organization 等)。验证重建结果——查询一次工单搜索(经 API,确认索引可用):
zammad run rails r "puts Ticket.search(query: '*', limit: 5).count"
实测回显:
1
与 4.3 节 Ticket.count(1 条)一致,索引重建后搜索链路完整可用。
查看每个索引模型的 ES 层配置(字段数上限、分页窗口、分析器):
zammad run rails zammad:searchindex:settings:show
实测回显(节选):
AI::Agent => {"index.mapping.total_fields.limit" => 2000, "index.max_result_window" => 1000000, "analysis.analyzer.default.type" => "custom", "analysis.analyzer.default.tokenizer" => "standard", "analysis.analyzer.default.filter" => ["lowercase", "asciifolding"]}
AuditLog => {"index.mapping.total_fields.limit" => 2000, "index.max_result_window" => 1000000, "analysis.analyzer.default.type" => "custom", "analysis.analyzer.default.tokenizer" => "standard", "analysis.analyzer.default.filter" => ["lowercase", "asciifolding"]}
Ticket => {"index.mapping.total_fields.limit" => 2000, "index.max_result_window" => 1000000, "analysis.analyzer.default.type" => "custom", "analysis.analyzer.default.tokenizer" => "standard", "analysis.analyzer.default.filter" => ["lowercase", "asciifolding"]}
(输出节选——实测首尾部;每行一个模型,中间模型省略。)所有模型默认同构:字段上限 2000、单页最大 1,000,000、standard 分词 + 小写 + ASCII 折叠过滤。中文分词等定制需求通过 settings:set 调整后重建索引生效。
6.4 系统报告任务
zammad:system_report:plugins 列出报告的插件清单(即报告会覆盖的信息面):
zammad run rails zammad:system_report:plugins
实测回显(完整):
["Addons","Channel","Counts","LastCreatedAt","Ticket","User","Environment","FailedEmails","Hardware","MacAddress","Os","PostgreSql","RailsRoot","Redis","Ruby","SearchIndex","Setting","Version"]
zammad:system_report 生成完整报告 JSON(版本、实体计数、环境、硬件等 18 类信息),用于提交技术支持或自检:
zammad run rails zammad:system_report
实测回显(JSON 头部节选,完整输出 40KB+):
{"system_report":{"Addons":[],"Channel":{"Email::Notification":1},"Entities":{"Counts":{"ActiveJobLock":0,"ActivityStream":0,"AI::Agent":0,"AI::Analytics::Run":0,"AI::Analytics::Usage":0,"AI::FeatureProvider":0,"AI::ProviderConnection":0,"AI::StoredResult":0,"AI::TextTool":5,"AuditLog":0,"Authorization":0,"Avatar":2,"Calendar":1,"Channel":2,"Chat::Agent":0,"Chat::Message":0,"Chat::Session":0,"Chat":1,"Checklist::Item":0,"Checklist":0,"ChecklistTemplate::Item":0,"ChecklistTemplate":0,"CoreWorkflow":10,"Cti::CallerId":0,"Cti::Log":0,"DataPrivacyTask":0,"EmailAddress":0,"ExternalCredential":0,"ExternalSync":0,"FailedEmail":0,"Group":1,"History::Attribute":3,"History::Object":5,"History::Type":3,"History":10,"HttpLog":0,"ImportJob":0,"Job":0,...
(输出节选——实测首部;Entities.Counts 后续、Environment、Hardware 等段省略。)解读:Entities.Counts 给出每类实体的数量(如本实例 Setting: 304、Scheduler: 30、Role: 3),巡检时可与业务预期对照;报告末段的 Version 键即应用版本,与 3 节 Version.get 结果一致。
6.5 附件校验与翻译同步
附件存储完整性校验(比对每个附件的校验和,排查存储损坏):
zammad run rails zammad:store:verify_files
实测回显:
Verifying files checksums...
Done.
翻译同步(把打包内置的 i18n 翻译文件刷新进数据库,升级后界面文案未更新时使用):
zammad run rails zammad:translations:sync
实测回显:
Synchronizing the latest translations from i18n/*.po to the database...
done.
七、rails r 实战脚本集
本章沉淀日常运维中最高频的 rails r 一行脚本,全部实测。脚本约定:输出一律 puts,字符串统一用 %q(...) 写字面量避免 shell 引号纠缠——但要注意 %q(...) 内部不做 #{} 插值(实测踩坑见 9.3 节),需要插值时改用双引号并转义。
7.1 系统信息查询
应用版本(排障时先报版本):
zammad run rails r "puts Version.get"
实测回显:
7.2.2-1792508402.43c767a.ubuntu22
读任意业务配置(对照 Setting 名单见《Zammad 7.2.2 配置参数详解》参数速查表):
zammad run rails r "puts Setting.get('fqdn')"
实测回显:
zammad.lab.local
7.2 用户与账号运维
查管理员账号及角色(账号被误改角色后快速核对):
zammad run rails r "u = User.find_by(email: %q(admin@lab.local)); puts [u.id, u.login, u.roles.map(&:name).join(%q(,))].join(%q( | ))"
实测回显:
5 | admin | Admin,Agent
解读:该账号 id=5、登录名 admin、同时具备 Admin,Agent 双角色(首次向导创建的账号即此配置)。
重置管理员密码(忘记密码或被锁时的兜底手段;Zammad 的密码策略对弱口令有复杂度校验,q1w2e3r4 为实测可用的合规值):
zammad run rails r "u = User.find_by(email: %q(admin@lab.local)); u.update!(password: %q(q1w2e3r4)); puts \"password updated for #{u.login}\""
实测回显:
password updated for admin
验证:用新密码登录 Web 界面成功(实测通过);update! 在校验失败(如密码过短)时会直接抛异常中止并打印原因,不会静默半改。
创建 API Token(给第三方集成签发凭据,API 调用方式见官方 API 文档):
zammad run rails r "t = Token.create!(user_id: User.find_by(email: %q(admin@lab.local)).id, name: %q(cli-demo), action: %q(api)); puts t.token"
实测回显:
PKvz069YqVNrfyMgz2Oo0_1UyD02xfP7LNDH30zA-nZP2bQ2qVX7cNUi_MXcuWhb
验证:拿该 Token 调一次 API(HTTP 头 Authorization: Token token=<值>)返回 200(实测通过)。演示 Token 用完立即删除:
zammad run rails r "t = Token.find_by(name: %q(cli-demo)); t.destroy!; puts %q(demo token removed)"
实测回显:
demo token removed
7.3 数据统计
巡检用的计数脚本(用户/工单/组织三件套):
zammad run rails r "puts User.count"
zammad run rails r "puts Ticket.count"
zammad run rails r "puts Organization.count"
实测回显(三条分别执行):
3
1
1
数字与 6.4 节系统报告 Entities.Counts 的对应值一致,两条通道可互为对账。
八、注意事项
综合全部实测,把容易踩坑的约定集中列出:
- 一切应用侧命令走
zammad run:它会补齐 zammad 用户身份、production 环境与/etc/default/zammad+/etc/zammad/conf.d/的环境变量。直接以 root 跑/opt/zammad/bin/rails会因用户与环境不对而行为异常。 zammad status不存在:状态检查用systemctl is-active zammad(4.10 节排障实录)。- 两套配置体系不要混淆:
zammad config:*管进程环境变量(落/etc/zammad/conf.d/),Setting.get/set管业务配置(落数据库);改环境变量要zammad restart才生效,业务配置多数即时生效。 - 交互式 rake 任务在脚本里会卡死或报错:
zammad:db:max_connections等任务依赖 stdin 问答,自动化场景用printf "1\n0\n0\n" |预喂答案(9.2 节)。 %q(...)不插值:rails r脚本里puts %q(#{u.login})会原样输出#{u.login};要插值用双引号形式puts "value: #{u.login}"并注意 shell 层的引号转义(9.3 节)。- 搜索索引任务按轻重选择:增量同步用
refresh(秒级),动过 ES 配置或索引损坏才rebuild(全量重建);rebuild会先删后建,期间搜索结果不全。 zammad:bootstrap:reset、zammad:db:reset、zammad:db:truncate是销毁级任务:清空数据重新初始化,生产环境禁用。- 日志三路分流:应用日志在
/var/log/zammad/production.log,索引重建在searchindex-rebuild.log,进程启动输出在 journal——zammad logs一次聚合三路但每路只给尾部,深查单路时直接对源文件或journalctl -u操作。 - Token 用完即删:7.2 节演示了创建与销毁闭环;线上长期 Token 应绑定专用集成账号而非管理员,并定期轮换。
九、常见问题(FAQ)
Q1:执行 zammad status 打出一堆 Usage 还退出异常,是不是装坏了?
不是。包装器本来就没有 status 子命令,任何未识别的子命令都会打印完整 usage 并以退出码 64 退出(4.1 节)。状态检查用 systemctl is-active zammad,返回 active 即健康;细查看 systemctl status zammad-web(5.2 节)。
Q2:脚本/管道里跑 zammad:db:max_connections 报 NoMethodError: undefined method 'chomp' for nil?
该任务是交互式的,靠 $stdin.gets 逐个读答案;管道下第一个问题若无输入,gets 返回 nil,chomp 就炸了(实测完整回显见 6.2 节)。解法是预喂答案:任务实际有三问(Web 实例数、cron 并发数、其他 rails 进程数),printf "1\n0\n0\n" | zammad run rails zammad:db:max_connections 即可全自动完成,实测输出 Total Zammad processes: 3 与 Recommended PostgreSQL max_connections value: 150。
Q3:rails r 脚本里 puts 出来的是 #{u.login} 字面量而不是用户名?
%q(...) 是 Ruby 的单引号字面量,不做插值。实测:puts %q(password updated for #{u.login}) 输出字面 password updated for #{u.login};改成双引号 puts "password updated for #{u.login}" 后正确输出 password updated for admin。写脚本时字面量用 %q(...)、要插值用双引号(7.2 节两个版本都有实测)。
Q4:zammad run rake about 报 Don't know how to build task 'about'?
Zammad 的任务集里没有 about 任务(rake --tasks 可证实)。查看可用任务用 zammad run rails -T(6.1 节);确认数据库版本用 db:version(6.2 节)。同理,任何任务的准确名称都先以 rails -T 输出为准,不要凭其他 Rails 项目的记忆照搬。
Q5:zammad logs 里看到 Redis::CannotConnectError: Failed to connect to localhost:6379,搜索是不是坏了?
先看时间戳。该行来自 searchindex-rebuild.log 的历史段落——本实例 Redis 就绪前的早期重建尝试留下的记录(实测时间戳 04:22,早于服务正常运行的 04:30)。zammad logs 聚合三路日志时会把历史报错一并带出,当前是否健康以 systemctl is-active redis-server 与 production.log 最新时间为准(4.6 节有完整分析)。
Q6:改了 /etc/zammad/conf.d/ 下的变量为什么不生效?
环境变量在进程启动时读取,运行中的进程不会重载。zammad config:set 落盘后执行 zammad restart(或针对单个服务 systemctl restart zammad-web),再验证 zammad run rails r "puts ENV['变量名']" 输出新值(4.7 节实测了 set/get/unset 全闭环)。
十、参考链接
- Zammad 官方文档 - Install Zammad(包管理与后置配置):https://docs.zammad.org/en/latest/admin/install.html
- Zammad 官方文档 - Console(Rails 控制台用法):https://docs.zammad.org/en/latest/admin/console.html
- Zammad 官方文档 - Search Index(索引任务与重建):https://docs.zammad.org/en/latest/admin/elasticsearch.html
- Zammad 官方文档 - Config(配置体系与环境变量):https://docs.zammad.org/en/latest/admin/config.html
- Zammad GitHub 仓库(源码与 Releases):https://github.com/zammad/zammad
- 本专栏相关篇目:
- 《Zammad 7.2.2 介绍与选型指南》——认知与选型第一站,架构与依赖矩阵
- 《Ubuntu 22.04 安装 Zammad 指南》——从零安装与初始化实测
- 《Zammad 7.2.2 配置参数详解》——Setting 业务配置体系的改→生效→验证闭环