exec总是返回-1(或127) [英] exec always returns -1 (or 127)

查看:277
本文介绍了exec总是返回-1(或127)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在生产服务器上使用php 5.2.9,看来exec()函数的行为是非标准".

I'm using php 5.2.9 on a production server, and it seems that the exec() function behaves "non-standard".

如果我运行exec("ls", $output, $return_var),则$output将按预期包含当前文件夹中的文件列表,但$return_var将按预期设置为-1而不是0. 我正在使用$return_var来确定命令在何处成功完成,并且在每台经过测试的其他服务器上都可以按预期进行:)

If i run exec("ls", $output, $return_var) then $output will contain the list of files in the current folder as expected, but $return_var will be set to -1 instead of 0, as expected. I'm using the $return_var to determine wherever the command finished successfully, and on every other server tested this works as expected:)

有人遇到过这样的情况吗?

Anyone ever hit a situation like this?

<?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,即使对于不存在的命令...这也很奇怪

Whatever command i put in $command, $result will always be -1, even for nonexistent commands...this is very weird

推荐答案

假定系统返回的$ result == -1是基于Unix的(我不知道使用相同代码的Windows的行为)

Assuming the system returning $result == -1 is Unix-like based (I don't know how would behave Windows with the same code)

PHP(5.2.9)exec()函数不会调用C exec()原语(如果无法替换/执行该过程,则返回-1,此处不是这种情况).相反,它将调用popen()来创建管道,执行fork()并使用命令执行Shell. return_value -1不是C语言原语的直接结果,而是由PHP在内部构建的,具体取决于命令的处理方式.换句话说,"ls"命令可能执行得很好,而例如PHP无法正确关闭管道.

The PHP (5.2.9) exec() function does not call the C exec() primitive (which returns -1 if it could not replace/execute the process, which is not the case here). Instead it calls popen() that creates a pipe, performs a fork() and execute a shell with your command. The return_value, -1, is not the direct result from a C primitive, but rather is built by PHP internally, depending on the way your command was processed. In other terms, the "ls" command may have been well executed, while for instance PHP could not close properly the pipe.

查看ext/standard/exec.c中的C代码,由于错误触发返回代码为-1可能有两个原因;第二个发生在popen()调用之后

Looking at the C code, in ext/standard/exec.c, there could be two reasons why the return code is -1, triggered by an error ; the 2nd one happens after the popen() call

  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;

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

However in this case, you wouldn't see the result, and the log would show an error.

稍后,return_value是通过行设置的

Later, the return_value is set via the line

  pclose_return = php_stream_close(stream);

查看_php_stream_free()(php_stream_close()是用_php_stream_free()替换的宏),最有可能返回-1的候选对象是

Looking at _php_stream_free() (php_stream_close() is a macro replaced with _php_stream_free()), the most likely candidate that could return -1 is

  ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC);

依次反过来调用C原语pclose().根据手册

Which in turn calls indirectly the C primitive pclose(). According to the manual

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

The pclose() function returns -1 if wait4(2) returns an error, or some other error is detected.

在关闭管道期间似乎检测到一个错误,这不会阻止设置结果数据.要严格查找原因,需要检查操作系统设置和日志,PHP配置和编译参数.

There seem to be an error detected during the closing of the pipe, that does not prevent the resulting data to be set. To find the reason rigorously, one need to check the operating system setup and logs, the PHP configuration and compilation parameters.

我会推荐

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

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

Be aware that there were changes related to the PHP suhosin module in the version 5.3 that enhance by default the security when running PHP files.

这篇关于exec总是返回-1(或127)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