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

在Docker容器中查看Laravel命令日志及解决Sitemap生成故障

问题背景

在AWS ECS上以容器化方式运行Laravel应用,容器内同时运行php-fpm和Nginx。新增了生成sitemap.xml的Artisan命令,但容器运行近一周仍未生成目标文件,访问mywebsite.co.uk/sitemap.xml无响应。已配置Sentry且能正常上报异常,但无该命令相关报错;容器日志仅显示Nginx访问日志,遍寻容器文件系统也找不到PHP日志,怀疑命令静默失败但无法排查。

相关配置信息

Dockerfile 配置

ENTRYPOINT 脚本:

nginx -g "daemon off;" &

echo "--- Clearing artisan cache"
yes | php artisan config:clear

echo "--- Running migrations"
yes | php artisan migrate

echo "--- Seeding database"
yes | php artisan db:seed

echo "--- Running final container command"
exec "$@"

CMD 配置:

CMD ["php-fpm", "--nodaemonize", "--force-stderr"]

GenerateSitemap 命令代码

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Spatie\Sitemap\SitemapGenerator;

class GenerateSitemap extends Command
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $signature = 'sitemap:generate';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate the sitemap.';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // modify this to your own needs
        SitemapGenerator::create(config('app.url'))
            ->writeToFile(public_path('sitemap.xml'));
    }
}

定时任务列表输出

执行php artisan schedule:list的结果:

0 0 * * *  php artisan sitemap:generate ........ Next Due: 12 hours from now
排查思路

一、命令本身问题排查

  • 手动执行命令验证:进入容器直接运行php artisan sitemap:generate,观察是否有报错输出,以及是否生成sitemap.xml文件。如果手动执行也失败,直接定位命令本身问题;如果手动成功,说明定时任务未触发或执行环境有差异。
  • 检查文件权限:确认public目录的读写权限,容器运行用户是否有写入public_path('sitemap.xml')的权限。可在命令的handle方法开头加入dd(is_writable(public_path())),手动执行查看结果。
  • 验证config('app.url')有效性:确认app.url配置是否正确,且能被容器内部访问。SitemapGenerator需要从容器内部抓取应用页面,若容器内无法解析或访问该URL,会导致生成失败。可替换为容器内部可访问的地址(如http://localhost)测试。
  • 捕获命令异常并输出:修改命令代码,主动捕获异常并打印详细信息,同时确保Sentry能捕获到异常:
    public function handle()
    {
        try {
            SitemapGenerator::create(config('app.url'))
                ->writeToFile(public_path('sitemap.xml'));
            $this->info('Sitemap generated successfully');
        } catch (\Exception $e) {
            $this->error('Failed to generate sitemap: ' . $e->getMessage());
            throw $e;
        }
    }
    
  • 确认定时任务调度进程状态:Laravel定时任务依赖php artisan schedule:run每分钟执行一次,但当前容器的CMD仅启动php-fpm,未启动任务调度进程。需检查是否有单独的调度容器,或通过Supervisor等工具在当前容器中同时运行php-fpm和schedule:run——这很可能是定时任务未执行的核心原因。

二、PHP日志排查

  • 配置PHP错误日志:修改php-fpm配置文件(如www.conf),设置error_log = /var/log/php-fpm.log,同时在php.ini中开启log_errors = On、error_reporting = E_ALL,确保错误信息被记录,并保证容器用户有日志目录的写入权限。
  • 将命令输出定向到容器日志:在App\Console\Kernel的schedule方法中,把命令输出重定向到容器标准输出/错误,让容器日志能捕获到命令输出:
    $schedule->command('sitemap:generate')
             ->daily()
             ->sendOutputTo('/proc/self/fd/2'); // 输出到stderr
    
  • 临时写入本地日志文件:在命令的handle方法中,将执行日志写入容器内可访问的文件,方便排查:
    $logPath = '/var/log/sitemap.log';
    file_put_contents($logPath, date('Y-m-d H:i:s') . ' Command started' . PHP_EOL, FILE_APPEND);
    try {
        // 原命令逻辑
        file_put_contents($logPath, date('Y-m-d H:i:s') . ' Sitemap generated successfully' . PHP_EOL, FILE_APPEND);
    } catch (\Exception $e) {
        file_put_contents($logPath, date('Y-m-d H:i:s') . ' Error: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
    }
    
  • 检查容器日志捕获范围:当前ENTRYPOINT中Nginx后台运行,最终exec php-fpm,容器日志仅捕获php-fpm的输出。若定时任务通过其他方式启动,其输出可能未被捕获,需确保定时任务输出定向到stdout/stderr,或单独写入可访问的日志文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 21:50:26