【问题标题】:run PHP script from cli : php.ini memory_size not taken into account从 cli 运行 PHP 脚本:未考虑 php.ini memory_size
【发布时间】:2015-09-13 08:38:23
【问题描述】:

我正在尝试从命令行运行 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); 也返回 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 的专用机器,运行 Debian GNU/Linux 7.5 和 64GB RAM!

php -v 返回:

PHP 5.6.12-1 (cli) 版权所有 (c) 1997-2015 The PHP Group Zend Engine v2.6.0,版权所有 (c) 1998-2015 Zend Technologies 使用 Zend OPcache v7.0.6-dev,版权所有 (c) 1999-2015,由 Zend Technologies 提供

free -k -h在脚本执行期间返回:

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

ps -aux 返回:

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 设置内存限制。我编写了这个从 cli 运行的 php 脚本来代替 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();
?>

仍然遇到同样的错误。

【问题讨论】:

    标签: php magento command-line-interface memory-limit reindex


    【解决方案1】:

    CLI 模式下的 Magento 解析 .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或者虚拟主机配置。

    【讨论】:

    • 太棒了,索引器脚本不再达到内存限制!但是,重新索引仍然没有成功完成,它现在卡住了(进程的 cpu 为 0%,没有任何反应)。我已经尝试终止进程并重新启动重新索引脚本,同样的事情发生了。我怀疑一个大的 MySQL 查询阻止了重新索引,这可能吗?知道如何调试吗?
    • 杀死进程后你应该删除var/locks中的锁文件。要监控 MySQL,您可以使用 mtop 工具或仅使用 SHOW PROCESSLIST;
    • 是的,由于 DELETE FROM 'core_url_rewrite' WHERE (url_rewrite_id IN('5498439', '5498441', '5498443', '5498445', ... 等查询超时,重新索引会卡住。我已经将innodb_lock_wait_timeout 设置为1000 但这还不够!截断core_url_rewrite 表会解决这个问题吗?
    • 可能,有一段时间。但是,如果您有自定义 URL 重写,请不要这样做,它们会丢失。 Magento CE 的 URL 索引是一团糟,更多信息在这里:magento.stackexchange.com/questions/17553/…
    【解决方案2】:

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

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

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

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

    apc.enable-cli=1
    

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

    【讨论】:

    • 当我从命令行启动 php 脚本时,我正在编辑 /etc/php5/cli/php.ini 文件。 (另外,我在问题的底部添加了一些额外的信息)
    【解决方案3】:

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

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

    $memoryManager->setMemoryLimit(-1);
    

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

    【讨论】:

    • 我将ini_set("memory_limit", -1); 添加到我的php 脚本中,但我仍然收到PHP Fatal error: Allowed memory size of 536870912 bytes exhausted 错误!这怎么可能?
    • 很可能 memory_limit 设置在添加语句之后的某处被覆盖。
    • 试过了,还是一样PHP Fatal error: Allowed memory size
    【解决方案4】:

    请按照以下步骤操作。

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

    1. 与其一一重新索引,不如一一重新索引

    php indexer.php --reindex catalog_product_price

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

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

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 2018-07-05
      • 2011-09-19
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多