我使用Java来处理运行子进程的开销。子进程是Microsoft Compute Cluster Pack(如果相关)。当我在命令行上运行MSCCP时,一切都很好,我在提示中与它进行交互,每个人都很高兴。当我尝试在Java中执行相同操作时,子进程似乎就像无限回车被发送到它的stdin一样。 (当我在命令提示符下运行进程并且反复点击回车符时,它表现出与在Java中运行它时相同的行为)。这是我的java代码,相当标准:
List<String> params =
Arrays.asList("cmd.exe", "/c", "job.cmd", "submit", stderr, stdout, cwd, scheduler, name, user, run, bif);
final Process p = new ProcessBuilder(params).redirectErrorStream(true).directory(location).start();
为了使问题简明扼要,假设所有变量都设置正确。它们是 - 我运行循环,将它们打印到控制台,然后将它们直接复制并粘贴到我的命令提示符中并运行。其他变量,例如下面的write
是BlockingQueues。在单独的线程中,我正在监听stdout / err和stdin:
// Thread for writing to sub-process' input stream when Queue has char[] in it
new Thread(new Runnable() {
public void run() {
char[] writeThis;
PrintWriter procIn = new PrintWriter(p.getOutputStream(), true);
try { //write is a BlockingQueue which contains input to the program.
while ((writeThis = write.take()) != null) {
wait.set(true);
for (int i = 0; i < writeThis.length; i++) {
procIn.print(writeThis[i]);
writeThis[i] = 0; //clearing buffer for security reasons.
}
procIn.println(); //the only carriage return I intend to send...
wait.set(false);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// Thread for listening to the stdout/stderr of the sub-process and reacting to its output.
new Thread(new Runnable() {
public void run() {
Scanner procOut = new Scanner(p.getInputStream());
StringBuffer reqs = new StringBuffer();
while (procOut.hasNext()) {
String str = procOut.next() + " ";
reqs.append(str);
if (reqs.toString().startsWith("Enter the password for")) {
// do stuff...
} else if (str.contains(")")) {
// do stuff...
}
pauseTillWaitFalse();
}
}
}).start();
我注意到,流程的输出(上面procOut
)会输出输出,就好像回车不断被发送到job.cmd
子流程一样。我希望在procIn
发送的命令根本不会被发送!就像procIn
转到NUL或其他东西一样。
关于job.cmd
的注意事项它是一个内部调用实际运行子进程的VB脚本的文件。 @%windir%\system32\cscript.exe //Nologo "%~dp0%~n0.vbs" %*
其中job.vbs正在运行。
同样,在命令提示符下,这一切都完全正常。我不明白为什么使用Java Process API运行它会有什么不同,除非命令提示符在后台发出某种稳定性命令以保持job.vbs
满意?
编辑:为了平息任何可能的混淆,输入参数stdout,stderr与进程标准输出/输入无关。它们与job.cmd系统特有的其他内容有关。
更新: 我发现vb代码中的位置要求输入密码。有一节如下:
Set objPassword = CreateObject("ScriptPW.Password")
if IsObject(objPassword)=false then
WScript.StdErr.WriteLine "Not support password to be * or empty on Vista or Longhorn."
WScript.Quit(1)
end if
因此,VB的ScriptPW.Password
功能似乎与Java不相称。有没有办法解决? (我仍然宁愿使用它作为传输密码的方法)。