Cron执行Bash脚本时未按指定邮箱发送邮件问题
问题解决:Cron执行脚本时邮件发件人/收件人异常
我有一个Bash脚本,命令行执行时能正常从alerts@xyz.one向bob.bok@example.com发送邮件,但加入Cron(配置为*/5 * * * * /scripts/check_running/check-running.sh)后,/var/log/mail.log显示邮件发件人为root@dev.localdomain、收件人为mod@dev.localdomain,并非脚本指定地址。已尝试指定mail命令绝对路径、用bash调用脚本,问题依旧。
相关配置内容
脚本内容
#!/bin/bash while read LINE do if curl --insecure -s -o /dev/null -w "%{http_code}" "${LINE}" | grep 200 2>&1 &>/dev/null ; then #echo "${LINE} is up" sleep 1 else #echo "${LINE} is down" echo "${LINE} is down" | mail -s "Env is down ${LINE}" -a "From:alerts@xyz.one" bob.bok@example.com sleep 1 fi done < env-list.txt
Cron配置
*/5 * * * * /scripts/check_running/check-running.sh
/var/log/mail.log日志
Aug 21 13:45:01 dev postfix/pickup[1495499]: 99CC78C1D42: uid=0 from=<root> Aug 21 13:45:01 dev postfix/cleanup[1500197]: 99CC78C1D42: message-id=<20230821114501.99CC78C1D42@dev.localdomain> Aug 21 13:45:01 dev postfix/qmgr[1483811]: 99CC78C1D42: from=<root@dev.localdomain>, size=704, nrcpt=1 (queue active) Aug 21 13:45:01 dev postfix/local[1500199]: warning: dict_nis_init: NIS domain name not set - NIS lookups disabled Aug 21 13:45:01 dev postfix/local[1500199]: 99CC78C1D42: to=<mod@dev.localdomain>, orig_to=<root>, relay=local, delay=0.07, delays=0.06/0.01/0/0, dsn=2.0.0, status=sent (delivered to mailbox) Aug 21 13:45:01 dev postfix/qmgr[1483811]: 99CC78C1D42: removed
Postfix main.cf配置
# Enable auth smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous smtp_tls_security_level = encrypt header_size_limit = 4096000 relayhost = [mx.xyz.one]:587 inet_interfaces = 127.0.0.1
问题原因分析
从日志的orig_to=<root>字段能判断,这封异常邮件是Cron自身发送的错误通知,而非脚本里的mail命令生成的。核心原因:
- Cron执行脚本时默认工作目录是
/root,脚本里用相对路径env-list.txt会找不到文件,导致脚本执行报错 - Cron会把脚本执行的错误信息发送给当前Cron用户(此处为root),而系统中root的邮箱别名被设置为mod,所以邮件最终投递到
mod@dev.localdomain
另外,不同系统的mail命令参数存在差异:比如Heirloom mailx中-a参数是用来添加附件的,设置发件人需要用-r选项,这也可能导致脚本里的mail参数无效。
解决方案
1. 修复文件路径问题
两种方式任选其一:
- 直接使用
env-list.txt的绝对路径:done < /scripts/check_running/env-list.txt - 脚本开头切换到脚本所在目录,确保相对路径有效:
#!/bin/bash # 切换到脚本所在目录,失败则退出 cd "$(dirname "$0")" || exit 1
2. 修正mail命令的发件人参数
根据你使用的mail版本调整:
- 若为Heirloom mailx(常见于CentOS/RHEL),用
-r指定发件人:echo "${LINE} is down" | mail -s "Env is down ${LINE}" -r alerts@xyz.one bob.bok@example.com - 若为BSD mailx(常见于Debian/Ubuntu),可保留
-a参数,或设置环境变量统一指定发件人:# 脚本开头添加 export MAILFROM="alerts@xyz.one"
3. 调试Cron执行情况
在Cron配置中添加输出重定向,查看脚本执行的具体错误:
*/5 * * * * /scripts/check_running/check-running.sh >> /var/log/check-running.log 2>&1
之后查看/var/log/check-running.log即可定位脚本执行时的问题。
内容的提问来源于stack exchange,提问作者Kamil Sz
相关产品推荐
相关产品推荐

