【问题标题】:checking memory_limit in PHP在 PHP 中检查 memory_limit
【发布时间】:2012-04-29 19:46:08
【问题描述】:

我需要在我的脚本安装程序中检查memory_limit 是否至少为64M。这只是应该工作的 PHP 代码的一部分,但可能由于这个“M”,它没有正确读取值。如何解决这个问题?

  //memory_limit
    echo "<phpmem>";
    if(key_exists('PHP Core', $phpinfo))
    {
        if(key_exists('memory_limit', $phpinfo['PHP Core']))
        {
            $t=explode(".", $phpinfo['PHP Core']['memory_limit']);
            if($t[0]>=64)
                $ok=1;
            else
                $ok=0;
            echo "<val>{$phpinfo['PHP Core']['memory_limit']}</val><ok>$ok</ok>";
        }
        else
           echo "<val></val><ok>0</ok>";
    }
    else
        echo "<val></val><ok>0</ok>";
    echo "</phpmem>\n"; 

【问题讨论】:

  • 我使用的是 XML 代码,所以这是不可能的。
  • 你能显示var_dump($phpinfo);,或者至少var_dump($phpinfo['PHP Core']);,这样我们就可以看到你从什么开始?

标签: php memory-limit


【解决方案1】:

尝试先转换值(例如:64M -> 64 * 1024 * 1024)。之后,进行比较并打印结果。

<?php
$memory_limit = ini_get('memory_limit');
if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) {
    if ($matches[2] == 'M') {
        $memory_limit = $matches[1] * 1024 * 1024; // nnnM -> nnn MB
    } else if ($matches[2] == 'K') {
        $memory_limit = $matches[1] * 1024; // nnnK -> nnn KB
    }
}

$ok = ($memory_limit >= 64 * 1024 * 1024); // at least 64M?

echo '<phpmem>';
echo '<val>' . $memory_limit . '</val>';
echo '<ok>' . ($ok ? 1 : 0) . '</ok>';
echo '</phpmem>';

请注意,上面的代码只是一个想法。不要忘记处理 -1(无内存限制)、仅整数值(以字节为单位的值)、G(以千兆字节为单位的值) )、k/m/g(值以千字节、兆字节、千兆字节为单位,因为速记不区分大小写)等。

【讨论】:

  • 提供的正则表达式不完整,不精确,会导致各种安装结果错误。
  • ini_get() 函数在某些服务器中抛出异常您对此有何调整?
  • 记得处理-1的memory_limit
  • '$ok = ($memory_limit >= 640 * 1024 * 1024); // 至少 64M?你的意思是至少640M?
【解决方案2】:

只要您的数组$phpinfo['PHP Core']['memory_limit'] 包含memory_limit 的值,它就可以执行以下操作:

  • 该值的最后一个字符可以表示速记符号。如果它是无效的,则会被忽略。
  • 以 PHP 自己的特定方式将字符串的开头转换为数字:忽略空格等。
  • 数字和简写符号(如果有)之间的文本被忽略。

例子:

# Memory Limit equal or higher than 64M?
$ok = (int) (bool) setting_to_bytes($phpinfo['PHP Core']['memory_limit']) >= 0x4000000;

/**
 * @param string $setting
 *
 * @return NULL|number
 */
function setting_to_bytes($setting)
{
    static $short = array('k' => 0x400,
                          'm' => 0x100000,
                          'g' => 0x40000000);

    $setting = (string)$setting;
    if (!($len = strlen($setting))) return NULL;
    $last    = strtolower($setting[$len - 1]);
    $numeric = (int) $setting;
    $numeric *= isset($short[$last]) ? $short[$last] : 1;
    return $numeric;
}

速记符号的详细信息在a PHP manual's FAQ entry 中概述,极端细节在Protocol of some PHP Memory Stretching Fun 中。

注意是否设置为-1 PHP 不会在这里限制,但系统会。因此,您需要决定安装程序如何处理该值。

【讨论】:

  • 这是紧凑的代码,但在 PHP 7.1+ 下会中断:$numeric = 0 + $setting; 抛出异常,因为 $setting 不是数字值,因为后缀(消息是“遇到的非格式正确的数字值在 [...]”)。在(至少)7.2 中,以下工作代替:$numeric = (int)$setting;
  • @GabrielMagana:好点,这是我很久以前写的,并且使用 (int) cast 无论如何都比 0 + 更可取来转换数字。编辑了答案。
【解决方案3】:

这是另一种更简单的检查方法。

