致命错误使用Symfony控制台时打开的文件太多

时间:2014-10-14 11:31:29

标签: php symfony laravel-4

我正在运行一个侦听事件的控制台进程,并将.写入控制台以指示进度。这可以运行10-15分钟,但是大约10分钟后,我得到以下一系列致命的控制台错误:

[2014-10-14 11:13:49] local.ERROR: 500 - fopen(php://stderr): failed to open stream: operation failed @ /
exception 'ErrorException' with message 'fopen(php://stderr): failed to open stream: operation failed' in /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php:53
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleError(2, 'fopen(php://std...', '/vagrant/www/te...', 53, Array)
#1 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php(53): fopen('php://stderr', 'w')
#2 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(262): Symfony\Component\Console\Output\ConsoleOutput->__construct()
#3 [internal function]: eComEvo\TaskRunner\TaskRunner::eComEvo\TaskRunner\Traits\{closure}('.', 280, Array)
#4 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): call_user_func_array(Object(Closure), Array)
#5 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/vendor/illuminate/support/Illuminate/Support/Facades/Facade.php(211): Illuminate\Events\Dispatcher->fire('task.group.prog...', Array)
#6 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(92): Illuminate\Support\Facades\Facade::__callStatic('fire', Array)
#7 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(92): Illuminate\Support\Facades\Event::fire('task.group.prog...', Array)
#8 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(205): eComEvo\TaskRunner\TaskRunner::event('progress', '.', 280, '423403-23463321-604...', 'event')
#9 /vagrant/www/test.dev/laravel/app/models/TaskRunner.php(280): eComEvo\TaskRunner\TaskRunner::progress('.', 280, '2423-521354...')
#10 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Commands/TaskRunnerImportOrdersCommand.php(128): TaskRunner::import('15', NULL, Array, '16', '4')
#11 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php(112): eComEvo\TaskRunner\Commands\TaskRunnerImportOrdersCommand->fire()
#12 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Command/Command.php(252): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#13 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php(100): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#14 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(889): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#15 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(193): Symfony\Component\Console\Application->doRunCommand(Object(eComEvo\TaskRunner\Commands\TaskRunnerImportOrdersCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#16 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(124): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#17 /vagrant/www/test.dev/laravel/artisan(59): Symfony\Component\Console\Application->run()
#18 {main} [] []
[2014-10-14 11:13:50] local.ERROR: 500 - proc_open(): unable to create pipe Too many open files @ /
exception 'ErrorException' with message 'proc_open(): unable to create pipe Too many open files' in /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php:983
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleError(2, 'proc_open(): un...', '/vagrant/www/te...', 983, Array)
#1 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(983): proc_open('stty -a | grep ...', Array, NULL, NULL, NULL, Array)
#2 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(799): Symfony\Component\Console\Application->getSttyColumns()
#3 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(760): Symfony\Component\Console\Application->getTerminalDimensions()
#4 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(690): Symfony\Component\Console\Application->getTerminalWidth()
#5 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Console/Application.php(201): Symfony\Component\Console\Application->renderException(Object(ErrorException), Object(Symfony\Component\Console\Output\StreamOutput))
#6 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(131): Illuminate\Console\Application->renderException(Object(ErrorException), Object(Symfony\Component\Console\Output\StreamOutput))
#7 /vagrant/www/test.dev/laravel/artisan(59): Symfony\Component\Console\Application->run()
#8 {main} [] []

以下是10分钟后触发这些错误的代码:

static::listen(
    'progress',
    function ($indicator = '.', $line = null, $id = 0) {
        $output = new \Symfony\Component\Console\Output\ConsoleOutput();

        $extra = [];

        if (static::$debug > 2) {
            if (!empty($line) && $line !== true)
                $extra[] = "line=$line";

            if (!empty($id)) {
                if (is_array($id))
                    $id = implode(',', $id);

                if (!empty($id))
                    $extra[] = "ID=$id";
            }
        }

        if (!empty($extra))
            $output->writeln('[' . implode(', ', $extra) . ']');
        elseif ($line === true)
            $output->writeln("\n$indicator");
        else
            $output->write($indicator);

        static $gc_count = 0;

        $gc_count++;

        if ($gc_count > 25) {
            $gc_count = 0;

            gc_collect_cycles();
        }
    },
    'event'
);

我已经四处寻找解决方案,所以我添加了gc_collect_cycles()行,希望这会有所帮助,但它无法解决问题。

1 个答案:

答案 0 :(得分:0)

查看Symfony ConsoleOutput code它始终在执行fopen($outputStream, 'w'),但我无法找到它再次关闭它的任何内容。
因此,您可以尝试在功能结束时自行关闭它:

$resource = $output->getStream();
fclose($resource);

或者只尝试将其实例化一次并重新使用它。

注意:实际上我认为如果不再引用匿名函数,垃圾收集应该关闭它。很难我不知道static::listen方法在做什么,所以尝试手动关闭它可能是值得的。