Cron任务执行Shell脚本时邮件无法发送,求排查原因
Cron执行Shell脚本删除文件成功但邮件发送失败的排查与解决
你遇到的问题是典型的Cron环境与交互式Shell环境差异导致的:脚本确实执行了(文件被删除),但邮件发送环节因环境不兼容失败,具体原因和解决方法如下:
1. Cron的PATH环境变量不包含sendmail路径
Cron默认的PATH非常有限(通常仅为/usr/bin:/bin),而sendmail往往安装在/usr/sbin或其他不在默认PATH的目录下。交互式Shell会加载全局/用户配置文件,能识别sendmail路径,但Cron不会。
解决方法:
- 先在命令行执行
which sendmail获取sendmail的绝对路径(例如/usr/sbin/sendmail) - 修改脚本中的sendmail调用,替换为绝对路径:
auditFile="/application-data/auditUrl.txt" [ -e $auditFile ] && (echo -e "Subject: Foo\nTo: user@example.com\n\n" `cat $auditFile` | /usr/sbin/sendmail -t ; rm -f $auditFile )
2. echo的-e参数在Cron默认Shell下不生效
Cron默认使用/bin/sh而非/bin/bash,POSIX标准的sh不支持echo -e参数,会导致邮件头的换行符无法正确解析,sendmail无法识别合法的邮件格式,进而发送失败。
解决方法:
用兼容性更好的printf替代echo -e:
auditFile="/application-data/auditUrl.txt" [ -e $auditFile ] && (printf "Subject: Foo\nTo: user@example.com\n\n%s" "$(cat $auditFile)" | sendmail -t ; rm -f $auditFile )
3. 缺少sendmail依赖的环境变量
Cron执行时不会加载用户的环境配置文件(如~/.bashrc、/etc/profile),sendmail可能依赖某些环境变量才能正常运行。
解决方法:
在脚本开头手动导入环境变量,或直接设置完整PATH:
# 导入系统全局环境变量 . /etc/profile # 或直接指定完整PATH export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" auditFile="/application-data/auditUrl.txt" [ -e $auditFile ] && (printf "Subject: Foo\nTo: user@example.com\n\n%s" "$(cat $auditFile)" | sendmail -t ; rm -f $auditFile )
验证排查方法
可在脚本开头添加日志输出,记录执行过程的错误信息:
exec > /application-data/sendUrl_exec.log 2>&1 set -x # 后续脚本内容...
Cron任务执行后查看sendUrl_exec.log,即可定位具体错误(如sendmail未找到、参数错误等)。
内容的提问来源于stack exchange,提问作者Peter VARGA
相关产品推荐
相关产品推荐

