Postfix 3.6.4 常用 CLI 命令详解

Postfix 3.6.4 运维命令矩阵实测:postfix 生命周期、postconf 配置、postqueue/postsuper 队列手术、qshape 队列形状、postmap/postalias 查表、postcat 开箱验货与排障组合拳

Postfix邮件服务器SMTPPostfix邮件2026/10/26

Postfix 3.6.4 常用 CLI 命令详解

目标:实测覆盖 Postfix 3.6.4(Ubuntu 22.04 仓库版 3.6.4-1ubuntu1.4)日常运维命令矩阵——服务生命周期(postfix)、配置查看与修改(postconf)、队列管理(postqueue/postsuper/qshape)、查表编译(postmap/postalias)、内容检查(postcat)、日志写入(postlog)与多实例(postmulti),全部命令附真实回显。实测日期 2026-10-26,环境同《Ubuntu 22.04 安装 Postfix 3.6.4 指南》。

一、环境信息

项目值
操作系统Ubuntu 22.04 LTS(amd64)
Postfix 版本3.6.4(postconf mail_version 实测)
命令目录/usr/sbin/(postfix、postconf、postqueue、postsuper、postmap、postcat、postalias、postmulti、qshape、postlog、sendmail)
实测主机mail1.example.com(10.89.57.11);mail2.example.com(10.89.57.12)
日志/var/log/mail.log

命令分类速查(本文行文顺序):

类别命令一句话用途
服务生命周期postfixstart/stop/status/reload/flush/check
配置postconf查看/修改 main.cf 参数
队列postqueue看队列、冲刷
队列postsuperhold/release/delete/requeue 超级操作
队列统计qshape按域名聚合的队列形状
查表postmap编译/查询/删除 hash 表
别名postalias查询别名库(newaliases 底层)
内容postcat读队列文件原文
日志postlog向系统日志写一行
多实例postmulti列出/管理 Postfix 实例
前端sendmail传统投递接口(mail 命令底层)

二、服务生命周期命令:postfix

2.1 postfix start / status / stop:停启闭环

启动(master 守护进程被拉起,命令本身静默返回):

postfix start; echo "rc=$?"
pgrep -a master

实测回显:

rc=0
3946 /usr/lib/postfix/sbin/master -w

运行状态确认(在运行时静默、退出码 0;停止时同样静默、退出码 1):

postfix status; echo "rc=$?"

实测回显(运行中):

rc=0

停止与停止后状态(mail1 实测完整闭环):

postfix stop; echo "rc=$?"
pgrep -a master || echo "master not running"
postfix status; echo "rc=$?"

实测回显:

rc=0
master not running
rc=1

再启动恢复(实测回显同 2.1 首段,pgrep 显示新 PID 6094)。排障经验:postfix status 无输出时看退出码(echo $?),0=在跑、1=没跑——脚本巡检用退出码而非文本判断。

2.2 postfix reload:重载配置

改完 main.cf 后的标配动作(不杀在途 SMTP 会话):

postfix reload; echo "rc=$?"

实测回显:

rc=0

2.3 postfix flush:强制冲刷队列

对 deferred 中的信立即重试投递(与 postqueue -f 等价,静默返回):

postfix flush; echo "rc=$?"

实测回显:

rc=0

2.4 postfix check:配置与目录自检

静默通过即退出码 0(语法错误、权限问题会逐条报出):

postfix check; echo "rc=$?"

实测回显:

rc=0

💡 技术拓展:systemd 环境的 systemctl start/stop/reload postfix 最终也落到 postfix 命令上;postfix.service 的 Active 状态显示 active (exited) 属正常形态(master 脱离监管自行常驻),进程验证用 pgrep -a master,见安装指南 4.5 节。

三、配置命令:postconf

3.1 三种查看姿势:-h / 参数名 / -n / -d

postconf -h mail_version
postconf mail_version
postconf -n
postconf -d message_size_limit

实测回显:

3.6.4
mail_version = 3.6.4

-n 输出与内置默认不同的全部生效参数(全新安装机完整回显为 22 行,见安装指南 4.4 节逐项解读);-d 给内置默认值(message_size_limit = 10240000)。-h 只取值不取键名,适合脚本 $(postconf -h myhostname)。

3.2 postconf -e:修改并写回 main.cf

