You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本printf不打印变量,Postfix日志查询脚本输出为空求助

问题原因

你脚本无输出的核心原因是printf格式占位符错误:你在格式字符串中写了$s,但bash的printf占位符需要用%s,$s会被解析为名为s的变量,你没有定义该变量所以输出为空。

除此之外你的脚本还有几处逻辑问题:

  • 提取队列ID的逻辑冗余且不稳定:你用-F"smtp"分割日志行的方式仅能匹配smtp进程的日志,一旦日志结构有微小变化就会提取失败
  • 循环内反复读取整个邮件日志三次,日志量大的时候执行效率极低
  • 多余的sed正则替换:你的日志中没有分号分隔的字段,sed -r 's/^([^;]*;)[^;]*;/\1/'这行完全无效,可以直接删除
  • 循环内覆盖了外层的RCPT变量,容易引发逻辑混乱
  • 使用老旧的反引号做命令替换,不如$()写法规范、兼容性好
修复后的完整脚本
#!/bin/bash

if [ $# -ne 1 ] ; then
    echo "
    请输入收件人邮箱
    示例:$0 rcpt@rcpt.com

"
    exit 1
fi

TARGET_RCPT="$1"
MAILOG="/var/log/mail.log"

echo -e "
==== 发送到 <$1> 的邮件详情汇总 ==== 
"

# 提取所有匹配收件人的队列ID
QUEUEID=$(grep -w "to=<${TARGET_RCPT}>" "${MAILOG}" | grep -E "status=(sent|deferred|bounced)" | awk '{print substr($6,1,length($6)-1)}' | sort | uniq)

for QID in ${QUEUEID} ; do
    # 一次读取当前队列ID对应的所有日志行,避免重复读文件
    QID_LOGS=$(grep -- "${QID}" "${MAILOG}")
    # 提取发件人
    EMAIL=$(echo "${QID_LOGS}" | grep -w "from=" | tr -d ',' | grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b")
    # 提取收件人
    TO_ADDR=$(echo "${QID_LOGS}" | grep -w "to=" | tr -d ',' | grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b")
    # 提取日期
    DATE=$(echo "${QID_LOGS}" | head -n1 | awk '{print $1, $2, $3}')
    # 格式化输出
    printf "From: %s\nTo: %s\nDate: %s\nLOG_ID: %s\n\n" "${EMAIL}" "${TO_ADDR}" "${DATE}" "${QID}"
done

exit 0
优化说明
  • 修复了printf占位符错误,直接解决无输出问题
  • 简化队列ID提取逻辑:直接取日志第6个字段,删除末尾的冒号即可得到队列ID,稳定性更高
  • 每个队列ID仅读取一次日志,效率提升3倍
  • 变量命名更清晰,避免变量覆盖问题
  • 所有变量引用都加了双引号,避免特殊字符引发的异常
  • 输出格式和你要求的目标格式完全对齐

内容的提问来源于stack exchange,提问作者pi314

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:36:07