gpt4 book ai didi

有/没有 cmd.exe 的 Java 子进程命令行执行

转载 作者:可可西里 更新时间:2023-11-01 09:28:19 26 4
gpt4 key购买 nike

我的问题包括几件关于在 Windows 中从 Java 执行子进程时使用“cmd.exe”、“/c”的事情我不明白。基本上,我找不到关于何时以及为何需要它们的良好解释。

我的具体问题:我有一个用于子流程执行的小框架。一种用途是 Java 应用程序,它“管理”由 ProcessBuilders 创建的其他几个 JVM。其中一项关键要求是,当子进程卡住或托管应用程序终止时,它必须能够杀死子进程。
一方面,问题是这样做:

new ProcessBuilder("java", "...").start();

原因:

Could not find or load main class ...

就好像系统变量或目录不同(实际上它们不是)。另一方面,将其包装在 cmd.exe 中,如下所示:

new ProcessBuilder("cmd.exe", "/c", "java", "...").start();

WORKS,但会创建另一个 cmd.exe 进程,这会产生副作用:子 JVM 现在是子进程,process.destroy(); 不会终止它(我发现了 Windows JRE 中的一个已知错误)。

这个特定的问题是在不同的层面上处理的,因为所有这些应用程序都是我们的,我们知道它们的 PID。但这是 cmd.exe 如何使一切工作不同(或完全阻止 JVM 工作)的一个例子。所以我想知道那里到底发生了什么。

在这里,框架本身也出现了。它也将被我们的测试平台使用。我想提供一个 API,它允许通过参数用 cmd.exe/c 包装命令。但是,该参数的具体含义是什么?用户如何决定他们是否需要 cmd.exe 包装?

还有一个我很感激的奖励:这在其他操作系统中是否相关?它在 Linux 中是否有某种等效物?

最佳答案

再次遇到它并找到了问题,并获得了一些额外的见解。

@HarryJohnston - 好点,根据 javadoc,子进程从 ProcessBuilderRuntime.getRuntime.exec(...) API 继承环境,所以这不是问题所在(实际上找到了 java.exe,因此 PATH 显然可用)。

但似乎某些命令行功能丢失了。其中包括命令行中的这种 %VARIABLE% 用法 - 它们不会被解释,除非命令以 cmd.exe/c 开头。

在这种找不到类的情况下(它也可能导致 NoClassDefFoundError),我在类路径中使用了几个变量(也许我应该发布整个命令,但它有点长)。当我用文学路径替换它们时,一切正常。

基本上:

java -cp %classpath% Main - 不好

cmd.exe/c java -cp %classpath% Main - 好

java -cp D:\proj\bin Main - 好

因此,关于 cmd.exe 的行为有何不同的一般问题:

  1. 这样的变量引用:%VARIABLE% 仅由 cmd.exe 解释。
  2. 使用 cmd.exe 你真的不需要将命令拆分成字符串参数数组,你可以使用一个长字符串(“cmd.exe”、“/c”、“其余...”的数组) ).
  3. 子进程将是 cmd.exe 而不是实际的可执行文件,因此 process.destroy() 不会终止它。这可能是在更高版本中修复的错误(我使用的是 Java 7 和 8、Windows 7 和 Server 2012)。
  4. 文件关联仅适用于 cmd.exe,因此您无法“执行”不是程序或脚本的文件(“CreateProcess 错误=193,%1 不是有效的 Win32 应用程序”)。调用 PATH 中定义的可执行文件确实有效。
  5. startcall 仅在 cmd.exe 下可用。
  6. 命令级错误的表现也不同:使用 cmd.exe 时,错误将只出现在输出流中,而没有它,API 会抛出一个异常,这可能也有轻微的不同的描述。

    例如:

    nothing 会导致java.io.IOException: CreateProcess error=2, The system cannot find the file specified

    cmd.exe/c nothing 将返回输出:'nothing' 未被识别为内部或外部命令、可运行程序或批处理文件,以及返回值共 1 个(唯一指示出了问题)。

关于为什么 的更深层问题,以及这是否是差异的完整列表,我仍然不太清楚。看起来 JVM 有其运行命令的方式,您可以使用 cmd.exe“包装”这些命令以获得额外的功能和保护。

另一个有趣的事实是,当您运行 Batch 时,它实际上是在 cmd.exe(及其所有功能)下运行的。从我的测试来看,process.destroy() 似乎只能在它不等待任何外部(例如,如果卡在 pause)时杀死它,有或没有额外的 cmd。 exe/c 包装,但如果它运行子进程则不包装 - 这与第 3 点中提到的 cmd.exe 限制一致。

关于有/没有 cmd.exe 的 Java 子进程命令行执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35584295/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com