- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在使用PHP和MySQL编写一个简单的在线判断(代码评分系统)。它接受提交的 C++ 和 Java 代码,编译并测试它们。
这是在旧版本的 Ubuntu 上运行 PHP 5.2 的 Apache。
我有一个无限循环的 php 程序,通过调用另一个 php 程序
//for(infinity)
exec("php -f grade.php");
//...
每十分之一秒。我们将第一个称为 looper.php
,将第二个称为 grade.php
。 (检查点:grade.php
应该在“for”循环继续之前完全运行完毕,对吗?)
grade.php
从 MySQL 数据库中提取最早提交的需要评分的代码,并将该代码放入文件中 (test.[cpp/java]
) ,并依次调用另外两个 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 秒,我想停止编译,如果程序在 10 秒之前停止编译,我想结束 compile.php
。由于我上面调用的 exec("javac...
是一个后台进程(或者是吗?),我无法在不查看进程 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秒循环和grep)在一定的时间限制运行程序,并且有类似的错误。
我认为错误在于 grep
没有找到 javac
的 pid,即使 javac
仍在运行,导致 10 秒循环提前中断。你能发现一个明显的错误吗?一个更谨慎的错误?我对 exec
的使用有问题吗? $out
有问题吗?还是发生了完全不同的事情?
感谢您阅读我的长问题。感谢所有帮助。
最佳答案
我刚刚想出了这段代码,它会运行一个进程,如果它运行的时间超过 $timeout
秒就会终止它。如果它在超时之前终止,它将在 $output
中有程序输出,在 $return_value
中有退出状态。
我已经测试过了,它似乎运行良好。希望您可以根据自己的需要进行调整。
<?php
$command = 'echo Hello; sleep 30'; // the command to execute
$timeout = 5; // terminate process if it goes longer than this time in seconds
$cwd = '/tmp'; // working directory of executing process
$env = null; // environment variables to set, null to use same as PHP
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);
// start the process
$process = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
$startTime = time();
$terminated = false;
$output = '';
if (is_resource($process)) {
// process was started
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
// loop infinitely until timeout, or process finishes
for(;;) {
usleep(100000); // dont consume too many resources
$stat = proc_get_status($process); // get info on process
if ($stat['running']) { // still running
if (time() - $startTime > $timeout) { // check for timeout
// close descriptors
fclose($pipes[1]);
fclose($pipes[0]);
proc_terminate($process); // terminate process
$return_value = proc_close($process); // get return value
$terminated = true;
break;
}
} else {
// process finished before timeout
$output = stream_get_contents($pipes[1]); // get output of command
// close descriptors
fclose($pipes[1]);
fclose($pipes[0]);
proc_close($process); // close process
$return_value = $stat['exitcode']; // set exit code
break;
}
}
if (!$terminated) {
echo $output;
}
echo "command returned $return_value\n";
if ($terminated) echo "Process was terminated due to long execution\n";
} else {
echo "Failed to start process!\n";
}
引用文献:proc_open() , proc_close() , proc_get_status() , proc_terminate()
关于php - 在 Linux : exec Behavior, 进程 ID 和 grep 上创建 PHP 在线评分系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9356250/
我有一个文件 test.log。非常大的日志文件。它有不同级别的日志记录。例如,trace , debug , info , warning和 error . 显然trace级别消息只是高速发送垃圾邮
我正在经历一些事情,发现了我无法理解的事情, grep -v grep 这意味着什么?我知道 -v 开关将选择所有不匹配的行。但为什么是第二个grep? 这是完整的命令: ps -ef | grep
我使用 egrep 输出一些带有平台名称的行: XXX | egrep "i686-nptl-linux-gnu$|i686-w64-mingw32$|x86_64-unknown-linux-gnu
grep退出状态部分报告中的手册: EXIT STATUS The exit status is 0 if selected lines are found, and 1 if not
我试图返回多个字符串的第一次出现,即,我想从以下文本中选择第一次出现 1259、3009 和 1589 的行。 ADWN 1259 11:00 B23 ADWN 3009
我猜它不是 Perl 兼容的正则表达式,因为有一种特殊的 grep具体来说就是 PCRE。什么是grep最相似? grep有什么特别的怪癖吗?我需要知道什么? (我习惯了 Perl 和 PHP 中的
有没有办法让 grep 从与搜索表达式匹配的文件中输出“单词”? 如果我想在多个文件中查找“th”的所有实例,我可以这样做: grep "th" * 但是输出会是这样的(粗体是我写的); some-t
我有许多(近 100 个)大 csv 文件,第一列中有 sellID。我知道某些 sellID 在 2 个或更多文件中重复 2 次或多次。是否可以使用 grep 找到所有重复的 sellID(创建映射
我有一个文件中的文件列表。该列表很大,并且文件名是非标准的:这意味着有些文件包含空格、非 ASCII 字符、引号、单引号... 因此,将庞大的文件列表作为参数传递给 grep 并不是一种选择: 因为我
我想在 shell 脚本中使用 grep 和两个变量 var = match cat list.txt | while read word_from_list; do grep "$word_
我有一个大文件,其中每一行都包含一个子字符串,例如 ABC123。如果我执行 grep ABC file.txt 或 grep ABC1 file.txt 我按预期返回这些行,但如果我执行 grep
当我执行以下 grep 时,我得到的结果我无法向自己解释: host:/usr/local/tomcat > grep '-XX:PermSize=256m' * RELEASE-NOTES:
这个问题在这里已经有了答案: grep recursively for a specific file type on Linux (5 个回答) 关闭4年前。 要在子目录中查找所有带有 .out 扩
有什么方法可以让我在搜索某些东西时使用 grep 忽略某些文件,相当于 svnignore 或 gitignore 的东西?我通常在搜索源代码时使用类似的东西。 grep -r something *
有没有办法让 grep 从匹配搜索表达式的文件中输出“单词”? 如果我想在多个文件中找到“th”的所有实例,我可以这样做: grep "th" * 但是输出会是这样的(粗体是我的); some-tex
我是 awk/sed 的完全菜鸟,所以如果我在这里遗漏了一些明显的东西,请原谅我。 基本上我正在尝试做一个嵌套的 grep,即类似于: grep $value `exim -Mvh $(`exim -
我正在尝试编写下载 node.js source 的脚本和 corresponding SHASUMS256.txt ,校验和,grep OK,不返回任何结果,使用 grep 的 -q 标志成功退出代
在 grep "str"* 这是否意味着 grep 执行 grep 的所有内容? 那么 grep -r "str". 的结果比前一个多 最佳答案 当您运行 grep str * 时,shell 将扩展
我正在尝试 grep 文件以查找匹配项的确切出现,但我也得到了更长的虚假匹配项: grep CAT1717O99 myfile.txt -F -w 输出: CAT1717O99 CAT1717O99
我有一个文件,其中包含我希望通过未指定分析运行的标识符(每行一个)。如果一切运行正常,分析将输出具有相同标识符的另一个列表(不一定按相同顺序)。 然而,事实证明,对某些输入标识符没有进行分析,并且这些
我是一名优秀的程序员,十分优秀!