PHP 程序因大量数据而失败

标签 php http

我正在编写一个 PHP 网络程序,用于从文件中检索数据并将其绘制成图表。如果我在服务器的命令行中运行它,它工作正常,并且它在浏览器中工作,用于相对少量的数据,但是一旦文件达到 1.2 或 130 万行(30 个字符/行,所以 3.5 或 4 MB ),我得到一个 HTTP 错误 500。奇怪的是,它工作不一致;有 125 万行,它有时有效,有时无效。 这是代码:

<?php

$wait = $_GET["wait"];
$measure = $_GET["measure"];
$graphsize = $_GET["graphsize"];
$title = "Current";
if ($measure == "CURR") $title = "Current (A)";
if ($measure == "VOLT") $title = "Voltage (V)";
if ($measure == "RES")  $title = "Resistance (Ohms)";

$page = $_SERVER["PHP_SELF"];

$data = array(array("Time", $title));
$datasize = filesize("data.csv")/30;
$x = 0;

$file = fopen("data.csv", "r");
while (($datum = fgets($file)) !== False) {
    $x++;
    if ($x % ($datasize/$graphsize) == 0) {
        $datum = explode(",", $datum);
        $datum[0] = floatval($datum[0]);
        $datum[1] = floatval($datum[1]);
        $data[] = $datum;
    }
}
fclose($file);

if (count($data) == 1) $data[] = array(0,0);

?>

graphing stuff down here, I'm pretty sure this isn't the problem

最佳答案

在某些系统上,PHP 有两个不同的 php.ini 文件——一个用于 apache,另一个用于 CLI。通常,CLI ini 文件不会对 max_execution_time 设置任何限制。 memory_limit 也有很大的值(value).这可能可以解释为什么它通过 CLI 而不是通过 Web 服务器运行。

逐行解析文件是明智的,因为这比一次读取整个文件内容消耗的内存更少。您应该检查 fopen 的结果以确保您确实打开了文件:

$file = fopen("data.csv", "r");
if (!$file) {
    throw new Exception("Could not open data file");
}

如果您的脚本在通过 Web 服务器访问时返回 5XX 结果,这通常意味着 PHP 脚本遇到了 fatal error 情况。我猜你要么 a) 时间用完了,要么 b) 内存用完了。要找出答案,您需要查看 php 错误。如果它没有直接输出到您的浏览器,那么您需要弄清楚我们的 php 日志在哪里。可能为此指定了一个值,也可能没有。试试看是否设置了值:

echo ini_get("error_log");

如果这个值为空,那么:

If this directive is not set, errors are sent to the SAPI error logger. For example, it is an error log in Apache or stderr in CLI.

在我的 Ubuntu 机器上,这个文件在每个域的 apache conf 文件中设置如下:

ErrorLog /var/www/site_name/log/error.log

但在您的机器上可能完全不同。如果您找不到它,请考虑使用 set_error_handler 函数来创建您自己的自定义错误处理函数,该函数可以拦截错误并将其写入文件或通过电子邮件发送或只是将其吐出或其他。

检查您的 php.ini 为几个设置设置的限制将提供信息:

// feel free to add more ini settings to this array if you are curious
$to_check = array("max_execution_time", "memory_limit", "error_log");
foreach($to_check as $setting) {
    echo $setting . ": " . ini_get($setting) . "\n<br>";
}

如果这些值看起来不令人满意,您可能会尝试使用 ini_set 通过编辑 web 服务器的 php.ini 来更改脚本本身中的这些值。不过,我不推荐后者,因为其中设置的值是为了保护您的服务器——如果您允许脚本运行时间过长或消耗过多内存,则您的服务器很容易受到运行可能消耗其所有资源的脚本的攻击。但是,如果您的服务器在安全模式下运行,则不允许您使用 ini_set 更改设置。

我还建议您看一下 php 函数 memory_get_usage() 和 microtime()。您可以跟踪脚本中使用的内存和耗时,以了解在脚本失败之前达到了哪些值。虽然从脚本中回显这些值可能更容易,但这意味着大量输出,这可能不是一个好主意。我建议您将返回的值写入文件。像这样的东西:

$log_file = "/some/path/to/log/file.txt";
$start_time = microtime(TRUE); // returns a unix timestamp as a float
file_put_contents($log_file, "start time is " . $start_time)
    or die("Unable to write log file");

// your script blah blah blah
$file = fopen("data.csv", "r");
while (($datum = fgets($file)) !== False) {

    // do your script datum stuff blah blah blah

    // write our progress to our log file
    file_put_contents($log_file, "elapsed time is " . (microtime(TRUE) - $start_time))
        or die("Unable to write elapsed time to log file");
    file_put_contents($log_file, "memory consumed is " . memory_get_usage())
        or die("Unable to write memory usage to log file");
}

如果你的脚本失败了,那么你可以去查看/some/path/to/log/file.txt 的内容,看看在它停止之前使用了多少时间和内存。

关于PHP 程序因大量数据而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41133238/

相关文章:

php - 我尝试在我的浏览器本地主机中打开一个 php 文件,但每次我双击它时它都会让我保存它

php - 数据库存在,但 WordPress 无法建立数据库连接

javascript - 无法获取 php 文件中 axios POST 方法的属性

php - 为什么websocket可以关闭连接?

php - 下拉列表在 chrome 中带有滚动条

http - 如何从 Rust 发出 HTTP 请求?

php - HTTP 缓存、用户身份验证和 PHP

angularjs - 如何在 http post 请求中发送大的 csv

security - HTTP是否重定向到密码的HTTPS风险捕获?

http - 什么时候确定 HTTP Date 响应 header ?