运行php脚本而不输出到浏览器

时间:2013-12-30 15:12:10

标签: php server-side

我有一个非常耗费人力的PHP脚本,它可以在其他地方对服务器进行几次api调用。 我需要运行此脚本以保留我的服务器上的某些数据,与远程服务器上的数据同步。

我希望每次特定类型的用户访问特定页面时都会启动此脚本。

但问题是,如果符合条件的用户访问此页面,则页面加载时间是非常的,即使脚本处理的数据不会以任何方式影响页面本身。

所以,我想知道的是,我如何使用相同的条件运行此脚本,但只在我的服务器上运行?

换句话说,如何运行此脚本并阻止浏览器等待其输出?

编辑:有用的信息:使用XAMPP for Windows,PHP 5.5,Apache 2.4。

编辑2:使用curl似乎是最好的选择,但它不想实际运行我的脚本。

这是电话:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost/tool/follow/PriceTableUpdate.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);
curl_exec($ch);

这是实际的PriceTableUpdate.php:

<?php  
ini_set('max_execution_time', 3600);
$marketData=simplexml_load_file("http://www.eve-markets.net/api/xml?listid=20158key=JKgLjgYvlY6nP");
foreach ($marketData->marketList->type as $type) {
     $ItemID = (int)$type['id'];
     $ItemBuy = $type->buy->price;
     $ItemSell = $type->sell->price;
     $ItemMedian = $type->median->price;
     mysqli_query($con,"UPDATE piprices SET `ItemBuyPrice` = $ItemBuy, `ItemSellPrice` = $ItemSell, `ItemMedianPrice` =$ItemMedian WHERE `piprices`.`ItemID` = $ItemID");
 }
?>

编辑3: 使用上述DOES工作,以防有人想再次提出这个问题。 你必须记住,因为你使用curl,php文件不再使用你之前设置的变量,所以你需要再次在php文件中定义你的数据库连接。

8 个答案:

答案 0 :(得分:4)

为什么不在此使用AJAX?当页面加载并满足您的特定条件时,向服务器发出AJAX请求并启动脚本,而不等待响应回浏览器。

答案 1 :(得分:2)

你可以用onLoad事件单独调用你的php脚本 - 也就是说,你等到页面加载,然后“在后台”调用另一个脚本。后者可以使用以下代码行完成(我通过@Gavriel发布的链接http://www.paul-norman.co.uk/2009/06/asynchronous-curl-requests/在对其他答案之一的评论中找到了这一点):

<?php
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'http://www.yoursite.com/background-script.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);

curl_exec($ch);
curl_close($ch);
?>

在页面中的任何位置添加此代码应该会导致脚本在没有延迟的情况下执行页面加载 - 在这种情况下甚至不需要使用onLoad事件。

答案 2 :(得分:2)

如果我理解你想要做什么,那么一个可能的解决方案是在另一个线程中运行另一个php。在php中,您可以通过curl:http://php.net/curl

调用它

答案 3 :(得分:1)

您应该将browser-request与background-data-request分开。

当用户进行访问时,然后在消息队列服务器中创建一个项目。将所需数据放入该消息中。让队列从相同/不同的机器执行。

如果您没有拆分请求,那么您的web服务器工作进程将保持活动状态,直到php完全执行您的脚本为止。还说,阻止浏览器。 你可以“刷新”当前的输出,但服务器仍然等到php准备好关闭浏览器连接。

答案 4 :(得分:0)

尝试使用exec()函数

如果您的服务器是类似于unix的操作系统,请使用&amp ;;终止您的命令将启动命令,不会等待它结束     exec('。/ mylongcommand&amp;');

从未尝试过这个,但它应该有用......

答案 5 :(得分:0)

有几种方法。一,你可以分叉执行:

<?php

# only works if pcntl_fork is installed on POSIX system
# will NOT work on windows


# returns new child id
$pid = pcntl_fork();

if ($pid == -1) {

  die("could not fork\n");

} else if ($pid) {

 $my_pid = getmypid();
 print " I am the parent. pid = $my_pid \n";
 pcntl_wait($status); //Protect against Zombie children

} else {  # child pid is 0 in child

  $my_pid = getmypid();
  print " I am the child.  pid = $my_pid  \n";

}

# example output
# I am the parent. pid = 23412
# I am the child.  pid = 23414

或者,在OS系统级别(使用command &分叉进程,假设您在linux / unix上运行PHP)。因此,PHP可用于执行shell脚本。

此外,有些人建议使用Ajax,但是您需要小心考虑可以同时触发多个脚本的情况。这将在服务器和资源锁定上加载什么?可能还需要一些锁定逻辑来确保一次只执行一个脚本,以及“心跳”,让您知道该进程是活着还是已死。

答案 6 :(得分:0)

有一个长时间运行的后台进程来处理队列中的作业;类似于beanstalkd的东西。

当此过程遇到名为“sync.schizz”的作业时,它将开始同步。现在你只需要在你的特殊访客挥手时将一个工作弹出到队列中 - 这将是闪电般的。

答案 7 :(得分:0)

使用OP中的卷曲功能显示,我开始工作了。 我忘了添加mysql连接细节,这是我以前不需要的(使用include时)。