crontab执行失败时收不到邮件,因系统默认未配置mta;脚本终端能运行而crontab报“command not found”,因crontab的path极简且不加载shell配置;成功/失败均需通知时须用$?判断并强制输出,而非依赖mailto。

crontab 执行失败时,邮件根本收不到?
默认情况下,crontab 任务出错(比如命令不存在、路径错误、权限不足)会尝试发邮件给当前用户,但绝大多数 Linux 系统**根本没配本地邮件服务**(如 sendmail 或 postfix),结果就是:任务静默失败,你啥也不知道。
验证方式很简单:tail -f /var/log/cron 能看到执行记录,但查不到“邮件已发送”日志——说明邮件根本没发出去。
- 最稳妥的做法是**不依赖邮件**,改用日志重定向:
0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1 - 如果真要邮件通知,必须先确认系统有可用 MTA:
which sendmail或systemctl is-active postfix - 全局邮件接收人由
/etc/crontab中的MAILTO=root控制;用户级crontab -e可在文件顶部加MAILTO=your@domain.com(但仅当 MTA 存在且配置正确才有效)
为什么脚本在终端能跑,放进 crontab 就报 “command not found”?
因为 crontab 使用的是极简环境:PATH 默认只有 /usr/bin:/bin,不读取你的 ~/.bashrc 或 /etc/profile。你常用的 python3、jq、mysqldump 很可能不在这个 PATH 里。
- 查真实路径:
which python3→ 得到/usr/local/bin/python3,然后在 crontab 里写死:0 * * * * /usr/local/bin/python3 /home/user/script.py - 或统一补全环境变量:在
crontab -e文件开头加两行:PATH=/usr/local/bin:/usr/bin:/bin和SHELL=/bin/bash - 避免用别名(alias)或 shell 函数——crond 不解析它们
怎么让 cron 任务成功/失败都发通知?
crontab 本身不提供“成功回调”,但可以用 shell 逻辑兜底。关键不是靠 MAILTO,而是用命令退出状态($?)做判断。
- 基础写法:
0 3 * * * /path/to/task.sh && echo "OK $(date)" | mail -s "Task OK" admin@example.com || echo "FAIL $(date)" | mail -s "Task FAILED" admin@example.com - 更健壮的做法是封装成小脚本:
/opt/bin/wrap-and-notify.sh /path/to/task.sh "Daily Backup",里面处理日志、超时、重试和邮件模板 - 注意:
mail命令在 CentOS/RHEL 上常叫mailx,Ubuntu 上可能是bsd-mailx,先which mail mailx确认
为什么设置了 MAILTO,却只收到失败邮件,成功不通知?
这是 crontab 的设计行为:它**只在标准输出(stdout)或标准错误(stderr)有内容时才发邮件**。如果命令完全静默(比如 rm -f file 成功后无输出),哪怕执行成功,也不会触发邮件。
- 想强制成功也发信,必须让命令产生输出:
0 4 * * * /path/to/job.sh && echo "Done at $(date)" - 或者用
echo强制刷 stdout:0 4 * * * /path/to/job.sh; echo "Job finished" - 别依赖“没报错=成功”——网络超时、返回码非 0 但被忽略、部分数据写入失败等情况,都可能让你误判
真正麻烦的不是配置 MAILTO,而是 crond 运行时的环境隔离、路径盲区和静默机制——这些地方不手动验证,光看文档永远以为“应该能行”。










