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

Docker容器中Symfony Worker日志无法输出至supervisord/runit/stdout求助

解决Symfony Worker在Docker容器中Monolog日志无法输出到stdout的问题

我之前处理过类似的场景,结合Symfony Monolog的配置逻辑、Docker的输出捕获机制,以及supervisord/runit的特性,给你几个具体的排查和解决方向:

1. 修复Monolog Handler的通道匹配问题

你的console handler配置里排除了console通道,而Symfony Messenger Worker(默认的Symfony Worker实现)的日志默认会打到console通道。这就导致Worker的日志直接被console handler忽略,而如果main handler还是指向文件路径(哪怕你改成了php://stdout),也要确认它的channels是否包含Worker的日志通道。

推荐两种调整方式:

  • 给Worker单独配置专属Handler:
handlers:
  main:
    type: stream
    path: "%kernel.logs_dir%/%kernel.environment%.log"
    level: debug
    channels: ["!event"]
  worker_stdout:
    type: stream
    path: php://stdout
    level: debug
    channels: ["console"] # 专门捕获Worker的console通道日志
  console:
    type: console
    process_psr_3_messages: false
    channels: ["!event", "!doctrine", "!console"]
  • 修改现有Console Handler的通道规则:
    去掉console通道的排除,同时开启process_psr_3_messages确保PSR日志被处理:
console:
  type: console
  process_psr_3_messages: true
  channels: ["!event", "!doctrine"]

2. 关闭Monolog的输出缓冲

长生命周期的Worker进程中,PHP的输出缓冲会导致Monolog写入php://stdout的内容被滞留,无法即时输出到容器的stdout。给Stream Handler添加buffering: false参数强制实时输出:

handlers:
  worker_stdout:
    type: stream
    path: php://stdout
    level: debug
    channels: ["console"]
    buffering: false # 关键:关闭缓冲,日志实时输出

3. 确保Supervisord/Runit正确捕获输出

针对Supervisord:

检查你的program配置,必须开启标准输出/错误的重定向,并且禁用日志文件大小限制:

[program:symfony-worker]
command=php /var/www/html/bin/console messenger:consume async -vv
process_name=%(program_name)s_%(process_num)02d
numprocs=1
autostart=true
autorestart=true
user=www-data
redirect_stderr=true # 将stderr合并到stdout,方便统一捕获
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0 # 不切割日志,持续输出到stdout
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
catch_workers_output=true # 强制捕获子进程的所有输出

针对Runit:

确保你的run脚本使用exec命令启动Worker,这样Worker进程会直接替换shell进程,所有输出都会被runit的日志捕获机制接管:

#!/bin/sh
cd /var/www/html
# 使用exec让Worker成为主进程,避免输出被shell拦截
exec php bin/console messenger:consume async -vv

4. 调整PHP的输出配置

在PHP层面禁用输出缓冲,确保日志能即时输出:

  • 在php.ini中设置:
output_buffering = Off
implicit_flush = On
  • 或者在启动Worker时通过命令行参数临时设置:
php -d output_buffering=0 bin/console messenger:consume async -vv

5. 验证Worker的Logger注入是否正确

检查你的Worker Handler类是否正确注入了Psr\Log\LoggerInterface,避免使用自定义的、未关联Monolog配置的日志实例:

use Psr\Log\LoggerInterface;

class OrderProcessingHandler
{
    private $logger;

    // 确保注入的是Symfony容器提供的Logger服务
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function __invoke(ProcessOrder $message)
    {
        // 测试日志输出
        $this->logger->info('开始处理订单', ['order_id' => $message->getOrderId()]);
        // ...业务逻辑
    }
}

6. 快速验证Monolog配置是否生效

可以在Worker中临时添加调试代码,确认Handler的配置是否正确加载:

// 在Worker Handler的__invoke方法中临时添加
$handlers = $this->logger->getHandlers();
foreach ($handlers as $handler) {
    if ($handler instanceof \Monolog\Handler\StreamHandler) {
        echo "当前Handler路径: " . $handler->getUrl() . "\n";
        echo "当前Handler监听的通道: " . implode(',', $handler->getChannels()) . "\n";
    }
}

运行Worker后,查看stdout输出,就能确认Handler的路径和通道是否符合预期。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:50:45