带有双引号参数的PHP exec()

时间:2012-07-19 21:24:32

标签: php command-line-arguments

我在Windows上使用PHP的exec()函数运行命令时遇到了问题。根据{{​​3}}上的PHP网站发表评论:

  

在Windows中,exec()发出对“cmd / c your_command”的内部调用。

我的命令如下:

"path\to\program.exe" -flag1 attribute1 -flag2 attribute2 -flag3 "attribute3 attribute4"

在我的本地命令提示符中定期执行此命令,没有/ c标志,该命令运行正常。但是,随着/ c标志的引入,命令提示符告诉我“系统找不到指定的路径。”

我认为命令提示符将双引号参数解释为另一个文件的路径,但这是我遇到此问题最远的。

有没有人对如何解决这个问题有任何想法?谢谢!

4 个答案:

答案 0 :(得分:2)

我也遇到过这个问题,其原因确实是内部使用" cmd / c"正如你自己的回答所述。

我做了一些调查,发现这已在PHP 5.3中得到解决,这就是为什么有些评论者无法重现它。

在以下提交中已修复:

https://github.com/php/php-src/commit/19322fc782af429938da8d3b421c0807cf1b848a#diff-15f2d3ef68f383a87cce668765721041R221

对于仍然需要支持PHP 5.2的任何人来说,在您自己的代码中复制修复程序相当容易。而不是:

$cmd = "...any shell command, maybe with multiple quotes...";
exec($cmd);

使用

$cmd = "...any shell command, maybe with multiple quotes...";

if (strtoupper(substr(php_uname('s'), 0, 3)) == "WIN"
    && version_compare(PHP_VERSION, "5.3", "<")) 
{
    $cmd = '"' . $cmd . '"';
}

exec($cmd);

这复制了PHP 5.3及更高版本的行为,其方式与上面链接的提交相同。

请注意,这适用于所有shell命令,而不仅仅是我的示例中使用的exec()。

答案 1 :(得分:1)

我自己想出了答案......

仔细阅读cmd.exe之后的?并试图破译,我注意到一个重要的部分:

  
      
  1. 如果满足以下所有条件,则会保留命令行中的引号字符:

         
        
    • 否/ S开关(带状引号)
    •   
    • 正好两个引号字符
    •   
    • 两个引号字符之间没有特殊字符,其中special是以下之一:&amp; &LT; &gt;()@ ^ |
    •   
    • 两个引号字符之间有一个或多个空格字符
    •   
    • 两个引号字符之间的字符串是可执行文件的名称。
    •   
  2.   
  3. 否则,旧行为是查看第一个字符是否为引号字符,如果是,则删除前导字符并删除命令行中的最后一个引号字符,保留最后一个引号字符后面的任何文本。要取消此行为,请在命令行的开头和结尾使用一组双引号。

  4.   

似乎在任何时候如果有多对引号,引号将从第二对引号中剥离并打开。

一个相关问题:How do I deal with quote characters when using cmd.exe但并不完全相关,因为PHP不会允许你通过在其调用上放置一个/ S标志来修改其exec()命令(这肯定会容易得多)。 / p>

我设法解决了这个问题,直接用chdir()将目录更改为.exe所在的文件夹,然后chdir()返回到我原来的工作目录。这是一个非常hacky的解决方案,考虑到我很幸运,我只有一组使用双引号的参数。如果有人使用双引号有多个参数,我不知道如何解决...

答案 2 :(得分:0)

只是一个猜测(我不熟悉Windows上的PHP):可能会因为"成为""而忽略引号?

"path\to\program.exe" -flag1 attribute1 -flag2 attribute2 -flag3 ""attribute3 attribute4""

无论解决方案是什么,请确保当某种形式的用户输入作为您使用escapeshellarg和/或escapeshellcmd的参数传递给此命令时。

答案 3 :(得分:0)