Postfix 3.6.4 常用 CLI 命令详解
Postfix 3.6.4 运维命令矩阵实测:postfix 生命周期、postconf 配置、postqueue/postsuper 队列手术、qshape 队列形状、postmap/postalias 查表、postcat 开箱验货与排障组合拳
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 |
命令分类速查(本文行文顺序):
| 类别 | 命令 | 一句话用途 |
|---|---|---|
| 服务生命周期 | postfix | start/stop/status/reload/flush/check |
| 配置 | postconf | 查看/修改 main.cf 参数 |
| 队列 | postqueue | 看队列、冲刷 |
| 队列 | postsuper | hold/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.
十、排障组合拳实录
以「用户反馈某域名发信总失败」为例,把上面命令串成标准作业流(全部实测过):
- 看队列形状:
qshape deferred→ 按域分桶(6 节实测回显),确认是不是目标域集中堆积; - 看明细与原因:
postqueue -j→ 拿 delay_reason(4.3 节实测connect to ...: No route to host); - 开箱验货:
postcat -q -e <ID>确认发件人/收件人/路由属性(8 节实测); - 按需处置:临时止血
postsuper -h <ID>挂起,修复后postsuper -H <ID>放行;确认是死信postsuper -d <ID>(5 节实测); - 变更配置:
postconf -e+postfix reload(3 节实测),必要时postsuper -r <ID>让存量信按新路由重排(5.2 节实测); - 对账:
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> 的用法。
十二、参考链接
- Postfix 官方命令手册集:https://www.postfix.org/documentation.html(postfix(1)、postqueue(1)、postsuper(1)、postcat(1) 等)
- Postfix 队列机制 OVERVIEW:https://www.postfix.org/QSHAPE_README.html
- 站内同族实战:《Ubuntu 22.04 安装 Postfix 3.6.4 指南》(安装与双机闭环)、《Postfix 3.6.4 配置参数详解》(参数级细节)、《Mailcow 2026-09a 介绍与选型指南》