php exec:不返回输出

发布于 2025-01-01 08:53:04 字数 334 浏览 3 评论 0原文

我有这个问题: 在 ISS Web 服务器上,安装了 windows 7 x64 professional、zend 服务器。在 php 下运行此命令:

exec('dir',$output, $err);

$output isempty, $err=1. 所以 exec 没有返回输出,似乎有一些错误。 Php disable_functions 为空,php 未处于安全模式,是标准的,我检查了所有选项。 这似乎是一个普遍的错误,即使在谷歌上搜索也没有给出结果。

请写下每个人的经验和最终的解决方案或解决方法。

I have this problem:
On a ISS web server, windows 7 x64 professional, zend server installed. Running this command under php:

exec('dir',$output, $err);

$output is empty, $err=1. So exec is not returing the output, it seems has some errors.
Php disable_functions is empty, php is not on safe mode, is standard, I check all option.
It seems to be a general errors, even search on google do not give results.

Please write every one his experince and eventual solutions or workarounds.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

冷月断魂刀 2025-01-08 08:53:04

PHP 手册的相关部分有一些帖子,例如这个

我在使用 PHP exec 命令执行任何批处理时遇到问题
文件。执行其他命令(即“dir”)工作正常)。但如果我
执行批处理文件后,我没有收到 exec 命令的任何输出。

我的服务器设置由运行的 Windows Server 2003 服务器组成
IIS6 和 PHP 5.2.3。在此服务器上,我有:

  1. 授予 Internet 用户对 c:\windows\system32\cmd.exe 的执行权限。
  2. 授予每个人 -> 写入批处理文件的目录的完全控制权。
  3. 授予每个人 -> 对整个 c:\cygwin\bin 目录及其内容的完全控制权。
  4. 授予互联网用户“批量登录”权限。
  5. 指定正在执行的每个文件的完整路径。
  6. 测试了从服务器上的命令行运行的这些脚本,它们工作得很好。
  7. 确保 %systemroot%\system32 位于系统路径中。

事实证明,即使服务器上具备上述所有内容,我
必须在 exec 调用中指定 cmd.exe 的完整路径。

当我使用调用时:$output = exec("c:\\windows\\system32\\cmd.exe
/c $batchFileToRun");

然后一切正常。在我的情况下, $batchFileToRun
批处理文件的实际系统路径(即调用的结果
真实路径())。

还有一些关于 execshell_exec 手册页。也许按照它们进行操作会让它启动并为你工作。

There are a few posts to the relevant sections of the PHP Manual such as this one:

I was having trouble using the PHP exec command to execute any batch
file. Executing other commands (i.e., "dir") works fine). But if I
executed a batch file, I receieved no output from the exec command.

The server setup I have consists of Windows Server 2003 server running
IIS6 and PHP 5.2.3. On this server, I have:

  1. Granted execute permissions to the Internet User on c:\windows\system32\cmd.exe.
  2. Granted Everyone->Full Control to the directory in which the batch file is written.
  3. Granted Everyone->Full Control on the entire c:\cygwin\bin directory and its contents.
  4. Granted the Internet User "log on as batch" permissions.
  5. Specified the full path to each file being executed.
  6. Tested these scripts running from the command line on the server and they work just fine.
  7. Ensured that %systemroot%\system32 is in the system path.

It turns out that even with all of the above in place on the server, I
had to specify the full path to cmd.exe in the exec call.

