exec():在 Windows 中引用完整命令 [英] exec(): quoting full command in Windows

查看:39
本文介绍了exec():在 Windows 中引用完整命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个 Web 应用程序,它使用 exec() 来运行外部程序.程序路径是可配置的,并且可以预期其名称中有空格.众所周知,Windows 命令提示符接受文件名或参数中的空格,您只需要将它们双引号:

I've written a web application that makes use of exec() in order to run an external program. The program path is configurable and can be expected to have spaces on its name. As we all know, the Windows command prompt accepts spaces in file names or parameteres, you just have to double quote them:

C:\>C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe
"C:\Archivos" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.

C:\>"C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe"
GraphicsMagick 1.3.12 2010-03-08 Q16 http://www.GraphicsMagick.org/

到目前为止一切顺利.我面临的问题是 exec() PHP 函数本身的使用.某些 Windows 服务器要求您将完整命令 (程序 + 参数) 括在双引号中:

So far so good. The issue I'm facing is the usage of the exec() PHP function itself. Certain Windows servers require that you enclose the full command (program + arguments) in double quotes:

exec('""C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" version"');

... 和其他 Windows 服务器要求使用双引号:

... and other Windows servers require not to use double quotes:

exec('"C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" version');

我可以读取 PHP_OS 常量来检测服务器是否运行 Windows,但我不知道引号背后的规则是什么,或者不是引号主题.如果 PHP 手册中有解释,我找不到它.

I can read the PHP_OS constant to detect whether the server runs Windows but I don't know what's the rule behind the quotes or not quotes subject. It if's explained in the PHP manual I cannot find it.

是否可以通过编程方式确定是否需要引号,这样我就不需要手动配置应用程序的每个实例?

Is is possible to determine programmatically if quotes are needed so I don't need to configure manually each instance of the application?

更新 #1:我被误解了,所以我改写了部分问题,使其更清楚.

Update #1: I was being misunderstood so I've reworded parts of the question to make it more clear.

更新 #2: 我发现了 aPHP 手册中的注释 解释了需要额外引号的确切原因(PHP 发出对 cmd/c 的内部调用).我仍然不知道为什么这会因系统而异.

Update #2: I found a comment in the PHP manual that explains the exact reason why extra quotes are needed (PHP issues an internal call to cmd /c). I still don't know why this appears to be true or false depending on the system.

推荐答案

我写了这个快速而肮脏的解决方法:

I've written this quick and dirty workaround:

<?php

class Thumb{
    const GM_PATH = 'C:\\Archivos de programa\\GraphicsMagick-1.3.12-Q16\\gm.exe';

    /**
     * Quote full command if required by server (program + arguments)
     */
    private static function quoteFullCommand($command){
        // Test only once per script
        static $extra_quotes_required=NULL;

        if( is_null($extra_quotes_required) ){
            if(PHP_OS=='WINNT'){
                // This call will be correct (0) if and only if the server requires extra quotes
                exec('""sort" /?"', $output, $return);
                $extra_quotes_required = $return==0;
            }else{
                $extra_quotes_required = FALSE;
            }
        }
        if($extra_quotes_required){
            $command = '"' . $command . '"';
        }

        return $command;
    }


    /**
     * Return output from "gm version"
     */
    public static function graphicsMagickVersion(){
        $command = escapeshellarg(self::GM_PATH) . ' version ';
        $command = self::quoteFullCommand($command);
        exec($command, $output, $return);

        return trim(implode(PHP_EOL, $output));
    }
}

但是,最好从 PHP 版本或服务器操作系统预测它,因此欢迎提供指向文档或进一步提示的链接.

However, it'd be way better to predict it from PHP version or server OS so links to documentation or further tips are welcome.

更新:我查看了负责在 Windows 中运行外部命令的 PHP 源代码:

Update: I've had a look at the piece of PHP source code that takes care of running external commands in Windows:

http://svn.php.net/viewvc/php/php-src/trunk/TSRM/tsrm_win32.c

以下行将额外的逗号添加到完整命令中:

The following line adds the extra comas to the full command:

sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command); 

根据文件历史记录,该行于 2008 年 5 月 29 日首次添加(r260429):

According to the file history, that line was first added on 29th May 2008 (r260429):

MFH:修复引用命令时的错误和参数在调用过程中被引用to exec,结果是 cmd.exe/c去掉第一个和最后一个引号.

MFH: Fix bug when command is quoted and parameters are quoted during call to exec, the result is that cmd.exe /c strips the first and last quote.

以下 PHP 版本是 5.3.0 和 5.2.7,但该行位于 5_3 分支而不是 5_2 分支.我对 PHP 开发过程不够熟悉,所以我找不到更改日志或指出修复程序移植到哪个 PHP 版本,但我敢说这是 PHP 中的一个错误,它已在 PHP 中修复/5.3.0(但它没有向后移植到 5.2,所以他们没有破坏遗留的东西).

The following PHP releases were 5.3.0 and 5.2.7 but the line is in the 5_3 branch and not in the 5_2 one. I'm not familiar enough with PHP development process so I can't find the changelog or tell out to which exact PHP releases the fix was ported to but I'd dare say that it was a bug in PHP and it was fixed in PHP/5.3.0 (yet it wasn't backported to 5.2 so they didn't break legacy stuff).

所以我的解决方法可能有点矫枉过正.您只需要测试 PHP 操作系统和版本:

So my workaround is probably overkill. You just need to test the PHP OS and version:

if( PHP_OS=='WINNT' && version_compare(PHP_VERSION, '5.3.0', '<') ){
   $command = $command = '"' . $command . '"';
}

这篇关于exec():在 Windows 中引用完整命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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