Haraka 3.3.5 常用 CLI 命令详解
Haraka 3.3.5 命令行工具全集实测:haraka 主命令(-i、-c、-l、-o、-p、-t、--qlist 等)与 haraka_grep 的用法、回显与踩坑实录
Haraka 3.3.5 常用 CLI 命令详解
目标:逐条讲清 Haraka 3.3.5 自带的命令行工具——
haraka主命令(版本查询、初始化、插件管理、运行、插件测试模式、出站队列管理)与haraka_grep日志检索脚本——给出真实回显、参数表、典型用法与踩坑实录,作为日常运维的速查手册。
一、环境信息
本文全部命令与回显在以下环境实测:
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Node.js:v20.20.2;npm:10.8.2
- Haraka:3.3.5(npm 全局安装,二进制位于 /usr/bin/haraka,包主体位于 /usr/lib/node_modules/Haraka)
- 服务目录:/opt/haraka;服务身份:mail01.example.com
- 运行方式:systemd 托管(haraka.service),25 端口
安装与托管过程见 《Ubuntu 22.04 安装 Haraka 3.3.5 指南》,配置文件逐项含义见 《Haraka 3.3.5 配置参数详解》。
二、工具概览
Haraka 3.3.5 的 npm 包自带两个可执行入口(bin 字段声明):
| 命令 | 路径 | 用途 |
|---|---|---|
| haraka | /usr/bin/haraka | 主命令:安装初始化、启动服务、插件管理、测试模式、队列管理 |
| haraka_grep | /usr/bin/haraka_grep | shell 脚本:在 Haraka 日志文件中按模式检索 |
三、前置条件
- 已安装 Haraka(
haraka --version可执行); - 服务目录已存在(没有则先
haraka -i /opt/haraka); - 系统装有
less(-h查看插件文档依赖它,缺失会崩溃,见 6.2 节); haraka_grep依赖grep/bzgrep/zgrep与 /var/log/maillog 式日志文件(Ubuntu 上默认不存在,见 6.4 节)。
四、haraka 主命令
4.1 命令总览与帮助
haraka --help
实测回显(全文):
Haraka.js — A Node.js Email Server project
Usage: haraka [options] [path]
Options:
-v, --version Outputs version number
-h, --help Outputs this help message
-h NAME Shows help for NAME
-c, --configs Path to your config directory
-i, --install Copies the default configs to a specified dir
-l, --list List the plugins bundled with Haraka
-p, --plugin Generate a new plugin with the given name
-f, --force Force overwriting of old files
--qlist List the outbound queue
--qstat Get statistics on the outbound queue
--qunstick Unstick (force delivery) for a given domain
-o, --order Show all registered plugins and their run order
-t PLUGIN Plugin test mode
--------------- PLUGIN TEST MODE OPTIONS (all optional) --------------
--ip IP IP address to use
--helo HELO HELO to use
--ehlo EHLO EHLO to use
--envfrom FROM MAIL FROM to use
--envfrom TO RCPT TO(s) to use
--message FILE Message file to use
--dump-mime Dump the MIME structure and body text
--dump-stream Dump the MessageStream to stdout
--skip-deny Continue running hooks after DENY/DENYSOFT
--set-relay Set connection.relaying
💡 注意帮助原文中
--envfrom TO为官方帮助的笔误(第 15 行与第 16 行重复了 --envfrom),实际作用是--envto TO——指定 RCPT TO,实测见 4.8 节。
4.2 版本与帮助查询(-v / -h)
haraka --version
haraka -v
实测回显(两个写法等价):
Haraka.js — Version: 3.3.5
4.3 初始化服务目录(-i)
haraka -i /opt/haraka
实测回显(在全新目录执行时):
create: /opt/haraka
create: /opt/haraka/plugins
create: /opt/haraka/docs
create: /opt/haraka/config
create: /opt/haraka/docs/Plugins.md
create: /opt/haraka/config/connection.ini
create: /opt/haraka/config/smtp.ini
create: /opt/haraka/config/log.ini
create: /opt/haraka/config/plugins
要点:-i 只生成骨架不启动服务;目录已存在时在已有文件上执行会保留原文件(不覆盖),配合 -f 可强制覆盖。生成文件清单与作用见《Haraka 3.3.5 配置参数详解》第四节。
4.4 前台启动运行(-c)
haraka -c /opt/haraka
实测回显(前台启动,Ctrl+C 结束;输出节选):
Using iconv-lite only. To support rare encodings: npm install iconv
loglevel: DEBUG
log format: DEFAULT
[WARN] [-] [server] smtp.ini.nodes unset, using 1, see https://github.com/haraka/Haraka/wiki/Performance-Tuning
Starting up Haraka version 3.3.5
[DEBUG] [-] [plugins] Loading
[INFO] [-] [plugins] loading relay
[DEBUG] [-] [plugins] registered hook connect_init to relay.acl priority 0
[ERROR] [-] [relay] appending missing CIDR suffix in: relay_acl_allow
⚠️ 注意两条启动告警的含义:
nodes unset提示未设 cluster worker 数(设nodes=cpus消除);appending missing CIDR suffix提示 relay_acl_allow 里的127.0.0.1未带掩码(Haraka 自动按 /32 处理并告警,写成127.0.0.1/32消除)。loglevel: DEBUG回显说明前台启动在读取 log.ini 当前值,示例环境当时 level=debug。
生产环境用 systemd 托管(unit 文件见安装指南 4.5 节),前台方式仅用于首次排障:
systemctl start haraka # 生产启动
systemctl status haraka # 状态
journalctl -u haraka -f # 实时日志(等价前台观察)
4.5 内置插件清单(-l)
haraka -l
实测回显(全文):
*global
plugins/
block_me
data.signatures
delay_deny
prevent_credential_leaks
process_title
profile
rcpt_to.host_list_base
rcpt_to.in_host_list
record_envelope_addresses
reseed_rng
status
tarpit
tls
toobusy
xclient
plugins/auth
auth_base
auth_bridge
auth_proxy
auth_vpopmaild
flat_file
plugins/queue
deliver
discard
lmtp
qmail-queue
quarantine
smtp_bridge
smtp_forward
smtp_proxy
test
NPM packages (/usr/lib/node_modules/Haraka)
access
aliases
asn
attachment
bounce
clamd
dcc
dkim
dns-list
early_talker
fcrdns
geoip
greylist
headers
helo.checks
karma
known-senders
limit
mail_from.is_resolvable
messagesniffer
qmail-deliverable
redis
relay
rspamd
spamassassin
spf
uribl
清单分四组:plugins/(内置顶层插件)、plugins/auth/(认证族)、plugins/queue/(队列族)、NPM packages(随包分发的 npm 插件)。名称可原样填入 config/plugins 启用。
4.6 插件执行顺序查看(-o)
haraka -o -c /opt/haraka
实测回显(实验环境启用了 relay、access、tls、mail_from.is_resolvable、rcpt_to.in_host_list、queue/smtp_forward 时,全文):
loglevel: DEBUG
log format: DEFAULT
Hook: connect_init -------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
relay acl 0 30
Hook: connect ------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
relay pass_relaying 0 30
access rdns_access 0 30
access any 0 30
Hook: capabilities -------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
tls advertise_starttls 0 30
Hook: unrecognized_command -----------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
tls upgrade_connection 0 30
Hook: disconnect ---------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
tls hook_disconnect 0 30
Hook: helo ---------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
access any 0 30
Hook: ehlo ---------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
access any 0 30
Hook: mail ---------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
access mail_from_access 0 30
access any 0 30
mail_from.is_resolvable hook_mail 0 30
rcpt_to.in_host_list hook_mail 0 30
Hook: rcpt ---------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
access rcpt_to_access 0 30
access any 0 30
rcpt_to.in_host_list hook_rcpt 0 30
Hook: data_post ----------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
access data_any 0 30
Hook: queue --------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
queue/smtp_forward queue_forward 0 30
Hook: get_mx -------------------------------------------------------------------
Plugin Method Prio T/O
--------------------------------------------------------------------------------
relay force_routing 0 30
queue/smtp_forward get_mx 0 30
解读:每个 Hook 段内的行序即执行序(Prio 相同时按 config/plugins 中的声明顺序);T/O 是插件超时(30 秒,来自 plugin_timeout)。修改 config/plugins 后用本命令核对实际生效的钩子链,是调序排障的第一工具。
4.7 插件文档查看(-h NAME)
haraka -h tls
实测回显(输出节选,less 分页展示插件 README):
# tls
This plugin enables the use of TLS (via `STARTTLS`) in Haraka.
For this plugin to work you must have SSL certificates installed correctly.
Haraka has [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) support. When the remote MUA/MTA presents a servername during the TLS handshake and a TLS certificate with that Common Name matches, that certificate will be presented. If no match is found, the default certificate (see Certificate Files) is presented.
## Certificate Files
Defaults settings are shown and can be overridden in `config/tls.ini`.
```ini
key=tls_key.pem
内容即插件的 README.md(含全部配置键说明),Q 键退出。按 haraka -h <插件名> 可查任一已装插件的文档;自定义插件的路径形式(如 haraka -c /opt/haraka -h plugins/my_first_plugin)同样支持。
⚠️ 已知坑:未安装 less 的最小化系统上此命令直接崩溃
Error: spawn less ENOENT,apt-get install -y less解决(详见安装指南 FAQ Q1)。
4.8 生成新插件脚手架(-p / -f)
正确用法必须同时给 -c 指定服务目录:
haraka -p my_first_plugin -c /opt/haraka
实测产物(生成两个文件):
/opt/haraka/plugins/my_first_plugin.js
/opt/haraka/docs/plugins/my_first_plugin.md
生成的插件模板内容(实测 cat 节选):
// my_first_plugin
// documentation via: haraka -c /opt/haraka -h plugins/my_first_plugin
// Put your plugin code here
// type: `haraka -h Plugins` for documentation on how to create a plugin
错误用法一:不带 -c 直接 haraka -p my_first_plugin,实测报错:
Error: Undefined or erroneous arguments
重复生成:同名文件已存在时(不带 -f)实测报错:
Error: /opt/haraka/plugins/my_first_plugin.js already exists
覆盖重建需加 -f(--force)。
4.9 出站队列管理(--qlist / --qstat / --qunstick)
出站队列文件位于服务目录的 queue/ 子目录,滞留消息(下游临时失败重试中)可用以下命令查看与干预。
列出队列消息:
haraka --qlist -c /opt/haraka
实测回显(队列中有 1 封滞留消息时):
Using iconv-lite only. To support rare encodings: npm install iconv
loaded TLD files: 1=1437 2=7876 3=3795
Q: 1792548278720_1792550369331_5_5170_NnZ1vS_2_317dc6228b57 rcpt:1 from:<sender@gmail.com> domain:stuck.example
队列文件名的重试计数段会随退避递增(第 3 段 _5_ 表示已临时失败 5 次);rcpt:1 收件人数、from: 发件人、domain: 投递域。
统计概要:
haraka --qstat -c /opt/haraka
实测回显:
Using iconv-lite only. To support rare encodings: npm install iconv
{ queue_dir: '/opt/haraka/queue', queue_count: 1 }
对指定域强制重投(解除退避等待):
haraka --qunstick stuck.example -c /opt/haraka
实测回显:
250 Command sent for execution. Check Haraka logs for results.
命令经 config/internalcmd_key 密钥通道下发给运行中的 Haraka,实际投递结果看日志(journalctl 中会立刻出现一次 get_mx/连接尝试)。
⚠️ 注意:三个命令都必须带
-c指向服务目录(否则找不到队列与 internalcmd_key)。Using iconv-lite only与loaded TLD files是这两类命令的固定开场提示行,非错误;提示缺 iconv 包仅在处理生僻编码邮件时有影响,可cd /usr/lib/node_modules/Haraka && npm install iconv补装。
4.10 插件测试模式(-t 及其参数)
-t <插件名> 用于在命令行单插件地加载并模拟 SMTP 会话,避免重启真实服务。参数组见 4.1 帮助输出末段。
典型调用(模拟 EHLO/MAIL/RCPT 环境):
haraka -t headers --ip 8.8.8.8 --ehlo tester.gmail.com --envfrom sender@gmail.com --envto postmaster@example.com --message /tmp/msg.eml --dump-mime -c /opt/haraka
实测回显(3.3.5,输出节选):
loglevel: DEBUG
log format: DEFAULT
[DEBUG] [-] [plugins] Loading
[INFO] [-] [plugins] loading headers
[DEBUG] [-] [plugins] no timeout in headers.timeout
[DEBUG] [-] [plugins] plugin headers timeout is: 30s
[DEBUG] [-] [plugins] registered hook data_post to headers.duplicate_singular priority 0
[DEBUG] [-] [plugins] registered hook data_post to headers.missing_required priority 0
[DEBUG] [-] [plugins] registered hook data_post to headers.invalid_return_path priority 0
...
Using iconv-lite only. To support rare encodings: npm install iconv
[DEBUG] [BF09E4B3-4D73-41CD-BC24-B598D57EC924] [core] setupClient got no IP address for this connection!
loaded TLD files: 1=1437 2=7876 3=3795
loaded Public Suffixes: 10210
实测观察(如实记录):在 3.3.5 环境中,测试模式能完成「加载指定插件 → 注册钩子 → 初始化连接上下文(日志出现模拟连接的 DEBUG 行)」全流程,但在 loaded Public Suffixes 后即正常退出(秒级),mail/rcpt/data_post 钩子的实际判定结果未打印输出(对 mail_from.is_resolvable、rcpt_to.in_host_list、headers 三类插件以 --dump-mime 等参数组合重复实测,现象一致)。因此当前版本 haraka -t 的可靠用途是验证插件能否加载、钩子能否注册;完整钩子行为验证建议用真实 SMTP 会话 + log.ini 临时 debug 级日志(见《Haraka 3.3.5 配置参数详解》FAQ Q2)。
| 参数 | 说明 |
|---|---|
| -t PLUGIN | 指定测试的插件名;-t all 表示全插件 |
| --ip IP | 模拟客户端 IP |
| --helo / --ehlo | 模拟 HELO/EHLO 名 |
| --envfrom FROM | 模拟 MAIL FROM |
| --envto TO | 模拟 RCPT TO(帮助文本写作 --envfrom TO 为笔误) |
| --user | 模拟客户端 uid |
| --message FILE | 用指定文件作为消息内容 |
| --dump-mime | 输出解析后的 MIME 结构 |
| --dump-stream | 输出 MessageStream 原始流 |
| --skip-deny | DENY/DENYSOFT 后继续跑后续钩子 |
| --set-relay | 置 connection.relaying=true(模拟中继客户端) |
五、haraka_grep 日志检索工具
5.1 定位与用法
haraka_grep 是一个 shell 脚本,用于在 Haraka 的日志文件(含压缩归档)中按模式检索,设计配合 syslog 风格日志(日志写入 /var/log/maillog 时):
haraka_grep <pattern> [目录]
脚本头部实测(grep 到的关键逻辑):
haraka_grep is a shell script that greps log files for a pattern and then prints
the results with the filename, line number, and the pattern highlighted.
其检索目标在脚本内硬编码为 /var/log/maillog(对归档文件使用 bzgrep/zgrep 兜底)。
5.2 实测行为与 Ubuntu 适配
在本环境的 Ubuntu 22.04(日志走 journald,无 /var/log/maillog)下执行:
haraka_grep "Listening" /opt/haraka/config
实测回显(脚本对不存在目标的处理,输出节选):
grep: /var/log/maillog: No such file or directory
结论(生产建议):
| 日志形态 | 推荐检索方式 |
|---|---|
| systemd 托管(本篇主线) | `journalctl -u haraka --no-pager |
| log.syslog/syslog 插件写入 /var/log/maillog(RedHat 系习惯路径) | haraka_grep <pattern> 直接可用 |
| format=json 落文件 | jq -r <字段> 过滤更高效 |
六、注意事项
-c是万能前缀:-o/-p/--qlist/--qstat/--qunstick/-t 都要求(或强烈建议)同时指定-c /opt/haraka,否则命令找不到配置/队列/密钥或直接报参数错误;-h依赖 less:最小化系统先装 less;- 前台启动必须
-c:haraka /opt/haraka位置参数写法报Error: Undefined or erroneous arguments; - 队列命令的密钥前提:--qunstick 依赖 config/internalcmd_key(haraka -i 生成),该文件丢失会使在线队列干预失效;
- 保持命令与版本同步:Haraka 补丁版本节奏快(月度级),升级后用
haraka --version与haraka -o -c复核插件注册行为是否变化(如 -t 的输出行为在版本间曾有变化); - 输出清洗:journalctl 回显里的时间戳/UUID 属每次会话不同的动态值,做自动化比对时按字段截取而非全行匹配。
七、常见问题(FAQ)
Q1:haraka 命令找不到(command not found)。
原因:npm 全局 bin 目录不在 PATH。先定位:which haraka;npm 全局安装的 bin 在 /usr/bin(root 安装)或 npm prefix/bin 目录。可用 npm ls -g --depth=0 确认包已装,npm config get prefix 查看全局前缀。
Q2:--qlist 显示的文件在 queue/ 目录找不到?
qlist 读取的是队列文件名列表,而工作进程在临时失败重试时会把队列文件改名(文件名中重试计数递增),两次查看之间文件名可能已变化,属正常现象;以 qlist 最新输出为准。
Q3:-o 输出 loglevel: DEBUG 但 log.ini 是 info?
-o 启动时也会读 log.ini,回显即当前值;若不一致先确认没有其他 haraka 进程/配置目录(-c 指错路径)。
Q4:如何让自建插件进入 -o 输出?
插件文件放 /opt/haraka/plugins/ 后,必须在 config/plugins 中登记才会注册钩子;只写文件不登记时 -l/-o 都不会出现,haraka -p 生成的模板也要手动加进 config/plugins。
八、参考链接
- Haraka 主命令源码(bin/haraka,参数定义):https://github.com/haraka/Haraka/blob/master/bin/haraka (查询日期 2026-10-21)
- haraka_grep 脚本源码:https://github.com/haraka/Haraka/blob/master/bin/haraka_grep (查询日期 2026-10-21)
- 插件注册表 Plugins.md:https://github.com/haraka/Haraka/blob/master/Plugins.md (查询日期 2026-10-21)
- 站内系列:《Ubuntu 22.04 安装 Haraka 3.3.5 指南》、《Haraka 3.3.5 配置参数详解》、《Haraka 3.3.5 介绍与选型指南》