When I used the call: $output = exec("c:\\windows\\system32\\cmd.exe
/c $batchFileToRun");

then everything worked fine. In my situation, $batchFileToRun was the
actual system path to the batch file (i.e., the result of a call to
realpath()).

There are a few more on both the exec and shell_exec manual pages. Perhaps following through them will get it up and working for you.

青巷忧颜 2025-01-08 08:53:04

从诸如 dir 之类的命令中获得零输出的主要原因是 dir 不存在。它是命令提示符的一部分,这个特定问题的解决方案很好,就在这个页面的某个地方。

您可以通过按 WIN + R,然后输入 dirstart 来找到这一点 - 会出现一条错误消息!

不管这听起来有多么反常,我发现在 Windows 中执行任何与进程相关的操作的最可靠方法是使用组件对象模型。你说让我们分享我们的经验,对吗?

$me 听到人们在笑

恢复镇静了吗?

因此,首先我们将创建 COM 对象:

$pCOM = new COM("WScript.Shell");

然后,我们将只运行需要运行的内容。

$pShell = $pCom->Exec("C:\Random Folder\Whatever.exe");

凉爽的!现在,它将挂起,直到该二进制文件中的所有内容都完成为止。所以,我们现在需要做的就是获取输出。

$sStdOut = $pShell->StdOut->ReadAll;    # Standard output
$sStdErr = $pShell->StdErr->ReadAll;    # Error

您还可以做一些其他事情 - 找出进程 ID、错误代码等。尽管这个示例< /a> 适用于 Visual Basic,它基于相同的方案。

The main reason you get zero output from a command such as dir is because dir doesn't exist. It's part of the command prompt, and the solution to this particular problem is well, in this page somewhere.

You can find this out by pressing WIN + R, and typing in dir or start for that matter - an error message appears!

However perverse this may sound, I've found that the most reliable way to do anything process related in Windows is with using the Component Object Model. You said for us to share our experiences, right?

$me hears people laughing

Regained your composure yet?

So, first we'll create the COM object:

$pCOM = new COM("WScript.Shell");

Then, we'll just run what ever needs to be run.

$pShell = $pCom->Exec("C:\Random Folder\Whatever.exe");

Cool! Now, that'll hang until everything's finished in that binary. So, what we need to do now is grab the output.

$sStdOut = $pShell->StdOut->ReadAll;    # Standard output
$sStdErr = $pShell->StdErr->ReadAll;    # Error

There's some other things you can do - find out what was the process ID, error code, etc. Although this example is for Visual Basic, it's based on the same scheme.

听不够的曲调 2025-01-08 08:53:04

编辑:经过一些研究,我看到执行 DIR 命令的唯一方法是这样的:

cmd.exe /c dir c:\

所以你可以尝试使用我的解决方案:

$command = 'cmd.exe /c dir c:\\';

你也可以使用 proc_open 函数,它使你可以访问 stderr、返回状态代码和 stdout。

    $stdout = $stderr = $status = null;
    $descriptorspec = array(
       1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
       2 => array('pipe', 'w') // stderr is a pipe that the child will write to
    );

    $process = proc_open($command, $descriptorspec, $pipes);

    if (is_resource($process)) {
        // $pipes now looks like this:
        // 0 => writeable handle connected to child stdin
        // 1 => readable handle connected to child stdout
        // 2 => readable handle connected to child stderr

        $stdout = stream_get_contents($pipes[1]);
        fclose($pipes[1]);

        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);

        // It is important that you close any pipes before calling
        // proc_close in order to avoid a deadlock
        $status = proc_close($process);
    }

    return array($status, $stdout, $stderr);

与 popen 或 exec 等其他函数相比,proc_open 的有趣之处在于它提供了特定于 Windows 平台的选项,例如:

suppress_errors (windows only): suppresses errors generated by this function when it's set to TRUE
bypass_shell (windows only): bypass cmd.exe shell when set to TRUE

EDIT: After a few researchs, the only way i see to execute the DIR command is like that:

cmd.exe /c dir c:\

So you can try my solution using:

$command = 'cmd.exe /c dir c:\\';

You can use proc_open function too, which gives you access to stderr, return status code and stdout.

    $stdout = $stderr = $status = null;
    $descriptorspec = array(
       1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
       2 => array('pipe', 'w') // stderr is a pipe that the child will write to
    );

    $process = proc_open($command, $descriptorspec, $pipes);

    if (is_resource($process)) {
        // $pipes now looks like this:
        // 0 => writeable handle connected to child stdin
        // 1 => readable handle connected to child stdout
        // 2 => readable handle connected to child stderr

        $stdout = stream_get_contents($pipes[1]);
        fclose($pipes[1]);

        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);

        // It is important that you close any pipes before calling
        // proc_close in order to avoid a deadlock
        $status = proc_close($process);
    }

    return array($status, $stdout, $stderr);

The interesting part with proc_open, compared to other functions like popen or exec, is that it provides options specific to windows platform like:

suppress_errors (windows only): suppresses errors generated by this function when it's set to TRUE
bypass_shell (windows only): bypass cmd.exe shell when set to TRUE
老旧海报 2025-01-08 08:53:04

试试这个:

shell_exec('dir 2>&1');

它在启用了 UAC 的 Windows 8.1 64 位上运行良好。

Try this:

shell_exec('dir 2>&1');

It works fine on Windows 8.1 64bits with UAC enabled.

此生挚爱伱 2025-01-08 08:53:04

我知道我已经选择了一个答案,因为我必须这样做,但我仍然不明白为什么它不能在我的机器上工作,但我使用另一种方法找到了一个后备(使用 proc_open)解决方案:

public static function exec_alt($cmd)
{
    exec($cmd, $output);
    if (!$output) {
        /**
         * FIXME: for some reason exec() returns empty output array @mine,'s machine.
         *        Somehow proc_open() approach (below) works, but doesn't work at
         *        test machines - same empty output with both pipes and temporary
         *        files (not we bypass shell wrapper). So use it as a fallback.
         */
        $output = array();
        $handle = proc_open($cmd, array(1 => array('pipe', 'w')), $pipes, null, null, array('bypass_shell' => true));
        if (is_resource($handle)) {
            $output = explode("\n", stream_get_contents($pipes[1]));
            fclose($pipes[1]);
            proc_close($handle);
        }
    }
    return $output;
}

希望这对某人有帮助。

I know I have choosen an answer as I must do it but I still do not understand why it wont work on my macchine but I found a fallback (using proc_open) solution using another method:

