PHP类Exec函数及COM组件执行批处理文件在Windows 2012失效排查
修复方案
核心问题说明
你遇到的是Windows 2012 + PHP 7环境下,Web运行身份的权限、环境变量、输出捕获逻辑三方面的差异导致的问题:pclose返回整数1说明批处理已经被触发执行,但执行过程出错退出,所有错误信息默认输出到stderr流,你之前的所有写法都只捕获stdout流,所以拿到的结果为空。
分步排查修复
第一步:优先补全输出捕获规则,拿到具体报错
所有执行命令末尾添加2>&1,将stderr输出重定向到stdout,同时用escapeshellarg处理文件路径避免转义问题,示例代码:// 测试用shell_exec写法 $safePath = escapeshellarg($filePath); $output = shell_exec("cmd /c {$safePath} 2>&1"); var_dump($output);执行后拿到的输出会直接显示rsync运行的具体错误,比如找不到rsync命令、密钥权限不足、目标路径无权限等。
第二步:修复批处理本身的路径问题
批处理内部不要用相对路径调用rsync,替换为rsync的绝对路径,示例::: 替换前 rsync -avz /source /target :: 替换后,路径改为你实际的rsync安装路径 "C:\Program Files\cwRsync\bin\rsync.exe" -avz /cygdrive/c/source /cygdrive/d/target第三步:修复Web运行身份的权限问题
Windows 2012的IIS默认用独立的应用池身份运行站点,和Win2003的默认IUSR权限逻辑完全不同:- 打开IIS管理器,找到站点对应的应用池,右键「高级设置」,将「加载用户配置文件」选项设置为
True - 如果rsync需要SSH密钥验证,将密钥文件放入对应应用池用户的家目录
.ssh文件夹下,路径通常为C:\Users\你的应用池名称\.ssh\,给应用池身份授予该目录的读取权限 - 如果rsync需要访问网络共享资源,直接将应用池的运行身份修改为有对应资源访问权限的本地/域用户,不要使用默认内置应用池身份
- 打开IIS管理器,找到站点对应的应用池,右键「高级设置」,将「加载用户配置文件」选项设置为
第四步:COM调用适配(如果要保留原有COM写法)
除开上述配置,调整COM调用逻辑,补全路径转义和错误流捕获:$WshShell = new COM("WScript.Shell"); $safePath = escapeshellarg($filePath); $oExec = $WshShell->Exec("cmd /c {$safePath} 2>&1"); // 可以单独读取标准输出和错误输出 $sStdOut = $oExec->StdOut->ReadAll(); $sStdErr = $oExec->StdErr->ReadAll();
内容的提问来源于stack exchange,提问作者Neil Wehneman
相关产品推荐
相关产品推荐