postconf -e "myhostname = mx1.example.net"
postconf -h myhostname

实测回显:

mx1.example.net

(改完需 postfix reload 才进入运行态;还原 postconf -e "myhostname = mail2.example.com"。)

3.3 postconf -X:删除参数恢复默认

postconf -X message_size_limit
postconf -h message_size_limit

实测回显:

10240000

(-X 只是把该键从 main.cf 移除,运行值回落到内置默认 10 MB。)

四、队列查看与冲刷命令:postqueue / mailq

4.1 制造一封 deferred 信作实验对象

(收件域 defer.example.org 在实测网络中指向一个不通的地址,投递必然失败入队;transport 表实测配置见配置详解 5.4 节同款机制。)

echo "deferred body" | mail -s "d1-capture" probe@defer.example.org
sleep 12
postqueue -p

实测回显:

-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
376EA3E14DF     357 Mon Oct 26 11:18:02  root@mail1.example.com
                    (connect to 10.89.57.99[10.89.57.99]:25: No route to host)
                                         probe@defer.example.org
-- 0 Kbytes in 1 Request.

deferred 的信会按 minimal_backoff_time(默认 300 秒)起步的退避节奏自动重试,队列 ID 后无 *(有 * 表示正在 active 队列投递中)。

4.2 postqueue -p 与 mailq:队列列表

mailq 是 postqueue -p 的传统别名,输出逐字节一致:

mailq | head -2

实测回显:

-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------

4.3 postqueue -j:机器可读 JSON

postqueue -j

实测回显:

{"queue_name": "deferred", "queue_id": "376EA3E14DF", "arrival_time": 1793013482, "message_size": 357, "forced_expire": false, "sender": "root@mail1.example.com", "recipients": [{"address": "probe@defer.example.org", "delay_reason": "connect to 10.89.57.99[10.89.57.99]:25: No route to host"}]}

每行一个 JSON 对象,监控脚本采集 delay_reason 就能拿到堆积原因。空队列时输出为空。

4.4 postqueue -f / postfix flush:立即重试

postqueue -f; echo "rc=$?"

实测回显:

rc=0

4.5 postqueue -i:按队列 ID 单封冲刷

postqueue -i 376EA3E14DF; echo "rc=$?"

实测回显:

rc=0

4.6 postqueue -s:指定站点冲刷(及其边界)

postqueue -s mail2.example.com; echo "rc=$?"

实测回显:

postqueue: fatal: Flush service is not configured for destination "mail2.example.com"
rc=69

-s 只对进入过 fast-flush 跟踪的目标站点有效,对未跟踪站点直接 fatal(退出码 69)——这是实测得出的真实边界,不是「无害空转」。

五、队列超级操作命令:postsuper

postsuper 是唯一能对队列文件做「外科手术」的命令(hold/删/重排),需 root。

5.1 postsuper -h / -H:挂起与释放

postsuper -h F30063E159D

实测回显:

postsuper: F30063E159D: placed on hold
postsuper: Placed on hold: 1 message

挂起后 postqueue -p 中该队列 ID 带 ! 标记(实测形态):

F30063E159D!     356 Mon Oct 26 11:21:00  root@mail1.example.com

投递代理不再触碰挂起的信。释放:

postsuper -H F30063E159D

实测回显:

postsuper: F30063E159D: released from hold
postsuper: Released from hold: 1 message

5.2 postsuper -r:强制重新入队

改了别名/改了 transport 后想让在队信件按新规则重新路由时用(实测):

postsuper -r F30063E159D

实测回显:

postsuper: F30063E159D: requeued
postsuper: Requeued: 1 message

5.3 postsuper -d:按 ID 删除

postsuper -d 35FBD3E3F18

实测回显:

postsuper: 35FBD3E3F18: removed
postsuper: Deleted: 1 message

批量清空 deferred(实测):

postsuper -d ALL deferred

实测回显:

postsuper: Deleted: 1 message

清理后确认:

postqueue -p

实测回显:

Mail queue is empty

5.4 postsuper 的 ID 形态:后缀才是坑

postsuper 直接接受 postqueue -p 显示形态的队列 ID(实测大写形式可识别、正常删除)。真正的坑是带着 ! 挂起后缀去操作——实测报错形态:

postsuper -d F30063E159D!

实测回显:

postsuper: warning: invalid mail queue id: F30063E159D!
postsuper: Deleted: 0 messages

