我的回答的三个主要方面
exec函数使用不当。
看看the man pages。首先,exec 函数的签名是:
string exec ( string $command [, array &$output [, int &$return_var ]] )
所以exec 最多可以接受 3 个参数。它返回命令输出的最后一行,就像文档中的状态一样清楚:
命令结果的最后一行。如果您需要执行命令并将命令中的所有数据直接传回而不受任何干扰,请使用 passthru() 函数。
要获取执行命令的输出,请务必设置并使用输出参数。
所以在你的情况下:
$lastLine = exec($command, $fullOutput, $status);
是您正在寻找的。如果$status 是0 以外的任何else,则您的命令不成功。这就是您应该检查以做出相应反应的内容。
任何命令的完整输出都可以在 $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-config 或 mysql_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 *。这意味着您必须致电escapeshellcmd 或escapeshellarg。两者都将禁止我传递有效的论点,即:
`mysql_config --libs --cflags`
其中包含反引号,因此将被转义。
坦率地说,我很难理解这个练习的意义......而且我仍然遗漏了很多内容:编译(更不用说运行)用户提供的代码的危险例如,在您的机器上,不容忽视。你不能只编译代码,然后在你的服务器上运行它:内存泄漏、段错误……哎呀,纯 evil 代码都在你的服务器上编译 unchecked 如果这是您拥有的代码。真的,为自己省去很多眼泪,并包含一个加载键盘或类似服务的 iframe...
回顾:
- 总是检查 man 的函数,看看你是否得到了它返回的所有信息
- 检查实际执行命令的用户的权限和运行时
- 永远不要相信网络,不要盲目地假设人们会提交有效、无害的代码供您编译。
- 不要重新发明轮子:编译服务是存在的,只需转发那些(但要先征求许可)