php exec 获取进程号,在Linux上创建PHP在线评分系统:exec行为,进程ID和grep

  • Post author:
  • Post category:php


背景

我正在使用PHP和MySQL编写一个简单的在线评判(代码评分系统).它采用C和Java提交的代码,编译它们并测试它们.

这是在旧版本的Ubuntu上运行PHP 5.2的Apache.

我目前在做什么

我有一个无限循环的PHP程序,调用另一个PHP程序

//for(infinity)

exec(“php -f grade.php”);

//…

每十分之一秒.让我们调用第一个looper.php和第二个grade.php. (检查点:在“for”循环继续之前,grade.php应该完全运行,对吗?)

grade.php提取需要从MySQL数据库评分的最早提交的代码,将该代码放入文件(test.[cpp / java]),并连续调用其他2个php程序,名为compile.php和test. php,像这样:

//…

exec(“php -f compile.php”);

//…

//for([all tests])

exec(“php -f test.php”);

//…

(检查点:compile.php应该在调用test.php的“for”循环之前完全运行,是否正确?)

然后compile.php编译test.[cpp / java]中的程序作为后台进程.现在,我们假设它正在编译Java程序,而test.java位于子目录中.我现在有

//…

//$dir = “./sub/” or some other subdirectory; this may be an absolute path

$start_time = microtime(true); //to get elapsed compilation time later

exec(“javac “.$dir.”test.java -d “.$dir.” 2> “.$dir

.”compileError.txt 1> “.$dir.”compileText.txt & echo $!”, $out);

//…

在compile.php中.它正在重定向javac的输出,所以javac应该作为后台进程运行……它似乎有效. $out应该在$out [0]中获取javac的进程ID.

真正的问题

我想停止编译,如果由于某种原因编译需要超过10秒,并且我想结束compile.php如果程序在10秒之前停止编译.由于exec(“javac …我上面调用的是后台进程(或者是它?),我无法知道它何时完成而没有查看进程id,而进程id应该早先存储在$out中.紧接着,在compile.php中,我使用10秒循环调用exec(“ps ax | grep [pid].* javac”);并查看pid是否仍然存在:

//…

$pid = (int)$out[0];

$done_compile = false;

while((microtime(true) – $start_time < 10) && !$done_compile) {

usleep(20000); // only sleep 0.02 seconds between checks

unset($grep);

exec(“ps ax | grep “.$pid.”.*javac”, $grep);

$found_process = false;

//loop through the results from grep

while(!$found_process && list(, $proc) = each($grep)) {

$boom = explode(” “, $proc);

$npid = (int)$boom[0];

if($npid == $pid)

$found_process = true;

}

$done_compile = !$found_process;

}

if(!done_compile)

exec(“kill -9 “.$pid);

//…

……似乎没有用.至少在某些时候.通常情况下,test.php会在javac停止之前开始运行,导致test.php在尝试运行java程序时无法找到主类.我认为循环由于某种原因被绕过,尽管可能并非如此.在其他时候,整个评分系统按预期工作.

同时,test.php在一定的时间限制内运行程序时也使用相同的策略(使用X-second循环和grep),并且它有类似的bug.

我认为错误在于grep没有找到javac的pid,即使javac仍然在运行,导致10秒循环早期破坏.你能发现一个明显的错误吗?一个更谨慎的错误?我使用exec有问题吗? $out有问题吗?或者发生了什么完全不同的事情?

感谢您阅读我的长篇问题.所有帮助表示赞赏.