public static function exec_alt($cmd)
{
    exec($cmd, $output);
    if (!$output) {
        /**
         * FIXME: for some reason exec() returns empty output array @mine,'s machine.
         *        Somehow proc_open() approach (below) works, but doesn't work at
         *        test machines - same empty output with both pipes and temporary
         *        files (not we bypass shell wrapper). So use it as a fallback.
         */
        $output = array();
        $handle = proc_open($cmd, array(1 => array('pipe', 'w')), $pipes, null, null, array('bypass_shell' => true));
        if (is_resource($handle)) {
            $output = explode("\n", stream_get_contents($pipes[1]));
            fclose($pipes[1]);
            proc_close($handle);
        }
    }
    return $output;
}

Hope this helps someone.

心不设防 2025-01-08 08:53:04

我遇到了同样的问题,在花了很多时间和一杯咖啡之后,

在 Windows 7 中禁用用户帐户控制 (UAC)
短路径:P
C:\Windows\System32\UserAccountControlSettings.exe
并选择“从不通知”

并且 php exec() 工作正常!

我用:
Apache 版本:2.2.11
PHP 版本:5.2.8
Windows 7 SP1 32 位

致以诚挚的问候! :D

I was the same problem and after spend a lot of hours and cup of coffee

Just Disabling User Account Control (UAC) in Windows 7
short path :P
C:\Windows\System32\UserAccountControlSettings.exe
and select "Never notify"

and php exec() works fine!

I use:
Apache Version : 2.2.11
PHP Version : 5.2.8
Windows 7 SP1 32bit

Best regards! :D

日裸衫吸 2025-01-08 08:53:04

如果您在 Windows 计算机上并尝试运行如下所示的可执行文件:

shell_exec("C:\Programs\SomeDir\DirinDir\..\DirWithYourFile\YourFile.exe");

并且没有输出或您的文件未启动,那么您应该尝试以下操作:

chdir("C:\Programs\SomeDir\DirinDir\..\DirWithYourFile");
shell_exec("YourFile.exe");

它应该可以工作。

如果使用脚本当前所在文件夹的相对路径,这尤其方便,例如:

$dir = dirname(__FILE__).'\\..\\..\\..\\web\\';

如果需要运行其他程序,请不要忘记 chdir() 返回原始文件夹。

If you are on Windows machine and trying to run an executable like this:

shell_exec("C:\Programs\SomeDir\DirinDir\..\DirWithYourFile\YourFile.exe");

and there is no output or your file isn't started, then you should try this:

chdir("C:\Programs\SomeDir\DirinDir\..\DirWithYourFile");
shell_exec("YourFile.exe");

It should work.

This is particularly handy if one is using relative path from folder where script currently is being located, for example:

$dir = dirname(__FILE__).'\\..\\..\\..\\web\\';

And don't forget to chdir() back to originating folder if you need to run other programs.

旧时模样 2025-01-08 08:53:04

出于安全目的,您的服务器可能限制对“exec”命令的访问。在这种情况下,也许您应该联系托管公司以删除此限制(如果有)。

For security purposes, your server may have restricted access to "exec" command. In this case, maybe you should contact the hosting company to remove this restriction (if there is one).

关于从前 2025-01-08 08:53:04

您可以检查 IIS 用户对 cmd.exe 的权限

cacls C:\WINDOWS\system32\cmd.exe

如果输出中出现类似 (COMPUTERNAME=您的计算机名称) 的行:

C:\WINDOWS\system32\cmd.exe COMPUTERNAME\IUSR_COMPUTERNAME:N

则表示该用户没有执行 cmd 的权限。

您可以使用命令添加执行权限:

cacls C:\WINDOWS\system32\cmd.exe /E /G COMPUTERNAME\IUSR_COMPUTERNAME:R

You can check permisssions of IIS User to cmd.exe

cacls C:\WINDOWS\system32\cmd.exe

If in output is line like (COMPUTERNAME=your computer name):

C:\WINDOWS\system32\cmd.exe COMPUTERNAME\IUSR_COMPUTERNAME:N

It means that user has no rights to execute cmd.

You can add execute permissions with command:

cacls C:\WINDOWS\system32\cmd.exe /E /G COMPUTERNAME\IUSR_COMPUTERNAME:R
谷夏 2025-01-08 08:53:04

看看Apache error_log,也许你会发现错误信息。

另外,您可以尝试使用 popen 而不是 exec。它提供了更多控制,因为您可以将进程启动与输出读取分开:

$p = popen("dir", "r");
if (!$p)
    exit("Cannot run command.\n");
while (!feof($p))
    echo fgets($p);
pclose($p);

Take a look at Apache error_log, maybe you'll find the error message.

Also, you can try using popen instead of exec. It gives more control because you can separate process start from output read:

$p = popen("dir", "r");
if (!$p)
    exit("Cannot run command.\n");
while (!feof($p))
    echo fgets($p);
pclose($p);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文