PHP脚本意外地没有继续

PHP脚本意外地没有继续,php,javascript,html,Php,Javascript,Html,我有一个PHP脚本(我们称之为execute.PHP),它在开始时绘制整个页面(HTML标记和主体标记等),然后在后台执行一些命令(C++程序)。然后,它等待这些程序终止(一些程序取决于其他程序的结果,因此它们可能会按顺序执行),然后有一个JavaScript自动将表单提交给另一个PHP脚本(我们称之为results.PHP),因为results.PHP需要来自上一个脚本的POST信息 execute.php: <?php print" <html> <body>

我有一个PHP脚本(我们称之为
execute.PHP
),它在开始时绘制整个页面(HTML标记和主体标记等),然后在后台执行一些命令(C++程序)。然后,它等待这些程序终止(一些程序取决于其他程序的结果,因此它们可能会按顺序执行),然后有一个JavaScript自动将表单提交给另一个PHP脚本(我们称之为
results.PHP
),因为
results.PHP
需要来自上一个脚本的POST信息

execute.php

<?php
print"
<html>
<body>
   Some HTML code here
</body>
</html>
";

// Here come some C++-program calls
$pid_program1 = run_in_background($program1)
$pid_program2 = run_in_background($program2)
while (is_running($pid_program1) or is_running($pid_program2) )
{
  //echo(".");
  sleep(1);
}

// Here come some later C++-program calls that execute quickly
$pid_program3 = run_in_background($program3)
$pid_program4 = run_in_background($program4)
while (is_running($pid_program3) or is_running($pid_program4) )
{
  sleep(1);
}
...
// We are now finished 
print "
<form action=\"results.php\" id=\"go_to_results\" method=\"POST\">
<input type='hidden' name=\"session_id\" value=\"XYZ\">
</form>
<script type=\"text/javascript\">
AutoSubmitForm( 'go_to_results' );
</script>
";
php包含C++程序调用、等待例程,最后通过“include”(“results.php”)”创建结果页面。 同样,对于“不太长”的程序执行,自动子任务按预期工作,但如果需要“更长”的时间,则不会。我说的“更长”是指大约25分钟

我完全不知道是什么原因导致了这种情况,因为同样,没有找到任何错误消息。 我是否缺少一个关键的配置选项(apache、php等)

编辑
事实证明,让请求的PHP脚本反复“回显”某些内容可以防止超时。因此,它基本上与不使用AJAX的PHP解决方案相同,但这一次,由于不一定需要AJAX请求的responseText,因此进度页并不凌乱,可以将其用作解决方法。具体来说,我不一定推荐它作为一种通用解决方案或良好实践。

这似乎相当复杂。。。而且非常危险。任何网络故障、用户浏览器因任何原因关闭,甚至防火墙超时,此脚本都会中止

为什么不在后台运行整个程序

<?php

session_start();
$_SESSION['background_run_is_done'] = false;
session_write_close(); // release session file lock

set_time_limit(0); 
ignore_user_abort(true); // allow job to keep running even if client disconnects.

.... your external stuff here ...

if ($successfully_completed) {
   session_start(); // re-open session file to update value
   $_SESSION['background_run_is_done'] = TRUE;
}

... use curl to submit job completion post here ...

?>


这将断开用户浏览器状态与作业处理的连接。然后,您只需偶尔让客户端代码ping服务器,以监视作业的进度。

