crontab调用php发邮件失败的根本原因是环境变量差异,需用绝对路径、设全path、重定向日志、避免web变量依赖;mail()需正确配置sendmail_path和邮件头;phpmailer要确保autoload路径正确;时区须统一,加锁防重复。

crontab 调用 PHP 脚本发邮件,为什么死活不执行?
常见现象是:手动运行 php /path/to/send.php 没问题,但加进 crontab 就收不到邮件,日志里也没报错。根本原因是环境变量不同——crontab 默认只有极简 PATH(通常不含 /usr/local/bin 或 /opt/homebrew/bin),PHP、sendmail、SSL 证书路径全可能找不到。
- 务必在 crontab 条目里写绝对路径:
/usr/bin/php /var/www/html/send.php,别用php简写 - 加环境变量前缀更稳妥:
PATH=/usr/local/bin:/usr/bin:/bin /usr/bin/php /var/www/html/send.php - 重定向输出查问题:
> /tmp/send.log 2>&1,否则错误全丢进黑洞 - PHP 脚本里别依赖
$_SERVER['DOCUMENT_ROOT']这类 Web 环境变量,改用__DIR__或硬编码路径
PHP mail() 函数发不出去?先确认这三件事
mail() 表面调用成功,实际被拒收或进垃圾箱,90% 是配置没对。它不校验邮箱真实性,也不返回 SMTP 错误细节,纯靠系统本地 MTA(如 sendmail/postfix)中转。
- 检查
sendmail_path:在php.ini里确认sendmail_path = "/usr/sbin/sendmail -t -i",注意-t(读取邮件头里的 To)和-i(忽略单个点号结束)不能少 - 发信头必须规范:至少含
From:和Subject:,且From域名得和服务器反向 DNS 匹配,否则 Gmail 直接拒收 - 别用
mail()发大量邮件:无队列、无重试、无退信处理,一卡全崩;小量通知(比如每日备份报告)还凑合
用 PHPMailer 发定时邮件,为什么 cron 下报 Class not found?
脚本在浏览器能跑,cron 里提示 Class 'PHPMailer\PHPMailer\PHPMailer' 找不到,本质是自动加载器没触发——crontab 不走 Web 服务器的 autoloader(比如 Composer 的 vendor/autoload.php 路径错了)。
- 在脚本开头强制引入:
require_once '/var/www/html/vendor/autoload.php';,路径必须绝对 - 如果用相对路径
require_once __DIR__.'/vendor/autoload.php';,确保 cron 执行时工作目录是脚本所在目录(加cd /var/www/html &&前缀) - SMTP 登录失败常被吞成静默失败:给
$mail->SMTPDebug = 2;并重定向输出,才能看到Authentication failed这类关键信息 - 别把密码写死在脚本里;用环境变量或独立配置文件(权限设为
600),避免被 web 可读
每天凌晨 2 点发邮件,crontab 时间格式怎么写才不翻车?
看似简单,但时区、分钟偏移、系统时间同步都会导致“说好 2 点发,结果 1:59 或 2:01 才动”。Linux 系统默认用系统本地时区,而 PHP 脚本里若调了 date_default_timezone_set('UTC'),时间逻辑就乱套了。
立即学习“PHP免费学习笔记(深入)”;
- 统一用系统时区:查
timedatectl status,确保服务器时区是你期望的(比如Asia/Shanghai) - crontab 写法:
0 2 * * * /usr/bin/php /var/www/html/daily-report.php—— 注意是「第 0 分钟」,不是2 0 * * *(那是凌晨 0 点) - 测试时别等一天:先改成
* * * * *(每分钟一次),确认能跑通再改回正式时间 - 加锁防重复:同一任务若执行超时(比如网络卡住),下次 cron 到点又起一个,邮件发两遍。用
if [ ! -f /tmp/daily-report.lock ]; then touch /tmp/daily-report.lock; php ...; rm /tmp/daily-report.lock; fi
真正麻烦的从来不是写几行发信代码,而是让 cron 在无人值守时稳定跑满一年——路径、时区、权限、锁、日志,漏一个,半夜告警就是它。











