php - 如何从 php 脚本运行 linux 命令来编译 c 程序

标签 php linux

我正在尝试为 c 编程做一个在线评委。当用户输入 c 代码并提交时,我的表单重定向到judge.php,这是表单的操作文件。
这是我在judge.php中写的

<?php 
$text=$_POST['code'];
//echo $text;

$var_str = var_export($text, true);

file_put_contents('code.c', $text);

$ans=exec('pwd');

$ans= exec('gcc code.c');

echo $ans;

?>

我已经在 $text 中捕获了用户输入并将其写入 c 文件(code.c)。到现在为止,还好。
但是exec(gcc code.c)不工作,不提供任何输出。我尝试了其他 linux commnads,如 pwd、date 等。它们工作正常。这可能是什么原因以及如何解决?
这不是我尝试过的目录问题 exec(pwd)并将输出与代码所在的目录相同。
我试图从终端运行相同的 code.c 文件,它运行良好。因此,这也不是“许可”问题。

还有一件事,如果任何 exec() 命令无法正常工作,如何回显生成的错误消息?

从下面的答案中得到建议后,我尝试了 $cmd="gcc -std=c99 code.c -g -Wall mysql_config --libs --cflags -o db_obj.o --pedantic";
exec($cmd,$out,$status);

但它也不起作用。返回的状态为 1

很可能是权限问题。 “whoami”没有人说。请告诉如何将所有者从nobody更改为root或如何分配从nobody执行gcc的权限

最佳答案

我的回答的三个主要方面exec 使用不当功能。
the man pages .一、exec函数的签名是:

string exec ( string $command [, array &$output [, int &$return_var ]] )
所以exec最多可以接受 3 个参数。它返回命令输出的最后一行,就像文档状态一样清楚:

The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

To get the output of the executed command, be sure to set and use the output parameter.


所以在你的情况下:
$lastLine = exec($command, $fullOutput, $status);
是你要找的。如果 $status是不是 0 ,您的命令不成功。这就是您应该检查以做出相应 react 的内容。
任何命令的完整输出都可以在 $fullOutput 中找到。作为逐行数组。
输出如:
all went well
except for this
$fullOutput 中看起来像这样大批:
array('all went well', 'except for this');
权限可能仍然是一个问题。
您说权限不太可能是问题的原因,因为您可以运行 gcc从命令行。一切都很好,但是什么用户在服务器上运行 PHP 脚本?
在网络服务器的情况下,该用户通常被称为nobody、apache 或其他东西,并且该用户很可能是。不是 允许运行gcc .是 PHP 运行它设置的任何默认 shell(可能是 bash)的新实例,并且是 PHP 的用户登录到该 shell,并且是那个用户正在调用 gcc ...
知道你是谁,你属于什么群体。尝试将此添加到您的脚本中:
echo 'Script is running under user: ', exec('whoami'), '<br>', PHP_EOL;
echo 'member of the following groups: ', exec('groups'), '<br>', PHP_EOL;
在你问之前:是的,那些是逗号......不需要连接,你可以将多个变量/值传递给 echo , 用逗号分隔。它实际上更快(将其视为 C++ 的 std::cout << some_var << another_var; )
一般问题+安全
这一切都说了又做了:从 php 脚本编译 C 代码并不像您想象的那么简单。假设我要写这个:
#include <stdio.h>
#include <time.h>
int main ( void )
{
    time_t t = time(NULL);
    if (t%2)
    {
        float val = (float) t/2.0;
        //do stuff with float...
    }
    else
    {
        unsigned long long val = t/2;
        //do stuff with unsigned long long...
    }
}
您的 gcc test.c命令将失败,因为您未能传递参数 -std=c99 , 例如。
如果我想要一个脚本来编译给定的文件,我还希望该脚本允许我选择编译代码时使用的参数-g , -Wall而且,更不用说:cflags 和 libs(pkg-configmysql_config --cflags --libs 的输出,以我最近使用的一个具体示例为例)。
基本上,你的脚本根本无法处理我想用类似的命令编译一些东西
gcc -std=c99 code.c -g -Wall `mysql_config --libs --cflags` -o db_obj.o --pedantic
这仍然是许多编译命令的简化版本,尤其是在调试正在开发的代码时。对于稳定版本,您可能会放弃 -g--pedantic ,但你明白我的意思...
想想这意味着什么,允许用户传递一组 cli 参数以及代码。他们可能会传递像 -DSOME_MACRO 这样的参数。或 -O0 ,这意味着它们也可能通过 -O0 && rm -Rf * .这意味着您必须调用 escapeshellcmdescapeshellarg .两者都将禁止我传递有效的论点,即:
`mysql_config --libs --cflags`
其中包含反引号,因此将被转义。
坦率地说,我很难理解这个练习的意义......而且我仍然遗漏了很多:例如,在您的机器上编译(更不用说运行)用户提供的代码的危险不是被忽视。你不能只编译代码,然后在你的服务器上运行它:内存泄漏、段错误……哎呀,纯邪恶的代码都在你的服务器上编译 未选中 如果这是您拥有的代码。真的,为自己省去很多眼泪,并包含一个加载键盘或一些类似服务的 iframe...

回顾:
  • 总是检查 man 的函数,看看你是否得到了它返回的所有信息
  • 检查实际执行命令的用户的权限和运行时间
  • 永远不要相信网络,不要盲目地假设人们会提交有效的、无害的代码供你编译。
  • 不要重新发明轮子:编译服务是存在的,只是转发那些(但要先征求许可)
  • 关于php - 如何从 php 脚本运行 linux 命令来编译 c 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21136328/

    相关文章:

    php - MySQL 中两个日期列之间的差异

    php - Tcpdf多重签名

    java - Java 7 Hotspot JVM 是否在 Linux 上使用 SIGRT*?

    linux - Unix Bash 脚本空文件条件

    c - 为什么 linux 内核使用非标准 C 编码(gcc 特定功能)?

    php - 防止通过表单覆盖文件上传和MySQL记录?

    php - 使用 codeigniter 设置坐标 phpexcel

    php - JWT 认证 Laravel

    linux - 共享库如何在 64 位/32 位混合系统中工作?

    linux - 一些 linux 程序中奇怪的描述符关闭