2012-09-28 51 views
1

我有一个包含20,000个电子邮件地址的数据库,并且不断增加。我一次发送100封电子邮件,然后使用CURL php访问相同的页面,但页面仍然有最大的执行时间。我在共享(Hostgator)服务器上运行这个php脚本。我应该怎么做才能消除这个问题?执行长时间运行的php脚本时,如何解决执行超时错误?

exec("php-cli file.php > testoutput.php 2>&1 & echo $!", $output) 
+0

在crontab计划的较小块中执行该工作,可能存储您启动了哪个ID以便crontab作业可以快速继续并执行下一个块 – BugFinder

回答

1

您可以添加在数据库中的列(或辅助表),并作为最初标记所有地址“要工作”:

我通过执行这个脚本。

那么你的脚本可以:

- SELECT the number of worked addresses and total addresses 
- display a progress bar 
- SELECT the lowest 100, or 50, or N addresses yet to be worked 
- send the emails and mark them worked 
- issue a javascript to refresh itself. 

然后客户端会看到一个页面,一个进度条的不断进步,永不超时(只要“N”是足够小)。

你也可以在AJAX中做到这一点,但这可能是矫枉过正。此外,您可以使用一些技巧(如果您还没有这样做)来加速操作。一种可能性是将多个地址“合并”为密件抄送:,如果电子邮件正文相同;通过这种方式,您可以在一次通话中发送多条短信注意不要超过任何密件抄送:限制您的ISP可能执行。这个策略在ISP端使用更多的资源,所以请检查它们。

另一种可能性(可一起使用)是发送按域排序的电子邮件。如果可能的话,多个邮件服务器尝试在一个连接中将电子邮件发送到同一台服务器以节省资源和时间。如果您将一组电子邮件全部发送到同一个域中,则可以使服务器更轻松。

在这最后一种情况下,你会SELECT电子邮件这样的:

SELECT * FROM addresses 
    WHERE (worked=0 AND active = 1) 
    ORDER BY SUBSTRING_INDEX(email, '@', -1) 
    LIMIT 20; 

然后(例如与MySQL功能 - PDO越好),

while($tuple = mysql_fetch_assoc($exec)) 
{ 
    if (send_mail_to(...)) 
     $sent[] = $tuple['id']; 
    else $failed[] = $tuple['id']; 
} 
// Now mark both SENT and FAILED as worked 
$sentm = implode(',', $sent); 
$failm = implode(',', $failed); 

// UPDATE addresses SET worked = 1 WHERE id IN ($sentm,$failm); 
// UPDATE addresses SET active = 0 WHERE id IN ($failm); 

如果在PHP中保存的启动时间会议,你甚至可以显示一个很棒的仪表板,如

+--------------------+ 
|########   | 
+--------------------+ 
40% processed 
38% delivered 
2% failed 
Expected time remaining 5 min 17" 
+0

目前,我已经完成了创建后端进程和调用它与PHP。我也创建一个日志。使它成为一个后端过程客户端不需要再等待了,我建立了一个仪表板来向他展示如何发送邮件如何可能剩下的电子邮件在那里,我知道所有的电子邮件发送或不发送感谢这个答案 –

0

PHP's时间限制可以通过PHP的set_time_limit()功能被删除:

set_time_limit(0); 

然而,这只能解决一个长期运行的过程中死亡,由于PHP本身注意到这个过程时间太长的问题。尽管这是一个重要的步骤,但您还应该预测长时间运行过程中发生的其他类型的故障,方法是将工作分成较小的批次,并确保代码的结构方式允许在不重新运行整件事。