質問

Below is the code I'm trying to finish to view logs on our PBX. It runs fine, sorts through the log files, displays all the data, etc. The problem is that once it's done, it keeps a large amount of data (several hundred MB) in memory. I need it cleared out when it's done but can't figure out how. If it's run a couple of times it sucks all of the RAM from the server and we start getting errors. Thanks in advance!

<!DOCTYPE html>
<html>
<title>Call Search</title>
<body>

<?php
function getBetween($var1, $var2, $pool)
{
        $temp1 = strpos($pool, $var1) + strlen($var1);
        $result = substr($pool, $temp1, strlen($pool));
        $dd=strpos($result, $var2);
        if($dd == 0){$dd = strlen($result);}
        return substr($result, 0, $dd);
}

if(!isset($_POST['phonenum']) && !isset($_POST['WantedCallID']))
{
        echo '<form action="test.php" method="post">';
            echo '<h4>Please enter the number you wish to search for...</h4><input     type="text" name="phonenum">';
    echo '<input type="submit" value="Go">';
    echo '</form>';
}

else if(isset($_POST['WantedCallID']))
{
   $counter = 0;
   $logfile="calllog";
   while (file_exists("/var/log/".$logfile))
   {
      if($counter==0){$logfile="calllog";}
      else{$logfile="callog.".$counter;}
      $path = "/var/log/".$logfile;
      $logtoarray = file($path);
      foreach ($logtoarray as $linenumber => $line)
      {
         if(strpos($line, "[".$_POST['WantedCallID']."]") !== false){echo $line."    <br>";}
      }
   $counter++;
   }
}

else
{
   $counter = 0;
   $logfile="calllog";
   $arrayCounter = 0;
   while (file_exists("/var/log/".$logfile))
   {
      if($counter == 0){$logfile = "calllog";}
      else{$logfile="calllog.".$counter;}
      $path = "/var/log/".$logfile;
      if(file_exists($path))
      {
         $logtoarray = file($path);
         $oldCallId = "";
         $currentCallId = "";
         foreach ($logtoarray as $linenumber => $line)
         {
             if(strpos($line, $_POST['phonenum']) !== false && strpos($line, "VERBOSE[") !== false)
             {
                    $currentCallId = getBetween("VERBOSE[", "]", $line);
                if($currentCallId !== $oldCallId)
                {
                   $callIdArray[$arrayCounter] = "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."\n";
                   echo "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."<br>";
               $oldCallId = $currentCallId;
            }
        }
        $arrayCounter++;
     }
  }
  else{break;}
  $counter++;
   }
   echo '<form action="test.php" method="post">';
   echo '<h4>Please enter the call ID you wish to search for...</h4><input type="text" name="WantedCallID">';
   echo '<input type="submit" value="Go">';
   echo '</form>';
}

$variables = array_keys(get_defined_vars());
foreach($variables as $variable) {
    unset(${"$variable"});
}
unset($callIdArray);
?>

</body>
</html>
役に立ちましたか?

解決

Here is a simple modification to your code that will read the logfiles one line at a time rather than reading the entire file into memory.

while (file_exists("/var/log/".$logfile))
{
    if($counter == 0){$logfile = "calllog";}
    else{$logfile="calllog.".$counter;}
    $path = "/var/log/".$logfile;
    if(file_exists($path))
    {
        $fh = fopen($path, 'r'); //change
        $linenumber = 0; //addition
        $oldCallId = "";
        $currentCallId = "";
        while( $line = fgets($fh) ) //change
        {
            $linenumber++; //addition
            if(strpos($line, $_POST['phonenum']) !== false && strpos($line, "VERBOSE[") !== false)
            {
                $currentCallId = getBetween("VERBOSE[", "]", $line);
                if($currentCallId !== $oldCallId)
                {
                    $callIdArray[$arrayCounter] = "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."\n";
                    echo "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."<br>";
                    $oldCallId = $currentCallId;
                }
            }
            $arrayCounter++;
        }
        fclose($fh); //addition
    }
}

他のヒント

I'm going to presume that you run this script through an Apache server. This is a fairly common problem, though I've more often seen it from resizing images.

Once an Apache child (the process that runs PHP) has had the amount of memory it, or more usually, PHP, increased because of a lot of data being used, it doesn't have a method to return the memory to the OS.

Instead, each child-process has the MaxRequestsPerChild setting. This might be set to 0 - never restart. If the inflating memory size is a problem, then setting this to a few hundred, or thousand, might be useful. After that many requests, the apache child is restarted, and so all the memory captured si returned to the OS, and a new child is spun up if needed. While the requests might take a little longer when the process is being restarted, the freeing of memory would be more useful.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top