2010-11-13 65 views
4

我有一个庞大的PHP脚本。PHP内存不同服务器到服务器

正因如此,我不得不这样做

ini_set('memory_limit', '3000M'); 
set_time_limit (0); 

它运行罚款一台服务器上,但我都会:内存(分配1653342208)(试图分配71个字节)在/ home /writeabo/public_html/propturk/feedgenerator/simple_html_dom.php on line 848

两者都来自同一个主机,但服务器不同。

上述问题解决下面的赏金

更新新的问题:剧本是如此之大,因为它从252页,包括超过60,000图像,它使两个副本的罗尔斯网站和解析器数据。我已经把它分解成几部分。

虽然我现在有另一个问题。当我从外部网站上的图像写入服务器这样的:

try { 
    $imgcont = file_get_contents($va); // $va is an img src from an array of thousands of srcs 
    $h = fopen($writeTo,'w'); 
     fwrite($h,$imgcont); 
     fclose($h); 
    } catch(Exception $e) { 
    $error .= (!isset($error)) ? "error with <img src='" . $va . "' />" : "<br/>And <img src='" . $va . "' />"; 
    } 

突然它关系到一个500内部服务器错误页面,我必须做一遍,此时它的工作原理,因为文件只复制它们不存在。无论如何,我可以收到500个回复代码,并将其发送回网址以使其重新出现?因为这是一个自动化的过程?

+0

您是否有权访问此服务器上的PHP .ini文件? – Treffynnon 2010-11-13 10:13:03

+5

不是每天都有人看到一个PHP脚本吞噬了这么多的内存。它有什么作用? – stillstanding 2010-11-13 10:13:11

+4

任何一个服务器的机会是64位,另一个是32位? (尝试'uname -a') – 2010-11-13 10:18:08

回答

0

感谢您的输入。当我写这个问题的时候,我分离了所有的东西,所以爬虫,解雇了图像采集卡等。

我采取了解决方案来拆分图像的数量,这也有帮助。

我还加了一个try,抓住了读取的文件。

这只是在测试期间从浏览器调用,但现在它已全部启动并正在运行,它将成为一项cron工作。

感谢Swish和Benubird为您提供了特别详细的教育答案。不幸的是,我与后端的开发者没有合作关系,图片来源于这些(漫长而复杂的故事)。

无论如何,现在一切都好,谢谢。 (Swish如何从命令行调用脚本,我对此领域的知识严重缺乏?)

0

所以这听起来像你正在通过网络浏览器运行这个过程。我猜测你可能会在某段时间之后以某种方式从Apache获得500错误,或者该进程死亡或者某些事情发生。我建议你执行以下操作之一:

A)将图像下载移动到后台进程,您可以在浏览器中运行爬网脚本,该脚本会将要下载的图像的URL写入数据库或其他东西另一个脚本将通过cron启动并获取所有图像。你也可以让这个脚本一次批量处理100个左右,以保持内存消耗降低

B)直接从命令行调用脚本(对于类似这样的东西,这真是首选方法,而你应该仍然可能会将图像提取分离为另一个脚本)

C)如果由于某种原因命令行不是一个选项,请让浏览器加载脚本触摸一个文件,并且每分钟运行一次cron,然后查找文件存在。然后它启动你的脚本,你可以将输出写入文件供你稍后检查或发送完成时发送电子邮件

3

如果这是与内存有关的,我将亲自使用copy()而不是file_get_contents()。它以相同的方式支持文件包装,并且我没有看到将内存中的整个文件加载到文件系统中的优势。

否则,您的error_log可能会为您提供更多有关500发生的原因。

+0

那么,我可以使用完整的URL从外部网站上的文件复制? – 2010-11-22 15:44:05

+0

是的,你可以。这就是文件包装器所做的:处理各种URL,比如本地文件。 – 2010-11-24 15:56:46

0

是否有反正我可以收到500响应代码,并将其发送回网址,使它再次?因为这是一个自动化的过程?

这里是我会怎么做简单的版本:

function getImage($va, $writeTo, $retries = 3) 
{ 
    while ($retries > 0) { 
     if ($imgcont = file_get_contents($va)) { 
      file_put_contents($writeTo, $imgcont); 
      return true; 
     } 
     $retries--; 
    } 
    return false; 
} 

