PHP中的奇怪错误,路径和窗口中的空格
我得把这个小虫子修好。首先,让我们谈谈一个小事实: 在Windows上的CLI中,无法运行路径中有空格的程序,除非:PHP中的奇怪错误,路径和窗口中的空格,php,windows,path,command-line-interface,space,Php,Windows,Path,Command Line Interface,Space,我得把这个小虫子修好。首先,让我们谈谈一个小事实: 在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
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
- 结果:1
- STDERR:'C:\a'未被识别为内部或外部命令, 可操作的程序或批处理文件
- 标准:
- 结果:1
- STDERR:'C:\a'未被识别为内部或外部命令, 可操作的程序或批处理文件
- 标准:
- 结果:1
- STDERR:文件名、目录名或卷标语法不正确
- 标准:
- 使用临时环境变量:
(不知道这是否适用于proc_open)exec('SET ENVPATH="C:\a b"'); proc_open('%ENVPATH%\c.bat' ....
- 如果可以在PHP中以某种方式获取文件名,请使用8.3文件名-使用另一个
exec()
有一个选项可以绕过proc\u open()
——如果文件系统以不同方式处理引号,可能值得一试cmd.exe
- 尝试转义引号
\“
$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上也解决这个问题。到目前为止,它工作得很好!另一种解决方法是在命令的开头和结尾加上双引号
$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);
我在这看起来很奇怪,但是嘿-这是Windows…:D在黑暗中拍摄的,但是你能尝试切换引号类型吗?(
“
到”
)我没有这方面的经验,但是在命令提示符中运行“a b/c.bat”,在PHP中调用“c:\a b\c.bat”,包括引号内的路径。也许调用C:\'ab\C.bat“有效吗?@Pekka,我得到的结果与示例3相同;单引号似乎不像双引号那样是容器字符。@deltreme,这也不管用。你试过最简单的吗?C:\\“AB”\\C.batth绕过cmd.exe给了我一个想法:cmd“C:\\AB\\C.bat”
proc\u open有一个参数可以传递环境变量,更好地使用它。@Christian啊,很有趣。可能有用。也许还可以试着打电话给毒蛇好点!别介意我先前的评论。我的问题不是关于cmd.exe
;我实际上运行的是程序而不是批处理文件(例如:C:\b\C.exe)。两者都有相同的问题(但程序当然不依赖cmd.exe)。好吧,这“起作用”,但我失去了对过程的控制,所以,还没有修复:(嗨,在我的代码中尝试使用你的解决方案,发现有一个语法错误。你有一个悬空)在第5行的末尾。我会修复它,但编辑时有一个最小字符限制。cheers@ted.strauss谢谢修复了。这是一个很好的解决方法。我看不出这在linux上会失败的任何原因。这种解决方案很奇怪,但它可以工作,而且比仅仅为了运行命令而cd'ing到目录更明智。请注意,is_可执行文件不适用于引号内的路径。如果您使用的是proc_open(如OP文章中所述),那么在Windows上使用“其他_选项”参数proc_open的值为array('bypass_shell'=>true)意味着整个命令不需要包装(但您仍然需要转义\(如\\),并引用包含空格的路径(如“C:\\Program Files\\”)。使用bypass_shell还意味着使用的cmd.exe进程少了一个(在W7上也有一个conhost.exe进程-可能在W8和W10上也有,我不知道)