6

我已经构建了一个命令来触发通过 Internet 下载文件,但是由于这些文件需要由另一个组件处理,我们需要确保每个已下载且在过去 10 秒内未修改的文件是正确的视频并且没有损坏/部分下载。

出于这个原因,我们需要找到一种方法来捕获 CTRL+C 或命令终止并清理任何尚未成功下载的适用文件。

到目前为止,这是我尝试使用symfony/consoleand的方法symfony/event-dispatcher

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

require_once(__DIR__ . '/../vendor/autoload.php');

use Symfony\Component\Console\Application;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;
use ImportExport\Console\ImportCommand;
use Monolog\Logger;

$dotenv = new Dotenv\Dotenv(__DIR__ . '/../');
$dotenv->load();

$logger = new Logger('console');

$dispatcher = new EventDispatcher();
$dispatcher->addListener(ConsoleEvents::TERMINATE, function (ConsoleTerminateEvent $event) {
    // gets the command that has been executed
    $command = $event->getCommand();

    var_dump($command);
});

$application = new Application("Import-Export System", 'v0.1.0-ALPHA');
$application->add(new ImportCommand($logger));
$application->setDispatcher($dispatcher);
$application->run();

但是var_dump(),如果我执行 CTRL+C,则永远不会在控制台中显示。

建议?

4

2 回答 2

5

当您执行 CTRL+C 时,实际上SIGINT是正在发送,而不是SIGTERM. 我能想到的最好方法是使用http://php.net/manual/en/function.pcntl-signal.php注册处理程序并使用 发送信号pcntl_signal_dispatch,例如:

pcntl_signal(SIGINT,'sigIntHandler');

function sigIntHandler() {
  // Do some stuff
}

当然,您需要根据自己的需要进行调整。请注意,您还可以遵循命令中的类方法,因此您可以例如使用泛型创建一个 AbstractCommandsigIntHandler()并将其注册到构造函数中:

pcntl_signal(SIGINT, [$this, 'sigIntHandler']);

然后pcntl_signal_dispatch()例如在命令的循环中使用(需要在每次迭代中调用它)。

于 2018-02-27T09:23:04.633 回答
0

从 Symfony 5.2 开始,它是一个原生功能:https ://symfony.com/blog/new-in-symfony-5-2-console-signals

实现一个接口(SignalableCommandInterface),订阅信号,并处理它们:

public function handleSignal(int $signal)
{
    if (SIGINT === $signal) {
        // ...
    }

    // ...
}
于 2021-10-25T14:01:30.760 回答