简体   繁体   English

为什么远程批处理文件不是由 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?

I am currently facing the issue that I want to implement a PHP script that starts a batch file on a remote server.我目前面临的问题是我想实现一个在远程服务器上启动批处理文件的 PHP 脚本。

After hours of ideas the nearest I came to the solution was a batch file on a local server which could be started by the PHP script.经过几个小时的思考,我最接近的解决方案是本地服务器上的一个批处理文件,它可以由 PHP 脚本启动。 However, the batch file somehow does not start the remote batch file when started via PHP script.但是,当通过 PHP 脚本启动时,批处理文件不会以某种方式启动远程批处理文件。

If the batch file c:\directoryapps\sub\classes\actions\test.bat is started locally with a double click, the remote batch file c:\directory\sub\test.bat is executed without a problem by PsExec .如果批处理文件c:\directoryapps\sub\classes\actions\test.bat是通过双击在本地启动的,则远程批处理文件c:\directory\sub\test.bat会被PsExec毫无问题地执行。

The permissions are granted as needed.权限是根据需要授予的。

I am using the following code in PHP to start the first batch file:我在 PHP 中使用以下代码来启动第一个批处理文件:

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

The code of that batch file is as followed:该批处理文件的代码如下:

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

How do I implement a working version of this?我如何实现这个的工作版本?

I have also tried to run the first batch file code from within PHP script with even less success.我还尝试从 PHP 脚本中运行第一个批处理文件代码,但收效甚微。

The main problem is the decision to install the Sysinternals Suite into a subdirectory of %SystemRoot%\System32 .主要问题是决定将Sysinternals Suite安装到%SystemRoot%\System32的子目录中。 That was no good decision and cause the issue here.这不是一个好的决定,并导致了这里的问题。

The directory %SystemRoot%\System32 is for 64-bit applications executed in 64-bit environment on 64-bit Windows.目录%SystemRoot%\System32用于在 64 位 Windows 上的 64 位环境中执行的 64 位应用程序。

The usage of %SystemRoot%\System32 , which is usually expanded to C:\Windows\System32 , in 32-bit environment results in a redirection by Windows File System Redirector to %SystemRoot%\SysWOW64 respectively expanded C:\Windows\SysWOW64 .在 32 位环境中使用%SystemRoot%\System32通常扩展为C:\Windows\System32导致 Windows 文件系统重定向器重定向%SystemRoot%\SysWOW64分别扩展为C:\Windows\SysWOW64

%SystemRoot%\SysWOW64 contains the 32-bit system executables, but not the directory SysinternalsSuite with file PsExec.exe . %SystemRoot%\SysWOW64包含 32 位系统可执行文件,但不包含文件PsExec.exe的目录SysinternalsSuite

python.exe is a 32-bit executable. python.exe是一个 32 位可执行文件。 For that reason is started with just cmd in the Python script %SystemRoot%\SysWOW64\cmd.exe which is the 32-bit version of Windows command processor.因此,仅使用 Python 脚本%SystemRoot%\SysWOW64\cmd.exe中的cmd启动,这是 32 位版本的 Windows 命令处理器。 32-bit cmd fails to find C:\Windows\SysWOW64\SysinternalsSuite\PsExec.exe and so psexec.exe is not executed at all. 32 位cmd无法找到C:\Windows\SysWOW64\SysinternalsSuite\PsExec.exe ,因此根本不会执行psexec.exe

Well, starting cmd.exe to run a batch file which contains only one command line to run psexec.exe with wrong path for 32-bit environment is not needed at all.好吧,根本不需要启动cmd.exe来运行一个批处理文件,该批处理文件只包含一个命令行来运行带有错误路径的psexec.exe 32 位环境。

It would be enough to use in Python script:在 Python 脚本中使用就足够了:

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

32-bit python.exe runs with this code the 32-bit executable PsExec.exe in subdirectory SysinternalsSuite of 64-bit Windows system directory with the appropriate arguments. 32 位python.exe使用此代码运行 32 位可执行文件PsExec.exe ,位于 64 位 Windows 系统目录的子目录SysinternalsSuite中,并带有适当的参数。

The special redirecting Sysnative exists only for 32-bit applications executed in 32-bit environment.特殊重定向Sysnative仅适用于在 32 位环境中执行的 32 位应用程序。 Please note that Sysnative is neither a directory nor a symbolic link or hard link.请注意, Sysnative既不是目录,也不是符号链接或硬链接。 The file system does not contain an entry Sysnative in directory C:\Windows .文件系统在目录C:\Windows中不包含条目Sysnative For that reason it is not possible to use in a batch file if exist %SystemRoot%\Sysnative or if exist %SystemRoot%\Sysnative\ as both conditions evaluate always to false.因此, if exist %SystemRoot%\Sysnativeif exist %SystemRoot%\Sysnative\ ,则不可能在批处理文件中使用,因为这两个条件的计算结果始终为假。 But if exist %SystemRoot%\Sysnative\cmd.exe can be used in a batch file to find out if the batch file is processed by 32-bit Windows command processor on a 64-bit Windows because of the condition evaluates to true in this use case.但是if exist %SystemRoot%\Sysnative\cmd.exe可以在批处理文件中使用以查明批处理文件是否由 64 位 Windows 上的 32 位 Windows 命令处理器处理,因为条件在此计算为真用例。

