【问题标题】:Symfony command not reaching execution when run by croncron 运行时 Symfony 命令未执行
【发布时间】:2019-03-28 23:04:14
【问题描述】:

我在 Symfony 4 中构建了一个命令,它在从 CLI 运行时运行良好,但在通过 cron 运行时不执行。控制台命令正在运行,没有抛出任何错误。

我什至在execute 中抛出了一个,它并没有失败/出错:

public function execute(InputInterface $input, OutputInterface $output): void
{
    throw new \Exception('I am doing something');
}

我的完整命令如下所示并且是自动连线的:

<?php declare(strict_types = 1);

namespace CRMInterface\Command\Customer;

use CRMInterface\Service\Customer\CustomerSyncService;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class CustomerSyncCommand extends Command
{
    const COMMAND_NAME = 'crm:sync:customer';

    /**
     * @var CustomerSyncService
     */
    private $syncService;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @param CustomerSyncService $syncService
     * @param LoggerInterface $logger
     */
    public function __construct(CustomerSyncService $syncService, LoggerInterface $logger)
    {
        parent::__construct(self::COMMAND_NAME);
        $this->syncService = $syncService;
        $this->logger = $logger;
    }

    protected function configure()
    {
        $this
            ->setName(self::COMMAND_NAME)
            ->setDescription('Processes outstanding portal sync tasks');
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return void
     */
    public function execute(InputInterface $input, OutputInterface $output): void
    {
        $this->logger->info('Syncing customers...');
        try {
            $this->syncService->sync();
            $this->logger->info('Customer sync complete.');
        } catch (\Exception $e) {
            $this->logger->error('Customer sync failed: ' . $e->getMessage());
        }
    }
}

我的 cron 工作如下:

*/3 * * * * www-data cd /var/www/html && /usr/local/bin/php bin/console crm:sync:customer --env=prod

此设置适用于我运行的 Symfony 3 应用程序和 Symfony 2.8 应用程序,但不适用于 4,它让我发疯。

我的bin/console 如下 - 我已经删除了与 APP_ENV 相关的内容,因为在我的情况下它是多余的,并且由于 cron 中缺少环境变量而失败。

#!/usr/bin/env php
<?php

use CRMInterface\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;

set_time_limit(0);

require __DIR__.'/../vendor/autoload.php';

if (!class_exists(Application::class)) {
    throw new \RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
}

$input = new ArgvInput();
$env = $input->getParameterOption(['--env', '-e'], $_ENV['APP_ENV'] ?? 'dev');
$debug = ($_ENV['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption(['--no-debug', '']);

if ($debug) {
    umask(0000);

    if (class_exists(Debug::class)) {
        Debug::enable();
    }
}

$kernel = new Kernel($env, $debug);
$application = new Application($kernel);
$application->run($input);

谁能指出正确的方向,为什么命令正在运行但没有开始执行?

就好像它只是在没有命令的情况下运行bin/console...可能与延迟加载有关吗?

【问题讨论】:

  • 手动调用bin/console crm:sync:customer --env=prod时是否运行?
  • @Tomasz - 是的 - 完美运行
  • 您可以 grep syslog 处理 cron 错误,但我看到在 crontab 行中您有 (...) www-data cd &amp;&amp; (...) 我相信由于未定义的命令而失败
  • 我会尝试运行 cron 任务:*/3 * * * * /usr/local/bin/php /var/www/html/bin/console crm:sync:customer --env=prod
  • @Tomasz 我设置了系统日志,但它只是显示它运行了 - 没有发现错误。我也知道它正在访问bin/console 文件,因为它正在监控中出现。当我在该文件中添加一条语句以引发异常时,如果命令名称为 crm:sync:customer,则引发该异常...

标签: php symfony cron


【解决方案1】:

对于那些有类似问题的命令没有执行没有错误,请检查 cron 是否可以访问您的应用程序使用的所有环境变量。

在这种情况下,有一个异常被抛出,但被 Symfony Application 类捕获。 Environment variable not found: "ELASTICSEARCH_INDEX".。不幸的是,它只是继续运行,就好像它已经运行了一样。 (可能会在回购中产生问题)。

对于基于 Ubuntu 的 apache 容器上的 Docker,解决方案相当简单 - 在入口点脚本中添加一行以将环境变量写入 /etc/environment 文件:

FROM php:7.2
EXPOSE 80 443
CMD ["sh", "./.docker/run.sh"]

运行.sh:

#!/usr/bin/env bash

printenv | grep -v "no_proxy" >> /etc/environment \
    && /etc/init.d/cron start \
    && apache2-foreground

【讨论】:

  • 我这辈子都无法在一个新项目中复制它以制造一个关于它的问题,所以这看起来很前卫。
【解决方案2】:

与上一个答案类似,但请确保将 cron 作业添加到正确的用户。

示例:crontab -u www-data -e 通过更新或添加来编辑 cron 作业

*/3 * * * * /usr/local/bin/php /var/www/html/bin/console crm:sync:customer --env=prod

您可以在命令上添加一些测试,如下所示

0 * * * * if [ -f /var/www/html/bin/console ]; 然后 /var/www/html/bin/console crm:sync:customer --env=prod >> /var/log/symfony/crm.log; else echo '找不到控制台'

/var/log/symfony/crm.log; fi >/dev/null 2>&1

【讨论】: