(这是我的同事在其他地方发布的问题,但我想我会在这里发布,看看是否可以吸引不同的受众。)
大家好,我正在测试编写一个小型 Java 应用程序的可能性,该应用程序将使用 Psexec 来启动远程作业。在测试将 java 程序的标准输入和标准输出绑定到 psexec 的过程中,我遇到了一个奇怪的错误。
我的测试程序是一个基本的回声程序。它启动一个线程从标准输入读取,然后将读取的输出直接通过管道传输回标准输出。当在本地机器上运行而不是从 psexec 上运行时,它运行良好。正如它应该的那样。
但是,当我第一次从 PsExec 调用它时,输入直接通过管道传输到标准输出,它会丢失。使该错误真正奇怪的是,只有第一次将输入直接通过管道传输到 stdout 时才会丢失。如果输入字符串附加到另一个字符串,它工作正常。字符串文字或字符串变量。但是,如果输入字符串直接发送到标准输出,它不会通过。第二次将其发送到标准输出时,它会正常运行 - 之后每次都可以。
我完全不知道这里发生了什么。我试图测试我能想到的每一个可能的错误。我没主意了。我错过了一个还是这只是 psexec 内部的东西?
这是有问题的代码,它位于三个类中(其中一个实现了一个接口,它是一个单一的函数接口)。
主类:
public class Main {
public static void main(String[] args) {
System.out.println("Starting up.");
CReader input = new CReader(new BufferedReader(
new InputStreamReader(System.in)));
CEcho echo = new CEcho();
input.addInputStreamListener(echo);
input.start();
System.out.println("Successfully started up. Awaiting input.");
}
}
CReader 类是从标准输入读取的线程:
public class CReader extends Thread {
private ArrayList<InputStreamListener> listeners =
new ArrayList<InputStreamListener>();
private boolean exit = false;
private Reader in;
public CReader(Reader in) {
this.in = in;
}
public void addInputStreamListener(InputStreamListener listener) {
listeners.add(listener);
}
public void fireInputRecieved(String input) {
if(input.equals("quit"))
exit = true;
System.out.println("Input string has made it to fireInputRecieved: "
+ input);
for(int index = 0; index < listeners.size(); index++)
listeners.get(index).inputRecieved(input);
}
@Override
public void run() {
StringBuilder sb = new StringBuilder();
int current = 0, last = 0;
while (!exit) {
try {
current = in.read();
}
catch (IOException e) {
System.out.println("Encountered IOException.");
}
if (current == -1) {
break;
}
else if (current == (int) '\r') {
if(sb.toString().length() == 0) {
// Extra \r, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else if(current == (int) '\n') {
if(sb.toString().length() == 0) {
// Extra \n, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else {
System.out.println("Recieved character: " + (char)current);
sb.append((char) current);
last = current;
}
}
}
}
CEcho 类,该类通过管道将其返回到标准输出:
public class CEcho implements InputStreamListener {
public void inputRecieved(String input) {
System.out.println("\n\nSTART INPUT RECIEVED");
System.out.println("The input that has been recieved is: "+input);
System.out.println("It is a String, that has been copied from a " +
"StringBuilder's toString().");
System.out.println("Outputting it cleanly to standard out: ");
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
System.out.println("Finished example outputs of input: "+input);
System.out.println("END INPUT RECIEVED\n\n");
}
}
最后,这是程序输出:
>psexec \\remotecomputer "C:\Program Files\Java\jre1.6.0_05\bin\java.exe" -jar "C:\Documents and Settings\testProram.jar" PsExec v1.96 - 远程执行进程 版权所有 (C) 2001-2009 Mark Russinovich Sysinternals - www.sysinternals.com 启动。 成功启动。等待输入。 测试 收到字符:T 收到的字符:e 收到的字符:s 收到的字符:t 输入字符串已进入 fireInputRecieved: Test 收到的开始输入 收到的输入是:测试 它是一个字符串,从 StringBuilder 的 toString() 复制而来。 将其干净地输出到标准输出: 再次将其干净地输出到标准输出: 测试 输入的完成示例输出:测试 收到的最终输入