exec总是返回-1(或127)

Qua*_*mis 12 php linux exec

我在生产服务器上使用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>";
Run Code Online (Sandbox Code Playgroud)

无论我输入什么命令$command,$result总是-1,即使对于不存在的命令......这很奇怪

Rin*_*g Ø 1

假设返回 $result == -1 的系统是基于 Unix 的(我不知道使用相同代码的 Windows 会如何表现)

PHP (5.2.9) exec() 函数不会调用 C exec() 原语(如果无法替换/执行进程,则返回 -1,但此处情况并非如此)。相反,它调用 popen() 创建管道,执行 fork() 并使用您的命令执行 shell。return_value -1 不是 C 原语的直接结果,而是由 PHP 内部构建的,具体取决于命令的处理方式。换句话说,“ls”命令可能已经执行得很好,但例如 PHP 无法正确关闭管道。

查看 ext/standard/exec.c 中的 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;
Run Code Online (Sandbox Code Playgroud)

但是在这种情况下,您将看不到结果,并且日志将显示错误。

稍后,通过以下行设置 return_value

  pclose_return = php_stream_close(stream);
Run Code Online (Sandbox Code Playgroud)

查看 _php_stream_free() (php_stream_close() 是一个被 _php_stream_free() 替换的宏),最有可能返回 -1 的候选者是

  ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC);
Run Code Online (Sandbox Code Playgroud)

它又间接调用 C 原语 pclose()。根据说明书

如果 wait4(2) 返回错误或检测到其他错误,则 pclose() 函数返回 -1。

关闭管道期间似乎检测到错误,但这并不妨碍设置结果数据。要严格查找原因,需要检查操作系统设置和日志、PHP配置和编译参数。

我会推荐

  • 为您的操作系统应用补丁,并可能更新到更新的版本(如果适用),
  • 将 PHP 更新到 5.3.3(目前最新),因为 PHP exec() 代码发生了显着变化。

请注意,版本 5.3 中存在与 PHP suhosin 模块相关的更改,默认情况下增强了运行 PHP 文件时的安全性。