标签:php
请阅读此问题后,不要说它已被复制.我已经在网上搜索过,但是没有一种解决方案适合我.
我在做什么:->
我正在通过在本地主机上运行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(),这样我可以轻松地重定向流.
我的机器配置:
操作系统-> Ubuntu 12.04 LTs
PHP 5.3.10
APACHE 2.2.22
在本地主机上运行
权限:-
/ code-> 777
主php文件所在的文件夹-> 777(由于安全原因,我知道777不好,但是由于我在本地服务器上运行脚本,因此这些权限没有问题.)
我想要的是 :-
谁能告诉我任何方式,以便我可以停止主要的php脚本,直到proc-open()创建的进程终止,或者有人可以告诉我其他方式来满足我的重定向要求?
这是代码的一部分:
$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()."
";
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等待.如果需要,我将进一步研究我的旧脚本,但这类似于:
$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
您可以使用多种方法来解决问题.
首先,您可以将select中的超时设置为零,它将无限期地等待.如果您的可执行文件不使用stdout,则在进程终止时stream_select函数将阻塞,直到关闭管道为止.
如果您的进程确实使用stdout和stderr,则可以在循环中使用select并在每次select返回时检查管道是否关闭.如果将来将来需要的话,这也将使您能够有效地处理来自stdout和stderr的信息(json非常有用).
标签:php
来源: https://codeday.me/bug/20191122/2057839.html