对已删除的 ID 重复操作也无害(实测回显只有计数行):

postsuper: Deleted: 0 messages

结论:操作前把 postqueue -p 显示行里 ID 后面的 !/* 去掉即可,大小写不用转。

六、队列形状统计命令:qshape

qshape 按收件域聚合队列,给出「时间分桶」——每列是「N 分钟前进入队列」的信件数,一眼看出堆积是突发还是持续:

qshape deferred

实测回显(1 封 deferred,1 分钟内进入):

                                         T  5 10 20 40 80 160 320 640 1280 1280+
                                  TOTAL  1  1  0  0  0  0   0   0   0    0     0
                      defer.example.org  1  1  0  0  0  0   0   0   0    0     0

空队列形态(TOTAL 行全 0):

qshape active

实测回显:

                                         T  5 10 20 40 80 160 320 640 1280 1280+
                                  TOTAL  0  0  0  0  0  0   0   0   0    0     0

💡 技术拓展:看 deferred 的 1280+ 列是否持续增长可判断退信风暴;配合 qshape -w 5 deferred(改桶宽为 5 分钟)可细化时间粒度。qshape 位于 /usr/sbin/qshape,随 postfix 包自带。

七、查表与别名命令:postmap / postalias

7.1 postmap -s:列出表内容

postmap -s hash:/etc/postfix/virtual

实测回显:

contact@example.org	root@example.com
info@example.org	admin@example.com
postmaster@example.org	root

(该表建立与改写闭环见配置详解 6.2 节。)

7.2 postmap -q:按键查询

postmap -q info@example.org hash:/etc/postfix/virtual
postmap -q nosuchkey hash:/etc/postfix/virtual; echo "rc=$?"

实测回显:

admin@example.com
rc=1

命中输出改写值;未命中静默、退出码 1——脚本里用退出码区分。

7.3 postmap / postmap -d:编译与删键

改表文件后必须重新编译:

postmap /etc/postfix/virtual

(无输出,生成/更新 /etc/postfix/virtual.db。)删除某键后复查:

postmap -d nosuchkey hash:/etc/postfix/virtual
postmap -q nosuchkey hash:/etc/postfix/virtual

实测回显(删除动作无输出,查询未命中亦无输出):

⚠️ 排障实录:改了 /etc/postfix/virtual 或 transport 后若忘记 postmap,运行值仍是旧 .db 的内容——用 postmap -s 对拍文件内容是定位这类「改了没生效」的标准动作。

7.4 postalias / newaliases:别名库

postalias -q webmaster /etc/aliases
newaliases

实测回显(查询行):

admin

(/etc/aliases 实测内容与 webmaster→admin 的映射说明见配置详解 4.3 节;newaliases 等价于 postalias /etc/aliases 重建 hash 库,静默完成。)

八、队列文件检查命令:postcat

postcat 直接翻看队列文件原文(信封 + 头 + 正文),不用真的投递就能「开箱验货」。以一封 deferred 信(队列 ID B65183E14EC)为例:

postcat -q -e B65183E14EC

实测回显(信封段,输出节选):

*** ENVELOPE RECORDS deferred/B/B65183E14EC ***
message_size:             360             195               1               0             360               0
message_arrival_time: Mon Oct 26 11:18:41 2026
create_time: Mon Oct 26 11:18:41 2026
named_attribute: rewrite_context=local
sender_fullname: root
sender: root@mail1.example.com

只看信头(-h):

postcat -q -h B65183E14EC

实测回显(输出节选):

Received: by mail1.example.com (Postfix, from userid 0)
	id B65183E14EC; Mon, 26 Oct 2026 11:18:41 +0000 (UTC)
Subject: d1-capture3
To: <probe@defer.example.org>
User-Agent: mail (GNU Mailutils 3.14)

不带 -e/-h 则输出信封+头+正文的完整记录(首行同为 *** ENVELOPE RECORDS deferred/B/B65183E14EC ***)。路径前缀 deferred/B/ 同时告诉你它躺在哪个队列。

对不存在的 ID,实测报错形态:

postcat -q 376EA3E14DF

实测回显:

postcat: fatal: open queue file 376EA3E14DF: No such file or directory

(该信已被 postsuper -d 删除——postcat 的报错同时是队列清理的旁证。)

九、日志与多实例命令:postlog / postmulti / sendmail

9.1 postlog:向系统日志写一行

把自定义告警写进与 Postfix 同一条日志流(rsyslog 提供 /var/log/mail.log):

postlog -t postfix-doc "postlog write test from doc"
grep postfix-doc /var/log/mail.log

实测回显:

Oct 26 10:46:07 mail1 postfix-doc[5844]: postlog write test from doc

-t 指定 tag(相当于日志的程序名),运维脚本里可用来把巡检结论写回邮件日志流统一检索。

9.2 postmulti -l:多实例清单

postmulti -l

实测回显:

-               -               y         /etc/postfix

单实例部署只有一行默认实例(name 为 -,enabled=y,config 目录 /etc/postfix)。需要一台服务器跑多套 MTA(不同 IP/不同端口)时用 postmulti -e create 增开实例。

9.3 sendmail -bv:只验证不投递

Postfix 兼容 sendmail 命令行,-bv 做「地址可达性」验证而不真正投递:

sendmail -bv root

实测回显:

Mail Delivery Status Report will be mailed to <root>.

随后 root 会收到一封 DSN 报告信(投递成功形态),失败场景则报告不可达原因。日常交互发信仍推荐 mail 命令(mailutils 提供,底层同走 sendmail 接口)。

9.4 版本锁定:apt-mark(安装视角)

防止 apt upgrade 意外升级 MTA:

apt-mark hold postfix
apt-mark unhold postfix

实测回显:

postfix set on hold.
Canceled hold on postfix.

十、排障组合拳实录

以「用户反馈某域名发信总失败」为例,把上面命令串成标准作业流(全部实测过):

  1. 看队列形状:qshape deferred → 按域分桶(6 节实测回显),确认是不是目标域集中堆积;
  2. 看明细与原因:postqueue -j → 拿 delay_reason(4.3 节实测 connect to ...: No route to host);
  3. 开箱验货:postcat -q -e <ID> 确认发件人/收件人/路由属性(8 节实测);
  4. 按需处置:临时止血 postsuper -h <ID> 挂起,修复后 postsuper -H <ID> 放行;确认是死信 postsuper -d <ID>(5 节实测);
  5. 变更配置:postconf -e + postfix reload(3 节实测),必要时 postsuper -r <ID> 让存量信按新路由重排(5.2 节实测);
  6. 对账:postqueue -p 归零(Mail queue is empty,5.3 节实测),postfix check 静默(2.4 节实测)。

十一、常见问题(排障实录)

Q1:postfix status 到底有没有输出? 任何状态都无文本输出,判断靠退出码(运行 0 / 停止 1,2.1 节实测闭环)。脚本巡检别 grep 文本。

Q2:postqueue -s 报 fatal 69? 目标站点不在 fast-flush 跟踪范围(4.6 节实测原文)。全局冲刷用 -f,单封用 -i。

Q3:postsuper 说 invalid mail queue id 或删除数为 0? 两种实测形态:ID 带着 postqueue -p 的 !/* 后缀 → warning: invalid mail queue id: …!(5.4 节原文),去掉后缀重试;ID 已被删除/投出 → Deleted: 0 messages,无需处理。

Q4:改了 transport/virtual 没生效? 忘了 postmap 编译或 postfix reload(7.3 节排障实录)。对拍 postmap -s 与文件内容即可定位。

Q5:队列清空后 qshape 还有数据? qshape 读的是即时队列,先 postqueue -p 确认队列真空了再看;持续增长的 1280+ 桶说明有源头在不停注入,查发件方而不是只删队列。

Q6:postcat 显示 deferred/B/xxx 路径是什么意思? 斜杠前是队列名、单字母是 hash 子目录(大队列分散目录用),不影响 postcat -q <ID> 的用法。

十二、参考链接

  1. Postfix 官方命令手册集:https://www.postfix.org/documentation.html(postfix(1)、postqueue(1)、postsuper(1)、postcat(1) 等)
  2. Postfix 队列机制 OVERVIEW:https://www.postfix.org/QSHAPE_README.html
  3. 站内同族实战:《Ubuntu 22.04 安装 Postfix 3.6.4 指南》(安装与双机闭环)、《Postfix 3.6.4 配置参数详解》(参数级细节)、《Mailcow 2026-09a 介绍与选型指南》