这不会创建该文件,除非我们成功地让我们的图像文件,并且将默认重试三次。当然,您将需要添加任何需要的异常处理,错误检查等

0

我肯定会()停止使用的file_get_contents和写入文件块,像这样:

$read = fopen($url, 'rb'); 
    $write = fope($local, 'wb'); 
    $chunk = 8096; 
    while (!feof($read)) { 
     fwrite($write, fread($read, $chunk)); 
    } 
    fclose($fp); 

这将是更好到你的服务器,并希望能解决你的500个问题。至于“捕捉”500错误,这根本不可能。这是您的脚本抛出并由Web服务器写入客户端的不可挽回的错误。

+0

试过了,但是文件写的是空白的,我以为是因为它们在外部服务器上 – 2010-11-22 15:42:57

+0

我不这么认为 - 你是在本地写的,对吧? – frak 2010-11-25 15:49:41

1

有三方这里涉及到:

  • 远程 - 计算机运行PHP脚本
  • 客户 - 的包含你的图像后
  • Server服务器(S) - 您的家庭计算机,如果您正在从Web浏览器运行脚本,或者如果您从Cron运行该服务器,则使用与服务器相同的计算机。

您看到的500错误是由'远程'生成,并被'服务器'看到(即图像暂时不可用); 或者它是由'服务器'生成,并被'客户端'看到(即您的脚本有问题)。

如果它是由'远程'生成的,那么请参阅阿里关于如何重试的答案。

如果它是由'服务器'上的脚本生成的,那么你需要确切地确定错误是什么 - php错误日志应该给你更多的信息。我可以想到两个可能的原因:

  • 达到PHP的时间限制。在返回500错误之前,PHP只会花费一定的时间工作。您可以将其设置为更高的值,或者定期通过调用set_time_limit()来重新设置定时器,但如果您的服务器配置为安全模式,则这不起作用。
  • 达到PHP的内存限制。你似乎已经忍受了这一点,但值得确保你的脚本仍然没有吃大量的内存。考虑输出调试数据(可能只有当你设置$ config ['debug_mode'] = true或其他)。我建议:

    try { 
        echo 'Getting '.$va.'...'; 
        $imgcont = file_get_contents($va); // $va is an img src from an array of thousands of srcs 
        $h = fopen($writeTo,'w'); 
        fwrite($h,$imgcont); 
        fclose($h); 
        echo 'saved. Memory usage: '.(memory_get_usage()/(1024 * 1024)).' <br />'; 
        unset($imgcont); 
    } catch(Exception $e) { 
        $error .= (!isset($error)) ? "error with <img src='" . $va . "' />" : "<br/>And <img src='" . $va . "' />"; 
    } 
    

我还添加了一条线,从内存中删除图像,柜面PHP不这样做正确的本身(理论上该行不应该是必要的)的。

您可以通过让您的脚本一次处理更少的图像并定期调用它来避免这两个问题 - 在服务器上使用Cron(理想的解决方案,尽管不是所有共享的虚拟主机都允许)或桌面上的某些软件电脑。如果你这样做,一定要考虑如果同时运行两个脚本副本会发生什么情况 - 它们是否会同时获取相同的图像?

0

我与Swish一样,这不是PHP的目标 - 你会更好地使用某种服务器端脚本。

Is there anyway I can receive the 500 response code and send it back it to the url to make it go again?

你有没有考虑使用第三方库?从外部服务器获取文件在我看来似乎更像curl或ftp的工作,而不是file_get_content &等。如果错误是外部的,并且您使用的是curl,则可以检测到500返回代码并正确处理而不会崩溃。如果没有,那么也许你应该把你的程序分成两个文件 - 其中一个取一个文件/图像,另一个使用curl重复调用第一个文件/图像。除非500错误意味着所有php执行崩溃,否则您将能够检测到失败并处理它。

事情是这样的伪代码:

file1.php:

foreach(list_of_files as filename){ 
    do { 
     x = call_curl('file2.php', filename); 
    } 
    while(x == 500); 
} 

file2.php:

filename=$_GET['filename']; 
    results = use_curl_to_get_page(filename); 
    echo results;