You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在DigitalOcean通过crontab运行PHPSpreadsheet无法保存文件的问题

Crontab运行PHP脚本异常:邮件中断+Excel无法保存的排查方案

问题重现

通过浏览器URL运行PHP脚本时,所有邮件发送成功,XLSX文件能正常保存到指定路径,执行流畅;但通过crontab定时运行时,仅能发送前两封邮件,最后一封发送失败,同时XLSX文件无法保存,且无报错日志输出。

服务器环境

  • 服务器:DigitalOcean
  • PHP版本:8.2.13

依赖配置(composer.json)

{
    "require": {
        "phpoffice/phpspreadsheet": "^1.29",
        "phpmailer/phpmailer": "^6.9.1"
    }
}

涉事脚本代码

<?php

require dirname(dirname(__FILE__)).'/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
include dirname(dirname(__FILE__)) . '/includes/mail.php';

// 发送邮件通知:"STARTED CRON"

$spreadsheet = new Spreadsheet();
$newsheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, "My first sheet");
$spreadsheet->addSheet($newsheet);

$activesheet = $spreadsheet->setActiveSheetIndexByName("My first sheet");
$activesheet->getTabColor()->setRGB("FF0000");
$activesheet->setCellValue("A1", "Test");
$activesheet->setCellValue("A2", "Some numbers...");
$activesheet->setCellValue("A3", 1);
$activesheet->setCellValue("A4", 2);
$activesheet->setCellValue("A5", "=SUM(A3:A4)");

$activesheet->getStyle("A1")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
$activesheet->getStyle("A1")->getFill()->getStartColor()->setARGB("FFC6EFCE"); // 浅绿色

// 发送邮件通知:"SET THE DATA"

$destinationfile = "/folder/to/file/TEST_FILE.xlsx";
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
$writer->setPreCalculateFormulas(false);
$writer->save($destinationfile);

// 发送邮件通知:"FINISHED CRON"

排查与修复方案

1. 修正路径与权限问题

Crontab默认工作目录是用户主目录,不是脚本所在目录,容易导致路径解析错误:

  • 将脚本中所有相对路径替换为绝对路径,比如确认/folder/to/file/TEST_FILE.xlsx是服务器真实存在的完整路径,避免依赖dirname(__FILE__)组合解析。
  • 检查目标目录权限:执行chmod 755 /folder/to/file/确保目录可读写,若crontab以特定用户运行,执行chown username:username /folder/to/file/调整目录所有者。

2. 强制捕获错误日志

脚本无错误捕获机制,crontab的错误不会默认输出,需手动添加日志记录:
修改脚本关键位置,添加错误捕获:

// 在$writer->save()前添加
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', '/绝对路径/to/error.log'); // 写死日志文件绝对路径

try {
    $writer->save($destinationfile);
    // 发送"FINISHED CRON"邮件
} catch (\Exception $e) {
    error_log('Excel保存失败: ' . $e->getMessage());
    // 新增错误通知邮件
    sendMail('脚本执行失败', $e->getMessage()); // 调用mail.php中的发送函数
}

同时修改crontab命令,强制输出所有日志:

* * * * * php /绝对路径/to/your/script.php >> /绝对路径/to/cron.log 2>&1

3. 对齐PHP CLI与FPM环境配置

浏览器用PHP-FPM,crontab用PHP CLI,两者配置可能不一致:

  • 执行php -v确认CLI版本为8.2.13,和FPM环境一致。
  • 执行php -m检查是否缺少PhpSpreadsheet依赖的扩展(如zip、xml),缺失则安装对应扩展。
  • 对比CLI和FPM的php.ini配置,确保allow_url_fopen等必要参数开启状态一致。

4. 排查PHPMailer CLI环境问题

最后一封邮件失败大概率是脚本崩溃导致后续代码未执行,也可能是邮件配置问题:

  • 确认mail.php中的SMTP证书文件使用绝对路径,CLI环境无法识别相对路径的证书。
  • 在mail.php中添加日志,记录每一封邮件的发送状态,排查是否存在资源未释放导致的发送阻塞。

内容的提问来源于stack exchange,提问作者Jo H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:52:35