I recommend reading also the Microsoft documentation pages WOW64 Implementation Details and Registry Keys Affected by WOW64 to get knowledge on how 32-bit Windows emulation works on 64-bit Windows.我还建议阅读 Microsoft 文档页面WOW64 实施细节受 WOW64 影响的注册表项,以了解 32 位 Windows 仿真如何在 64 位 Windows 上工作。


A minor issue is appending & at end of the Windows command line.一个小问题是在 Windows 命令行的末尾附加& An ampersand at end of a shell script line is interpreted only by Unix/Linux/Mac shell script interpreters as instruction to run the executable detached in background. shell 脚本行末尾的 & 符号仅由 Unix/Linux/Mac shell 脚本解释器解释为运行在后台分离的可执行文件的指令。 So the shell script interpreter does not wait for termination of the started executable before continuation of the script or before the user can enter the next command to execute.因此,shell 脚本解释器不会等待已启动的可执行文件终止,然后才能继续执行脚本或用户可以输入下一个要执行的命令。

Windows command processor cmd.exe interprets an ampersand outside a double quoted argument string as AND operator usually used to specify multiple commands on one command line, see single line with multiple commands using Windows batch file . Windows 命令处理器cmd.exe将双引号参数字符串外的 & 符号解释为AND运算符,通常用于在一个命令行上指定多个命令,请参阅使用 Windows 批处理文件的单行多命令 If there is after & nothing on a command line interpreted by cmd.exe , the Windows command processor ignores the AND operator.如果cmd.exe解释的命令行上&之后没有任何内容,Windows 命令处理器将忽略AND运算符。

Therefore do not append & on a Windows command line.因此不要在 Windows 命令行上附加&


There are two more minor issues in the batch file on command line:命令行的批处理文件中还有两个小问题:

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

The directory separator on Windows is \ and not / as explained by Microsoft on documentation page Naming Files, Paths, and Namespaces . Windows 上的目录分隔符是\而不是/正如 Microsoft 在文档页面Naming Files, Paths, and Namespaces上所解释的那样。 The Windows kernel replaces by default all / by \ in a file/folder string before passing the string to the appropriate file system function.在将字符串传递给适当的文件系统函数之前,Windows 内核默认将文件/文件夹字符串中的所有/替换为\ But the usage of Linux/Mac directory separator / can nevertheless result in unexpected behavior.但是使用 Linux/Mac 目录分隔符/仍然会导致意外行为。

Example:例子:

Run in a Windows command prompt window:在 Windows 命令提示符窗口中运行:

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

The found executables in Windows directory are output with C: and the file name without path.在 Windows 目录中找到的可执行文件以C:和不带路径的文件名输出。 So assigned to loop variable I is a string which references an executable file in current directory of drive C: .因此分配给循环变量I的是一个字符串,它引用驱动器C:的当前目录中的可执行文件。 But the current directory on drive C: on execution of this command line is most likely not C:\Windows which would cause issues on really processing the file name assigned to loop variable I instead of just printing it to console window.但是在执行此命令行时,驱动器C:上的当前目录很可能不是C:\Windows ,这会导致在实际处理分配给循环变量I的文件名时出现问题,而不是仅仅将其打印到控制台窗口。

Run in same command prompt window now:现在在同一个命令提示符窗口中运行:

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

The same file names are output as before, but this time with full path.与以前一样输出相同的文件名,但这次使用完整路径。

Conclusion: Do not use / in file/folder strings on Windows and depend on automatic correction of Windows kernel.结论:不要在 Windows 上的文件/文件夹字符串中使用/并依赖于 Windows 内核的自动更正。 / is used on Windows mainly for beginning of an option. /在 Windows 上主要用于选项的开头。

The usage of \\ in a batch file between two directory names and between a directory name and a file name is also always wrong and must be corrected by Windows kernel before passing the file/folder name string to the file system by removing one backslash.在两个目录名之间以及目录名和文件名之间的批处理文件中使用\\也总是错误的,并且必须在通过删除一个反斜杠将文件/文件夹名称字符串传递到文件系统之前由 Windows 内核更正。 \\ is valid only at beginning of a UNC path . \\仅在UNC 路径的开头有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM