如何等待php中proc_open()执行的进程? [英] How to wait for a process executed by proc_open() in php?

查看:271
本文介绍了如何等待php中proc_open()执行的进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请阅读此问题后,不要说它已被复制.我已经在网上搜索过,但没有一种解决方案适合我.

我在做什么:->
我正在本地主机上运行apache服务器,通过php获取源文件(例如.c).我将该文件保存在"/code/"目录中,并在php中使用proc_open()编译并执行此源文件.现在我想要等待主要的php脚本,直到"proc_open()"创建的进程终止,所以我使用了"pcntl_waitpid()".但是我认为使用"pcntl_waitpid()"存在问题,因为"pcntl_waitpid()"之后的脚本没有执行. 由"pcntl_waitpid()"创建的进程从"/code/input.txt"文件获取输入,并将输出提供给"/code/output.txt"文件,因此出于重定向目的,我使用proc_open(),这样我就可以轻松实现重定向流.

What i am doing :->
I am taking a source file (say .c) through php by running apache server on local host.I am saving that file in "/code/" directory and compiling and executing this source file using proc_open() in php.Now i want to wait main php script until the process created by "proc_open()" terminates, so i used "pcntl_waitpid()".But i think there is a problem in using "pcntl_waitpid()" because the script after the "pcntl_waitpid()" is not executing. Process created by "pcntl_waitpid()" takes input from "/code/input.txt" file and gives output to "/code/output.txt" file, so for redirecting purpose i am using proc_open() , so that i can easily redirect streams.

我的机器配置:-
操作系统-> Ubuntu 12.04 LT
PHP 5.3.10
APACHE 2.2.22
在本地主机上运行

My machine configuration:-
OS -> Ubuntu 12.04 LTs
PHP 5.3.10
APACHE 2.2.22
Running on local host

权限:-
/code-> 777

Permissions :-
/code -> 777
Folder where main php file resides -> 777 (I know that 777 is not good due to security reasons , but as i am running script on local server so i have no problem with these permissions.)

我想要的是:- 谁能告诉我任何方式,以便我可以停止主要的php脚本,直到proc-open()创建的进程终止,或者有人可以告诉我其他方式来满足我的重定向要求?

What i want :- Can any one tell me any way so that i can stop main php script until the process created by proc-open() terminates or if anyone can tell me other way to meet my requirement of redirection ?

这是代码的一部分:

$descriptors = array(
            2 => array("pipe","w")
        );




        $process = proc_open($cmd,$descriptors,$pipes,$code);

        sleep(2);

        if(is_resource($process))
        {
            $status = proc_get_status($process);
            $pid = $status ["pid"];

            echo getmypid()."<br />";


            echo $pid;

            if(pcntl_waitpid($pid,$child_status) == -1)
            {
                fclose($pipes[2]);
                proc_close($process);
                exit("Sorry!Unable to compile the source_file.\n");


            }


            while(!file_exists("/code/test"))
            {

                proc_close($process);
                echo stream_get_contents($pipes[2]),"\n";
                fclose($pipes[2]);
                exit("Sorry!Unable to compile the source_file.\n");
            }

            echo "Compiled Successfully!\n";
            echo "Running test cases...\n";

            fclose($pipes[2]);

            proc_close($process);

        }
        else
        {
            exit("Sorry!Unable to compile the source_file.\n");
        }

谢谢!

推荐答案

最好使用管道解决此问题. pcntl_wait()仅是Linux,根据我的经验,除非您处理fork(),否则它不是很有用.使用stream_select等待.如果需要,我将进一步研究我的旧脚本,但这有点像:

It's best to use pipes for this problem. pcntl_wait() is Linux only, and it isn't very useful (in my experience) unless your dealing with fork(). Use stream_select for waiting. I'll look further into my old scripts if needed, but it's something like:

<?php

$cwd = "/code/";

chmod("/code/test.c",0777);

switch($xtension)
{
    case "c":
        $cmd = "gcc -g test.c -o test -lm ";
    break;
    case "cpp":
        $cmd = "g++ -g test.cpp -o test";
    break;
    case "java":
        $cmd = "javac test.java";
    break;
}

$descriptors = array(   0 => array('pipe', 'r'), // stdin
                        1 => array('pipe', 'w'), // stdout
                        2 => array('pipe', 'a')  // stderr
);

$process = proc_open($cmd,$descriptors,$pipes,$code);

stream_set_blocking($pipes[2], 0);

if(($error = stream_get_contents($pipes[2]) !== false)
{
    // error starting command (error *in* command)
    die($error);

}else
{
    stream_set_blocking($pipes[2], 1);

    /* Prepare the read array */
    $read   = array($pipes[1], $pipes[2]);
    $write  = NULL;
    $except = NULL;
    $tv_sec = 0;      // secs
    $tv_usec = 1000;  // millionths of secs

    if(false === ($rv = stream_select($read, $write, $except, $tv_sec, $tv_usec)))
    {
        die('error in stream_select');

    }else if ($rv > 0)
    {
        foreach($read as $pipe_resource)
        {
            if($pipe_resource == $pipes[1])
            {
                // is stdout

            }else if($pipe_resource == $pipes[2])
            {
                // is stderr
            }
        }

    }else
    {
        // select timed out. plenty of stuff can be done here
    }
}

    // this will be executed after the process terminates

您可以使用多种方法来解决问题.

There are many ways that you can use this to solve your problem.

首先,您可以将select中的超时设置为零,它将无限期地等待.如果您的可执行文件不使用stdout,则在进程终止时stream_select函数将一直阻塞,直到关闭管道为止.

First, you can set the timeout in select to zero and it will wait indefinitely. If your executable doesn't use stdout, the stream_select function will block until the pipes are closed when the process terminates.

如果您的进程确实使用stdout和stderr,则可以在循环中使用select并在每次select返回时检查管道是否关闭.如果将来将来需要的话,这也将使您能够有用地处理来自stdout和stderr的信息(json非常有用).

If your process does use stdout and stderr you can use the select in a loop and check if the pipes are closed each time select returns. This will also allow you to usefully process information from stdout and stderr if needed in the future (json is awesome for this).

这篇关于如何等待php中proc_open()执行的进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