$memory_limit = return_bytes(ini_get('memory_limit'));
if ($memory_limit < (64 * 1024 * 1024)) {
    // Memory insufficient      
}

/**
* Converts shorthand memory notation value to bytes
* From http://php.net/manual/en/function.ini-get.php
*
* @param $val Memory size shorthand notation string
*/
function return_bytes($val) {
    $val = trim($val);
    $last = strtolower($val[strlen($val)-1]);
    $val = substr($val, 0, -1);
    switch($last) {
        // The 'G' modifier is available since PHP 5.1.0
        case 'g':
            $val *= 1024;
        case 'm':
            $val *= 1024;
        case 'k':
            $val *= 1024;
    }
    return $val;
}

【讨论】:

  • 这个怎么样? $bytes = (int)$mem * 1024 ** ['k' =&gt; 1, 'm' =&gt; 2, 'g' =&gt; 3][strtolower($mem)[-1]] ?? 0;
【解决方案4】:

不是那么精确但更简单的解决方案:

$limit = str_replace(array('G', 'M', 'K'), array('000000000', '000000', '000'), ini_get('memory_limit'));
if($limit < 500000000) ini_set('memory_limit', '500M');                     

【讨论】:

  • 如果您将 K 视为 2^10,它将不起作用。所以它不是很普遍。但是为一项发明点赞。
  • 效果很好,因为在第二行比较中您可以进行相同的简化。到目前为止,这在数百个带有图像修改插件的网站上对我有用——所需的内存量从来都不是很精确,所以我无论如何都要检查 30% 大的数字,然后 1024 和 1000 之间的差异只是一个舍入错误:)
【解决方案5】:

很老的帖子。但我将把它留在这里:

/* converts a number with byte unit (B / K / M / G) into an integer */
function unitToInt($s)
{
    return (int)preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
        return $m[1] * pow(1024, strpos('BKMG', $m[2]));
    }, strtoupper($s));
}

$mem_limit = unitToInt(ini_get('memory_limit'));

【讨论】:

  • 这是什么?请不要只发布代码。解释你的这段代码如何以及为什么会解决这个问题。
【解决方案6】:

感谢您的启发。

我遇到了同样的问题,我没有从互联网上复制粘贴一些功能,而是为它编写了一个开源工具。随意使用它或提供反馈!

https://github.com/BrandEmbassy/php-memory

只需使用 Composer 安装它,然后您就可以像这样获得当前的 PHP 内存限制:

$configuration = new \BrandEmbassy\Memory\MemoryConfiguration();
$limitProvider = new \BrandEmbassy\Memory\MemoryLimitProvider($configuration);
$limitInBytes = $memoryLimitProvider->getLimitInBytes();

【讨论】:

    【解决方案7】:

    如果您对 CLI 内存限制感兴趣:

    cat /etc/php/[7.0]/cli/php.ini | grep "memory_limit"
    

    FPM/“正常”

    cat /etc/php/[7.0]/fpm/php.ini | grep "memory_limit"
    

    【讨论】:

      【解决方案8】:

      在命令行上检查:

      php -i | grep "memory_limit"
      

      【讨论】:

      • 你能解释一下我从中得到的输出吗:memory_limit => -1 => -1
      • 对于某些 PHP 设置,-1 表示“无限制”,但我不确定 memory_limit。您可以从 php.ini 文件中检查它。执行 php -i |在命令行上 grep "php.ini" 并检查加载的配置文件中的 memory_limit。
      • 如果终端打印 => -1 => -1 这表示内存限制是无限的
      【解决方案9】:

      1. PHP-CLI:

      检查ini的命令行:

      $ php -r "echo ini_get('memory_limit');"
      

      或者查看php-cli info和grep memory_limit值:

      $ php -i | grep "memory_limit"
      

      2。 PHP-FPM:

      将此行粘贴到index.php任何可以在浏览器上查看的php文件,然后检查结果:

      <?php echo ini_get('memory_limit');
      

      另一种方法是使用phpinfo()

      <?php phpinfo();
      

      然后查找memory_limit

      【讨论】:

      • 仅供参考,这将返回 PHP 的 CLI 版本的内存限制,但您的 nginx/apache 将使用“其他”PHP 进程,即 PHP 的 fpmversion(抱歉,不知道该由谁来描述) )。最好在 .ini 中手动检查:/etc/php/7.4/cli/php.ini/etc/php/7.4/fpm/php.ini
      猜你喜欢
      • 1970-01-01
      • 2013-08-08
      • 2011-04-08
      • 1970-01-01
      • 2012-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多