我在生产服务器上使用php 5.2.9,似乎exec()函数表现为“非标准”。
如果我运行exec("ls", $output, $return_var)
,则$output
将按预期包含当前文件夹中的文件列表,但$return_var
将按预期设置为-1而不是0。
我使用$return_var
来确定命令在哪里成功完成,并且在测试的每个其他服务器上都按预期工作:)
有人遇到过这样的情况吗?
编辑:
<?php
$command = "asd";
$t1 = time();
$output = Array();
$result = -5;
$r = exec($command, $output, $result);
$t2 = time();
echo "<pre>";
var_export(Array(
'command'=>$command,
'result'=>$result,
'output'=>implode("\n", $output),
'r'=>$r,
't2-t1'=>$t2-$t1,
));
echo "</pre>";
无论我在$command
中输入什么命令,$result
总是-1,即使是不存在的命令......这很奇怪
答案 0 :(得分:1)
假设系统返回$ result == -1是基于Unix的(我不知道如何用相同的代码表现Windows)
PHP(5.2.9)exec()函数不调用C exec()原语(如果它不能替换/执行进程则返回-1,这不是这里的情况)。相反,它调用popen()创建管道,执行fork()并使用您的命令执行shell。 return_value,-1不是C原语的直接结果,而是由PHP在内部构建,具体取决于命令的处理方式。换句话说,“ls”命令可能已经很好地执行,而例如PHP无法正确关闭管道。
查看C代码,在ext / standard / exec.c中,返回代码为-1的原因可能有两个,由错误触发;第二个发生在popen()调用之后
fp = VCWD_POPEN(cmd_p, "r");
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd);
goto err;
}
// ...
err:
pclose_return = -1;
goto done;
但是在这种情况下,您将看不到结果,并且日志会显示错误。
稍后,return_value通过
行设置 pclose_return = php_stream_close(stream);
查看_php_stream_free()(php_stream_close()是一个用_php_stream_free()替换的宏),最有可能返回-1的候选者是
ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC);
反过来间接调用C原语pclose()。根据手册
如果wait4(2)返回错误,或者检测到其他错误,则pclose()函数返回-1。
在关闭管道期间似乎检测到错误,这不会阻止设置结果数据。要严格查找原因,需要检查操作系统设置和日志,PHP配置和编译参数。
我会推荐
请注意,版本5.3中的PHP suhosin模块有相关更改,默认情况下会在运行PHP文件时增强安全性。
答案 1 :(得分:0)
确保您没有在safe mode中运行,并且该exec未在php.ini中的disable_functions
中列出。
这两种情况都会导致exec()
失败,但我认为会引发通知。
答案 2 :(得分:0)
我们可以得到strace'the PHP进程的输出吗?这可能包含我们正在寻找的答案。
5.2.14也是5.2系列的最新产品。你有机会尝试吗?如果您在共享托管服务提供商上,您仍然可以让它在本地运行以查看行为是否发生变化。
答案 3 :(得分:0)
我在两台不同的Linux PC上试用了它(PHP 5.03和PHP 5.2.10) - 两者都运行得很好。
PHP 5.2.10示例:
array (
'command' => 'ls',
'result' => 0,
'output' => 'atmail
...
vhosts',
'r' => 'vhosts',
't2-t1' => 0,
)
我会仔细检查php.ini文件中任何与安全相关的指令,检查您尝试搜索的目录中的文件权限,看看是否有SELinux和/或AppArmor正在运行。
您也可以考虑使用opendir()/ readdir()。
恕我直言.. PSM
答案 4 :(得分:0)
似乎问题已由服务器管理员修复。我不知道他做了什么,但它现在有效。问题是服务器管理员非常“严格”,也许他对某些系统配置有一点限制。例如,从SSH shell中我看不到安装php二进制文件的位置。我很确定SSH shell是chrooted,还有webserver(或者它们是完全不同的服务器,但我不知道如何在不使用任何类型的mount的情况下实现这一点)......