运行 PHP 来自 cli 的脚本:php.ini memory_size 未考虑

run PHP script from cli : php.ini memory_size not taken into account

我正在尝试从命令行 运行 一个 php 脚本(magento reindexer 脚本)。该脚本消耗大量内存,因此出现以下错误:PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 72 bytes) in /home/karanta/www/karanta.fr/lib/Zend/Db/Adapter/Abstract.php on line 691

为了解决这个问题,我编辑了 /etc/php5/cli/php.ini 文件并设置了 memory_limit = 2048M.

为了检查配置,我 运行 一个包含来自 cli 的 phpinfo(); 的脚本,我看到:memory_limit => 2048M => 2048M,所以配置似乎被正确考虑了。 ini_get('memory_limit); 也 returns 2048M.

然而,当我重新运行 重建索引脚本时,我仍然得到 PHP Fatal error: Allowed memory size of 536870912 bytes exhausted,就好像 memory_limit 仍然是 512M。脚本无法完成,我不知道如何扩充 memory_limit 以允许脚本完成。

编辑:我还尝试将指令 ini_set("memory_limit", -1); 直接添加到 PHP 脚本中,但它仍然挂起相同的 PHP Fatal error: Allowed memory size of 536870912 bytes exhausted.

额外信息:

服务器是 ovh 运行ning Debian GNU/Linux 7.5 的专用机器,内存为 64GB!

php -v returns:

PHP 5.6.12-1 (cli) Copyright (c) 1997-2015 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

free -k -h 脚本执行期间 returns:

               total        used        free      shared  buff/cache     available
Mem:            62G        1,8G         48G         84M          12G         60G
Swap:          1,0G          0B        1,0G

ps -aux returns:

karanta  25568  5.6  0.0 229484 41824 pts/1    S    07:54   0:04 php shell/indexer.php --reindex catalog_url

按照@IgorGreg 的建议,我尝试使用Zend_Memory 设置内存限制。我写了这个 php 脚本,我从 cli 运行 替换了 shell/indexer.php 脚本。

<?php
require_once 'app/Mage.php';
$app = Mage::app('admin');
umask(0);
$memoryManager = Zend_Memory::factory('none');
$memoryManager->setMemoryLimit(-1);
$process = Mage::getModel('index/process')->load(3);
$process->reindexAll();
?>

仍然出现同样的错误。

设置memory_limit为-1表示没有内存限制。但是,如果您在 php.ini 或 .htaccess 中设置此值,它可能会在 运行 时间内被脚本覆盖。
为了确保它会生效,最好在脚本中使用ini_set("memory_limit", -1);
通常,在 php.ini 中将 memory_limit 设置为 -1 并不是一个好主意。它可能会导致您的系统在某些情况下挂起。

Magento 建立在 Zend framework 1 之上,它有自己的内存管理器。 documentation 说你可以像这样设置内存限制:

$memoryManager->setMemoryLimit(-1);

不需要是-1,可以是1,073,741,824,或者任何整数,以字节为单位。
不过我还没试过。

在Linux系统中,可以有三种独立的内存限制设置,一种用于Apache DSO模块php实例,一种用于命令行php实例,一种用于cgi php 实例.

每个安装都有自己的 php.ini 文件,例如 /etc/php5/apache2/php.ini/etc/php5/cli/php.ini 并且可能能够覆盖设置 memory_limit 关闭(通常发现在共享主机中)。

cli 的 php.ini 文件需要增加 memory_limit。

如果您使用 apc 缓存,可能会出现另一个问题。必须通过将以下内容添加到 apc 配置文件来启用它。

apc.enable-cli=1

如果您在 cPanel/WHM 下 运行 ,那么第三个麻烦来源是,由于实施了安全限制,可能会安装多个不同版本的 php。我必须联系我们的托管服务提供商才能 运行 那一个下来。尝试从出现故障的命令行中使用 which php 并确保它与可通过 cron 脚本访问的版本相同。该特定版本的 php.ini 文件也必须设置。

Magento 在 CLI 模式下解析 .htaccess 文件,如果发现内存限制或任何其他 PHP 设置,应用它们(是的,认真的....)

负责代码在shell/abstract.php:

/**
 * Parse .htaccess file and apply php settings to shell script
 *
 */
protected function _applyPhpVariables()
{
    $htaccess = $this->_getRootPath() . '.htaccess';
    if (file_exists($htaccess)) {
        // parse htaccess file
        $data = file_get_contents($htaccess);
        $matches = array();
        preg_match_all('#^\s+?php_value\s+([a-z_]+)\s+(.+)$#siUm', $data, $matches, PREG_SET_ORDER);
        if ($matches) {
            foreach ($matches as $match) {
                @ini_set($match[1], str_replace("\r", '', $match[2]));
            }
        }
        preg_match_all('#^\s+?php_flag\s+([a-z_]+)\s+(.+)$#siUm', $data, $matches, PREG_SET_ORDER);
        if ($matches) {
            foreach ($matches as $match) {
                @ini_set($match[1], str_replace("\r", '', $match[2]));
            }
        }
    }
}

解决方案

不要通过.htaccess设置内存限制和执行时间,使用php.ini或虚拟主机配置。

请按照以下步骤操作。

1。根据您的要求将以下内容更改为 .htaccess php_value memory_limit 256M => php_value memory_limit 2048M

  1. 与其一并重建索引,不如像
  2. 一样一个一个重建索引

php indexer.php --reindex catalog_product_price

需要通过 .htaccess 增加内存限制,因为您可以在 abstract.php 中看到它会引用 .htaccess 配置。

如果您还有任何疑问,请告诉我

谢谢