我正在运行一个控制台进程,该进程侦听事件并向控制台写入.
以指示进度。这可能会运行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()
行,希望这会有所帮助,但它并不能解决问题。
查看Symfony ConsoleOutput代码,它总是在执行fopen($outputStream, 'w')
,但我找不到它再次关闭它的任何位置
所以你可以在你的功能结束时自己关闭它:
$resource = $output->getStream();
fclose($resource);
或者只尝试实例化一次,然后重用它。
注意:实际上,我认为如果不再引用匿名函数,垃圾回收应该关闭它。很难,我不知道static::listen
方法在做什么,所以可能值得尝试手动关闭它。