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
相关产品推荐
相关产品推荐