我觉得更好的方法是:

  • 输出完整的HTML页面
  • 向用户显示加载消息
  • 发送AJAX请求以启动外部程序
  • 等待回调(等待外部程序完成)
  • 重复步骤3和4,直到执行完所有程序
  • 更新页面以告诉用户发生了什么
  • 提交表格
  • 这样,您可以尽快将HTML发送给用户,然后以有序和可控的方式顺序执行程序,而无需担心达到
    max\u execution\u time
    阈值。这还允许您随时通知用户—在每次AJAX回调之后,您可以告诉用户“程序ABC已完成,正在启动DEF…”等等

    编辑

    对于每个请求,我将添加一个如何实现的概要。还有一个警告:如果你要把更多的JavaScript派生的功能添加到你的页面中,你会考虑使用像JQuery或MooToots之类的库(我个人最喜欢的)。这是一个你应该马上做出的决定——如果你不打算做很多javascript,那么库只会使你的项目膨胀,但是如果你打算添加很多javascript,你不想以后再回来重新编写代码,因为你在整个项目中添加了3/4个库

    我已经使用mootools创建了这个演示,但是如果这是您将要使用它的唯一目的,那么添加mootools是不必要的,甚至是不可取的。对我来说,快速编写一个示例更容易,而不必停下来思考:)

    首先是主页。我们将此页面称为
    view.php
    。这应该包含您的初始HTML以及将触发AJAX请求的javascript。基本上,整个JSFIDLE将是view.php:

    现在,
    execute.php
    如下所示:

    $program_name = isset($_POST['program_name']) ? $_POST['program_name'] : false;
    switch ($program_name) {
        case 'program1':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 1';
            break;
        case 'program2':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 2';
            break;
        case 'program3':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 3';
            break;
        case 'program4':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 4';
            break;
        default:
            die(json_encode(array(
                'program_name'=>'Invalid',
                'status'=>'FAILED',
                'error'->true,
                'error_msg'=>'Invalid program'
            )));
            break;
    }
    
    $pid = run_in_background($program_path)
    while (is_running(pid)) {
      sleep(1);
    }
    
    // check here for errors, get any error messages you might have
    $error = false;
    $error_msg = '';
    // use this for failures that are not necessarily errors...
    $status = 'OK';
    
    die(json_encode(array(
        'program_name'=>$friendly_name,
        'status'=>$status,
        'error'->$error,
        'error_msg'=>$error_msg
    )));
    

    execute.php
    将为每个程序调用一次。
    $friendly\u程序
    变量提供了一种发回内容供用户查看的方法。那里的switch语句确保脚本不会被要求执行任何您不期望的操作。程序将被执行,完成后,您将发送一小包信息,包括状态、友好名称、任何错误等。这将进入
    view.php
    上的javascript,然后决定是否有更多程序要运行。如果是这样,它将再次调用
    execute.php
    。。。如果没有,它将提交表单。

    从Web服务器启动和管理多个长期运行的进程PHP进程充满了问题。它在不同的平台上也有很大的不同(你没有说你正在使用哪个)


    从PHP的执行中同步处理这些进程的调用不是解决这个问题的方法。您确实需要在一个单独的会话组中运行这些程序,并使用(例如)Ajax或Comet来轮询它们的状态。

    您如何调用
    execute.php
    ?通过
    http
    请求或命令行?这将是一种更好的方法。谢谢。这肯定是更协调,更好。由于我对web编程还很陌生,并且到目前为止,我已经成功地使用HTML、PHP和几行JavaScript实现了所有功能,所以我对AJAX一点也不熟悉。因此,我可以用一个例子来建立它。可能有很多例子,所以有一个接近我解释的我现在正在做的将是伟大的。我凑了一个快速和肮脏的例子,看看编辑。这真的很好。非常感谢你!根据我的经验,我自己也试过了。还不是所有的东西都能工作,但我会在完成后尝试提供解决方案的概述。我正在Linux机器上使用Apache和PHP-5模块。谢谢。我知道您提到的一些问题,建议您以不同的方式解决。但是,我没有
    $program_name = isset($_POST['program_name']) ? $_POST['program_name'] : false;
    switch ($program_name) {
        case 'program1':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 1';
            break;
        case 'program2':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 2';
            break;
        case 'program3':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 3';
            break;
        case 'program4':
            $program_path = '/path/to/executable/';
            $friendly_name = 'Some program 4';
            break;
        default:
            die(json_encode(array(
                'program_name'=>'Invalid',
                'status'=>'FAILED',
                'error'->true,
                'error_msg'=>'Invalid program'
            )));
            break;
    }
    
    $pid = run_in_background($program_path)
    while (is_running(pid)) {
      sleep(1);
    }
    
    // check here for errors, get any error messages you might have
    $error = false;
    $error_msg = '';
    // use this for failures that are not necessarily errors...
    $status = 'OK';
    
    die(json_encode(array(
        'program_name'=>$friendly_name,
        'status'=>$status,
        'error'->$error,
        'error_msg'=>$error_msg
    )));