【问题标题】:PHP exec() and spaces in pathsPHP exec() 和路径中的空格
【发布时间】:2011-07-26 06:23:54
【问题描述】:

我正在 PHP 应用程序中执行以下操作:

  $source = '/home/user/file.ext';
  $output_dir = $this->setOutputString();

  chdir('/home/ben/xc/phplib/bgwatcher-2011a/a01/');
  exec('php bin/createjob.php $source $output_dir', $output);

  return $output[0];

问题是这样的:我可以控制$source,但不能控制$output_dir,这是一个旧的Windows 文件系统,并且路径中有空格。一个例子$output_dir 是:

/home/vol1/district id/store id/this_is_the_file.html

将输出字符串插入exec()函数时,我都尝试了:

addslashes($output_dir)'"' . $output_dir . '"' 转义整个输出字符串。在第一种情况下,路径被连接到:

/home/vol1/districtthis_is_the_file.html

... 第一个空格和文件名之间的所有内容都被删除。在第二种情况下,exec() 似乎扔了一只鞋并且无法正常执行 - 不幸的是,错误消息在机器中丢失了 - 如果绝对必要,我可以提供它,但我也有时间限制找到解决办法。

这里有什么解决方案?我是sprintf() exec() 的整个字符串吗?我很困惑为什么addslashes 不能正常工作以逃避空格,我认为它与 exec() 的清理有关,但我找不到任何文档来支持它。

更新:我尝试了 escapeshellarg() 和 preg_replace() 都没有成功。进一步考虑这一点,我是否需要双重逃避路径?还是逃避路径和命令?如果路径被 exec() 转义一次,并且在 PHP 执行命令之前被 PHP 转义一次,我是否需要考虑这两种转义?或者这不是它的工作原理?

【问题讨论】:

    标签: php path exec


    【解决方案1】:

    根据PHP docs

    在数据库查询等中需要引用的字符之前返回一个带有反斜杠的字符串。这些字符是单引号('),双引号("),反斜杠()和NUL(NULL字节)强>。

    看起来你必须自己 preg_replace 空格。

    编辑:

    尽管这是另一个讨论的主题,但如果性能是一个问题,那么在进一步研究之后,似乎str_replace 实际上比@987654324快了不少@:

    标记为“str_replace()”的测试是 快了 0.9053 秒(花了 10.3% 的时间。)

    第一次测试耗时 1.0093 秒。 (preg_replace)

    第二次测试耗时 0.104 秒。 (str_replace)

    Benchmark found here.

    【讨论】:

    • 只是为了检查我缺少 RegExp-fu,这是正确的吗? preg_replace("/\s/", "\\ ", $this->output_dir);
    • 为了提高速度,或者只是为了与众不同,可以使用str_replace()?
    • 当我尝试这个时,字符串仍然在第一个空格处被截断,并且 createjob.php 失败。地狱的钟声 - 我想我需要双重逃避这个!或者转义整个命令...
    【解决方案2】:

    来自 PHP 文档 (here),

    在需要在数据库查询等中引用的字符之前返回一个带有反斜杠的字符串。这些字符是单引号 (')、双引号 (")、反斜杠 () 和 NUL(NULL 字节)。

    这不会对空格做任何事情。您需要做的是使用str_replace() 添加斜杠,如下所示:

    $new_string = str_replace(" ", "\\ ", $old_string);

    【讨论】:

      【解决方案3】:

      我不相信addslashes() 对空格做任何事情。 escapeshellarg() 可能是您想要的。 Docs on escapeshellarg

      【讨论】:

      • 我尝试在 $output_dir 字符串上使用 escapeshellarg(),但字符串在遇到的第一个空格处仍然被截断。
      【解决方案4】:

      我之前在 Windows 和 Linux 主机上都将 exec() 与带空格的路径一起使用,在这两种情况下引用路径对我来说都非常有效。

      也就是说,如果您无法控制 shell 参数的安全性,总是首先通过escapeshellarg() 运行它!

      【讨论】:

        【解决方案5】:

        你可以很好地使用 shell 引号,因为这是所有 exec 命令运行的内容:

        exec("php bin/createjob.php '$source' '$output_dir'", $output);
        

        顺便说一句,它不仅适用于参数,还适用于命令本身:

        exec('"/bin/echo" "one parameter"');
        

        还是使用escapeshellcmd()

        【讨论】:

          【解决方案6】:

          将 exec() 与 soffice(LibreOffice) 一起使用时,这对我有用:

          $file_name = "Some, file name.xlsx";
          exec('/usr/bin/soffice --headless --convert-to pdf '."'".$file_name."'".' 2>&1', $output, $r);
          

          【讨论】:

            猜你喜欢
            • 2012-10-29
            • 1970-01-01
            • 1970-01-01
            • 2012-02-26
            • 2011-05-12
            • 1970-01-01
            • 2015-02-08
            • 2016-01-09
            • 1970-01-01
            相关资源
            最近更新 更多