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

Bash脚本中Mailx无法发送邮件问题求助

嘿,这个问题我太熟了——你遇到的是Bash里历史扩展搞的鬼!单独执行mail没问题,但用echo管道带!就报错-bash: !": event not found,核心原因是双引号里的!会被Bash当成历史命令的扩展符,哪怕你加了反斜杠也没用(双引号里的反斜杠不阻止!的扩展)。

问题根源

Bash默认开启了历史扩展(set -H是默认状态),当你在双引号里写!时,它会尝试去匹配历史命令里的内容,而不是把它当成普通字符。你单独执行mail时可能用的是单引号,或者没在双引号里放!,所以没问题,但脚本里的双引号包裹了带!的字符串,就触发了这个问题。

修复方案

我给你两个简单的解决办法,再顺便修复脚本里的其他小bug:

1. 关闭历史扩展(最简单)

在脚本开头加上set +H,直接关闭Bash的历史扩展功能,这样双引号里的!就会被当成普通字符处理了。

2. 用单引号包裹带!的部分

如果不想关闭历史扩展,可以把包含!的字符串部分用单引号包裹,同时保留变量的双引号扩展(因为单引号里变量不会被解析)。比如把:

echo "$(date): ping OK, $IP host is UP\!" | mail -s "$IP host is UP\!" "$EMAIL"

改成:

echo "$(date): ping OK, $IP host is UP"'!' | mail -s "$IP host is UP"'!' "$EMAIL"

这里"'!"是把!放在单引号里,前面的变量部分用双引号正常解析。

顺便修复脚本里的其他小问题

除了!的问题,你的脚本还有几个小bug:

  • 数组定义了arrIP=()但实际用的是arrIPAddress,这个数组其实没用到,可以删掉或者统一变量名
  • 最后循环的结束符是大写DONE,Bash里必须小写done
  • 日志文件里的\!转义是多余的,写入文件时不需要转义!

修复后的完整脚本

#!/bin/bash
exec 5> debug_output.txt
BASH_XTRACEFD="5"
PS4='$line0: '
set -x
set +H  # 关闭历史扩展,解决!的问题
trap "exit" INT

echo "Please enter time in seconds:"
read -r var1
echo "Please enter email address"
read -r var2

LOG=mylog.log
SECONDS="$var1"
EMAIL="$var2"

# 数组未实际使用,可删除;若需保留请统一变量名
# arrIP=()
echo "Enter the IP addresses here enter and Ctrl-d when finished :"
while read IP
do
    # arrIP+=($IP)  # 如需使用数组请启用该行
    echo "$IP" >> ip_monitor_list.txt
    echo "$IP-UP!" > "$LOG.$IP"  # 移除多余的反斜杠
done

while true;
do
    cat ip_monitor_list.txt | while read IP
    do
        fping -c 1 -q "$IP" > /dev/null
        if [ $? -eq 0 ]; then
            STATUS=$(cat "$LOG.$IP")
            if [ "$STATUS" != "$IP-UP!" ]; then
                echo "$(date): ping OK, $IP host is UP!" | mail -s "$IP host is UP!" "$EMAIL"
            fi
            echo "$IP-UP!" > "$LOG.$IP"
        else
            STATUS=$(cat "$LOG.$IP")
            if [ "$STATUS" != "$IP-DOWN!" ]; then
                echo "$(date): ping Failed, $IP host is DOWN!" | mail -s "$IP host is DOWN!" "$EMAIL"
            fi
            echo "$IP-DOWN!" > "$LOG.$IP"
        fi
    done
    sleep "$SECONDS"
done  # 修正为小写done

# File cleanup
rm ip_monitor_list.txt

你可以试试这个修复后的脚本,应该就能正常发送邮件了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:07:56