php怎么部署线上脚本_定时任务不执行是路径还是权限错【技巧】

11次阅读

crontab 中 php 脚本不执行的主因是路径、权限、环境变量和日志缺失;需用绝对路径、显式指定 php 解释器、检查用户权限、声明环境变量、重定向日志并手动重载。

php 怎么部署线上脚本_定时任务不执行是路径还是权限错【技巧】

crontab 里 php 脚本不执行,先看绝对路径有没有写错

Linux 的 crontab 默认工作目录是用户家目录(~),不是你的项目根目录。如果你在脚本里用 require 'config.php'file_get_contents('data/log.txt'),它会去家目录下找,而不是你期望的项目路径。

解决办法只有一条:所有文件引用都用绝对路径。

  • 在 crontab 中调用时,显式指定 PHP 解释器和脚本全路径:/usr/bin/php /var/www/myapp/scripts/clean_cache.php
  • 脚本内部也统一用 __DIR__dirname(__FILE__) 拼接依赖路径,比如:require __DIR__ . '/../config.php';
  • 别信相对路径 + chdir() 临时切换目录——cron 环境不可靠,chdir() 可能失败且无提示

php 命令行权限和 web 权限不是一回事

Web 服务器(如 nginx + php-fpm)跑脚本用的是 www-datanginx 用户,而 crontab 默认用当前登录用户(比如 ubuntu)。这两个用户对文件的读写权限很可能不同。

典型表现是:网页能跑通,定时任务报 Permission deniedfailed to open stream

立即学习 PHP 免费学习笔记(深入)”;

  • 检查脚本本身是否可执行:chmod +x /var/www/myapp/scripts/clean_cache.php(非必须,但建议)
  • 重点检查脚本要读写的文件 / 目录归属和权限,比如日志目录:ls -ld /var/www/myapp/logs/;确保 cron 所用用户有写权限
  • 如果必须用特定用户运行,不要在个人 crontab 里写,改用系统级 cron:sudo crontab -u www-data -e,然后加任务

环境变量缺失导致 php 找不到扩展或命令

crontab 不加载用户的 ~/.bashrc~/.profile,所以 PATH、PHP_INI_PATH、甚至某些扩展(如 pdo_mysql)可能在 cron 里不可用。

常见症状:脚本直接退出、报 Class not foundcommand not found: php,但手动执行完全正常。

  • 在 crontab 第一行加上环境声明:SHELL=/bin/bashPATH=/usr/local/bin:/usr/bin:/bin
  • 更稳妥的方式是,在命令前显式指定完整路径:/usr/bin/php -c /etc/php/8.1/cli/php.ini /var/www/myapp/scripts/clean_cache.php
  • 调试时加日志输出环境信息:/usr/bin/php -i | grep 'Loaded Configuration File|extension_dir' >> /tmp/cron_debug.log 2>&1

log 输出被吞掉,根本不知道哪一步挂了

crontab 默认把 stdout/stderr 丢进邮件系统(多数线上服务器没配 mail 服务),或者直接丢弃。不加重定向,等于“静默失败”。

  • 每条 cron 任务末尾必须加日志重定向:> /var/log/myapp/cron_clean.log 2>&1
  • 避免日志无限增长,加简单轮转逻辑(不用 logrotate 也可):0 2 * * * /usr/bin/php /var/www/myapp/scripts/clean_cache.php >> /var/log/myapp/cron_clean.log 2>&1 && tail -n 1000 /var/log/myapp/cron_clean.log > /var/log/myapp/cron_clean.log.tmp && mv /var/log/myapp/cron_clean.log.tmp /var/log/myapp/cron_clean.log
  • 别依赖 echovar_dump() —— 加 error_log('step 1 done', 3, '/tmp/cron_debug.log'); 更可靠,因为不受输出缓冲影响

最常被忽略的是:crontab 编辑保存后不会自动 reload,必须退出编辑器并确认没有语法错误(比如最后一行没换行符,某些版本会静默忽略整条任务)。改完务必执行 sudo systemctl status cron 看有没有报错,再查日志。

text=ZqhQzanResources