PHP借助ssh2扩展通过SCP从Windows远程取文件到本地Unix失败排查
PHP ssh2 对接Windows主机SCP传输异常排查方案
先排查路径匹配问题
- 首先确认PHP SSH连接建立后,远程Windows端的实际工作路径:可在连接建立后执行命令
ssh2_exec($connection, 'echo %CD% && dir');,读取返回的输出内容,对比当前PHP连接的默认工作目录,和你手动命令行登录Windows后的工作目录是否一致。由于SCP的相对路径是基于登录后的默认工作目录解析的,一旦两边路径不匹配,就会出现“文件不存在”的报错。 - 直接把远程文件路径替换为绝对路径测试,Windows路径中的反斜杠需替换为正斜杠(或做双反斜杠转义),避免PHP字符串的转义逻辑破坏路径结构。
根因定位验证
- 你观察到
ssh2_scp_send推送后远程文件带多余单引号的现象,是典型的参数解析不兼容问题:PHP ssh2扩展内部实现SCP交互时,会按照Unix Shell的参数规则给文件路径包裹单引号做参数分隔,但Windows端默认的cmd命令行完全不识别单引号的参数包裹语法,反而会把单引号作为文件名的一部分做解析。 - 对应
ssh2_scp_recv找不到文件的报错,本质是同一个逻辑导致:扩展内部向远程Windows端发起的SCP读请求,实际是让远程端查找被单引号包裹后的'textexample'文件,自然匹配不到真实的textexample文件。 - 可以做快速验证:在代码中把远程文件名手动补上对应单引号,即
ssh2_scp_recv($connection, "'textexample'", "nexText.txt");,如果能正常拉取文件,即可确认是参数转义兼容的问题。
可落地的解决方向
- 优先替换为SFTP接口实现文件传输:SFTP是独立的SSH子系统,不走cmd命令行的参数解析逻辑,不会出现单引号转义、路径解析类的兼容问题,兼容全版本的Windows OpenSSH服务。
- 如果必须使用SCP接口,可先在Windows端的OpenSSH配置里把默认登录shell从cmd切换为PowerShell(或WSL shell),PowerShell会正确识别单引号的参数分隔逻辑,能适配PHP ssh2扩展的SCP实现逻辑。
- 升级Windows端的OpenSSH服务到最新稳定版本,老版本的Win32-OpenSSH本身存在大量SCP协议兼容bug,升级后可减少路径解析类的异常。
内容的提问来源于stack exchange,提问作者Bent
相关产品推荐
相关产品推荐

