我必须修复这个小虫子。首先,我们来谈谈一个小事实: 在Windows上的CLI中,除非转义,否则无法运行路径中包含空格的程序:
C:\>a b/c.bat
'a' is not recognized as an internal or external command,
operable program or batch file.
C:\>"a b/c.bat"
C:\>
我在PHP中使用proc_open ... proc_close来运行进程(程序),例如:
function _pipeExec($cmd,$input=''){
$proc=proc_open($cmd,array(0=>array('pipe','r'),
1=>array('pipe','w'),2=>array('pipe','w')),$pipes);
fwrite($pipes[0],$input);
fclose($pipes[0]);
$stdout=stream_get_contents($pipes[1]); // max execusion time exceeded ssue
fclose($pipes[1]);
$stderr=stream_get_contents($pipes[2]);
fclose($pipes[2]);
$rtn=proc_close($proc);
return array(
'stdout'=>$stdout,
'stderr'=>$stderr,
'return'=>(int)$rtn
);
}
// example 1
_pipeExec('C:\\a b\\c.bat -switch');
// example 2
_pipeExec('"C:\\a b\\c.bat" -switch');
// example 3 (sounds stupid but I had to try)
_pipeExec('""C:\\a b\\c.bat"" -switch');
示例1
示例2
示例3
所以你看,无论是(双引号还是双引号)代码都失败了。 是我还是我错过了什么?
答案 0 :(得分:4)
最不幸的是,修复程序没有按预期工作,但是Pekka的第一个建议给了我一个想法:
$file='C:\a b\c';
$cmdl='/d /b /g';
if(strtolower(substr(PHP_OS,0,3))=='win') // if windows...
$file='cd '.escapeshellarg(dirname($file)).' && '.basename($file);
_pipeExec($file.' '.$cmdl);
这是特定于平台的,我希望我也不必在linux上解决这个问题。到目前为止它运作良好!
答案 1 :(得分:1)
解决此问题的另一种方法是在命令的开头和结尾添加额外的双引号。
$process = 'C:\\Program Files\\nodejs\\node.exe';
$arg1 = 'C:\\Path to File\\foo.js';
$cmd = sprintf('"%s" %s', $process, escapeshellarg($arg1));
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
$cmd = '"'.$cmd.'"';
}
_pipeExec($cmd);
我在https://bugs.php.net/bug.php?id=49139上找到了这个解决方案 它看起来很奇怪,但是嘿 - 它的Windows ......:D
答案 2 :(得分:0)
这是一种策略。
未经测试的解决方法提示:
使用临时环境变量:
exec('SET ENVPATH="C:\a b"');
proc_open('%ENVPATH%\c.bat' ....
(不知道这是否适用于proc_open)
使用8.3文件名,如果可以以某种方式在PHP中获取 - 肯定可以使用其他exec()
proc_open()
有一个绕过cmd.exe
的选项 - 如果文件系统以某种方式处理报价,可能值得一试
尝试转义引号\"