crontab调用PHP脚本失败主因是环境差异:需用绝对路径调用php、切换工作目录、显式加载.env、重定向日志并确保权限与超时设置正确。

crontab 调用 PHP 脚本失败,八成是环境或路径没对齐——不是脚本写得不对,而是 cron 启动时根本找不到 php、读不到 $_ENV、连 require 的相对路径都会崩。
为什么 crontab 里执行 PHP 脚本总报 “Command not found” 或空白输出?
因为 cron 使用的是极简 shell 环境(通常是 /bin/sh),$PATH 和你终端里看到的完全不同,which php 在 cron 里大概率返回空。同时,当前工作目录默认是 root 用户的家目录,不是你的项目根目录。
- 务必用绝对路径调用
php:先运行which php查出真实路径(如/usr/bin/php或/opt/homebrew/bin/php),crontab 里不能写php script.php,得写/usr/bin/php /var/www/myapp/artisan schedule:run - 脚本内所有
require、file_get_contents、日志路径等,必须用绝对路径,或在脚本开头用chdir(__DIR__);切到脚本所在目录 - 避免依赖
$_SERVER或$_ENV中的 Web 环境变量(比如 Laravel 的APP_ENV),改用getenv('APP_ENV') || 'production'并显式加载 .env 文件(如Dotenv\Dotenv::createImmutable(__DIR__)->load();)
如何让 Laravel 的 schedule:run 在 crontab 中稳定触发?
Laravel 官方推荐只配一条 cron,让它每分钟拉一次调度器;但很多人直接把 php artisan schedule:run 塞进 crontab 却发现任务不执行——常见原因是没指定应用根目录或未加载环境。
- 在项目根目录下运行
which php和pwd,拿到两个关键路径:/usr/bin/php和/var/www/laravel-app - 编辑 crontab:
crontab -e,添加这一行(注意换行符和空格):* * * * * cd /var/www/laravel-app && /usr/bin/php artisan schedule:run >> /var/log/laravel-schedule.log 2>&1
- 日志重定向很重要:
>>记录标准输出,2>&1把错误也捕获进来,否则失败了你也看不见 - 别用
sudo crontab -e(除非你真想以 root 身份跑),普通用户 crontab 更安全;确认 crond 服务在运行:sudo systemctl status cron(Ubuntu/Debian)或sudo systemctl status crond(CentOS/RHEL)
PHP 脚本被 crontab 执行时权限或超时怎么办?
脚本可能因用户权限不足(比如写日志文件)、内存限制(CLI 默认 memory_limit 可能比 Web 小)、或执行时间过长被系统 kill。
立即学习“PHP免费学习笔记(深入)”;
- 检查脚本属主和目标目录权限:
ls -l /var/www/myapp/storage/logs/,确保 cron 运行用户(如www-data或你的用户名)有写权限 - 在脚本开头加
ini_set('memory_limit', '512M');或用 CLI 参数强制指定:/usr/bin/php -d memory_limit=512M /path/to/script.php - 如果脚本可能卡住,加上超时控制:
timeout 300 /usr/bin/php /path/to/script.php(Linux),macOS 需装gtimeout(via Homebrew) - 敏感操作(如数据库备份)建议用
mysqldump命令本身加--defaults-file指定配置,而不是靠 PHP 连接——减少 PHP 层依赖和超时风险
最常被忽略的一点:修改完 crontab 后,不需要重启 cron 服务,但要确认你编辑的是**正确用户的 crontab**(crontab -u www-data -e 和 crontab -e 是两回事),且时间格式里星号之间**必须是空格,不能是 Tab**——一个空格错位,整行就静默失效。











