crontab调用PHP脚本失败主因是环境差异:需用绝对路径调用php、切换工作目录、显式加载.env、重定向日志并确保权限与超时设置正确。
crontab 调用 PHP 脚本失败,八成是环境或路径没对齐——不是脚本写得不对,而是 cron 启动时根本找不到 php、读不到 $_ENV、连 require 的相对路径都会崩。
因为 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();)schedule:run 在 crontab 中稳定触发?Laravel 官方推荐只配一条 cron,让它每分钟拉一次调度器;但很多人直接把 php artisan schedule:run 塞进 crontab 却发现任务不执行——常见原因是没指定应用根目录或未加载环境。
which php 和 pwd,拿到两个关键路径:/usr/bin/php 和 /var/www/laravel-app
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)脚本可能因用户权限不足(比如写日志文件)、内存限制(CLI 默认 memory_limit 可能比 Web 小)、或执行时间过长被系统 kill。
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**——一个空格错位,整行就静默失效。