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

