为什么不由 PsExec 执行的远程批处理文件是从具有函数 exec 的 PHP 脚本中的批处理文件 运行 启动的?

Why is a remote batch file not executed by PsExec started from a batch file ran from within a PHP script with function exec?

我目前面临的问题是我想实现一个 PHP 脚本来在远程服务器上启动一个批处理文件。

经过几个小时的思考,我最接近的解决方案是本地服务器上的一个批处理文件,它可以由 PHP 脚本启动。但是,当通过 PHP 脚本启动时,批处理文件不会以某种方式启动远程批处理文件。

如果双击本地批处理文件 c:\directoryapps\sub\classes\actions\test.bat,则 PsExec 可以毫无问题地执行远程批处理文件 c:\directory\sub\test.bat

根据需要授予权限。

我在 PHP 中使用以下代码启动第一个批处理文件:

$cmd = '"c:\directoryapps\sub\classes\actions\test.bat"';
exec('cmd /c '.$cmd.' &');

该批处理文件的代码如下:

"C:/Windows/System32/SysinternalsSuite/PsExec.exe" \server -i -u **** -p **** c:\directory\sub\test.bat 

我如何实现它的工作版本?

我也曾尝试 运行 来自 PHP 脚本的第一个批处理文件代码,但收效甚微。

主要问题是决定将 Sysinternals Suite 安装到 %SystemRoot%\System32 的子目录中。这不是一个好的决定,导致了这里的问题。

目录 %SystemRoot%\System32 用于在 64 位环境中在 64 位环境中执行的 64 位应用程序 Windows。

%SystemRoot%\System32 的用法,通常 扩展为 C:\Windows\System32,在 32 位环境中导致重定向 Windows File System Redirector%SystemRoot%\SysWOW64分别展开C:\Windows\SysWOW64.

%SystemRoot%\SysWOW64 包含 32 位系统可执行文件,但不包含文件 PsExec.exe.

的目录 SysinternalsSuite

python.exe 是 32 位可执行文件。因此,在 Python 脚本 %SystemRoot%\SysWOW64\cmd.exe 中仅使用 cmd 启动,这是 Windows 命令处理器的 32 位版本。 32 位 cmd 无法找到 C:\Windows\SysWOW64\SysinternalsSuite\PsExec.exe,因此根本不会执行 psexec.exe

好吧,从 cmd.exe 到 运行 只包含一个命令行到 运行 psexec.exe 的批处理文件不需要 32 位环境的错误路径完全没有。

在Python脚本中使用就足够了:

$args = '\\server -i -u "****" -p "****" "C:\directory\sub\test.bat"';
exec('C:\Windows\Sysnative\SysinternalsSuite\PsExec.exe '.$args.);

32 位 python.exe 运行s 带有此代码的 32 位可执行文件 PsExec.exe 在 64 位 Windows 系统目录的子目录 SysinternalsSuite 中使用适当的参数。

特殊重定向 Sysnative 仅适用于在 32 位环境中执行的 32 位应用程序。请注意 Sysnative 既不是目录也不是符号 link 或硬 link。文件系统在目录 C:\Windows 中不包含条目 Sysnative。因此,无法在批处理文件中使用 if exist %SystemRoot%\Sysnativeif exist %SystemRoot%\Sysnative\,因为这两个条件的计算结果始终为假。但是 if exist %SystemRoot%\Sysnative\cmd.exe 可以在批处理文件中使用,以查明批处理文件是否由 64 位 Windows 上的 32 位 Windows 命令处理器处理,因为条件计算结果为真在这个用例中。

我建议还阅读 Microsoft 文档页面 WOW64 Implementation Details and Registry Keys Affected by WOW64 以了解 32 位 Windows 仿真如何在 64 位 Windows.

上工作

一个小问题是在 Windows 命令行末尾附加 &。 shell 脚本行末尾的符号仅由 Unix/Linux/Mac shell 脚本解释器解释为 运行 在后台分离的可执行文件的指令。因此,shell 脚本解释器不会等待已启动的可执行文件终止,然后才能继续执行脚本或用户可以输入下一个要执行的命令。

Windows 命令处理器 cmd.exe 将双引号参数字符串外的符号解释为 AND 运算符,通常用于在一个命令行上指定多个命令,参见 single line with multiple commands using Windows batch file。如果在 cmd.exe 解释的命令行上 & 之后没有任何内容,Windows 命令处理器将忽略 AND 运算符。

因此不要在 Windows 命令行上附加 &


命令行批处理文件中还有两个小问题:

"C:/Windows/System32/SysinternalsSuite/PsExec.exe" \server -i -u **** -p **** c:\directory\sub\test.bat

Windows 上的目录分隔符是 \ 而不是 Microsoft 在文档页 Naming Files, Paths, and Namespaces 上解释的 /。在将 file/folder 字符串传递给适当的文件系统函数之前,Windows 内核默认将所有 / 替换为 \。但是使用 Linux/Mac 目录分隔符 / 仍然会导致意外行为。

示例:

运行 在 Windows 命令提示符下 window:

for %I in (C:/Windows/*.exe) do @echo %I

在Windows 目录中找到的可执行文件以C: 和不带路径的文件名输出。因此分配给循环变量 I 的是一个字符串,它引用驱动器 C: 当前目录中的可执行文件。但是执行此命令行时驱动器 C: 上的当前目录很可能不是 C:\Windows,这会导致在真正处理分配给循环变量 I 的文件名时出现问题,而不仅仅是打印它安慰 window.

运行 在同一个命令提示符 window 现在:

for %I in (C:\Windows\*.exe) do @echo %I

输出与之前相同的文件名,但这次是完整路径。

结论:不要在Windows上的file/folder字符串中使用/,依赖Windows内核的自动修正。 / 用于 Windows 主要用于选项的开头。

在两个目录名之间以及目录名和文件名之间的批处理文件中使用 \ 也总是错误的,必须在传递 file/folder 通过删除一个反斜杠将名称字符串添加到文件系统。 \ 仅在 UNC path.

开头有效