J'essaie d'exécuter un nouveau processus et de lire son flux d'entrée en Java. J'ai utilisé Runtime.getRuntime(). Exec (String) avec succès pour démarrer et recevoir l'entrée de plusieurs processus. Cependant, lorsque j'essaie d'utiliser exec sur d'autres processus, la méthode de lecture du flux d'entrée se bloque et il semble qu'il n'y ait pas d'entrée. Qu'est-ce qui pourrait rendre le flux d'entrée vide pour certains de ces processus? Plus précisément, je me demande pourquoi bash.exe ne produit rien.Runtime.getRuntime(). Exec ("C: cygwin bin bash.exe") n'a pas d'entrée à lire
J'ai écrit un test JUnit pour démontrer cette question:
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;
public class TestExec extends TestCase {
public void testExec() throws IOException {
List<InputPrinter> threads = new ArrayList<InputPrinter>();
// Create a process for each of the commands and make sure that
// it outputs at least one line to its input stream.
threads.add(testExec("cmd"));
threads.add(testExec("java"));
threads.add(testExec("C:/cygwin/bin/vim-nox.exe"));
// These bottom two fail, even though executing these
// commands in cmd.exe results in immediate output
threads.add(testExec("javac"));
threads.add(testExec("C:/cygwin/bin/bash.exe"));
// Give the threads a second to execute
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
fail();
}
// Test that each command had input to read
for(InputPrinter ip : threads) {
assertTrue(ip.command + " has not read any input", ip.hasRead);
}
}
// Starts a process for the given command and returns an
// InputPrinter that can be used to check if the process
// has had an input to read.
public InputPrinter testExec(String command) throws IOException {
Process proc = Runtime.getRuntime().exec(command);
InputStream in = proc.getInputStream();
InputPrinter ip = new InputPrinter(in, command);
new Thread(ip).start();
return ip;
}
// Simple Runnable to read from an InputStream. hasRead will be
// true if at least one input has been read from the stream
private class InputPrinter implements Runnable {
InputStream in;
String command;
boolean hasRead;
public InputPrinter(InputStream in, String command) {
this.in = in;
this.command = command;
this.hasRead = false;
}
// Loop indefinitely while printing any received input
public void run() {
try {
final byte[] b = new byte[1024];
while (true) {
int n = in.read(b);
if (n > 0) {
System.out.print(new String(Arrays.copyOf(b, n)));
hasRead = true;
}
}
} catch (IOException e) {
e.printStackTrace();
fail();
}
}
}
}
EDIT:
Pour autant que je sache, si un programme n'utilise pas stdout ou stderr, je ne devrais pas voir quelque chose dans l'invite de commande Windows. Ce que je me attends de voir quand je commence le processus de bash est « bash-3.2 $, » la même chose que je vois quand j'ouvrir l'invite de commande et exécutez « bash.exe »:
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\cygwin\bin>bash.exe
bash-3.2$
C'est génial de voir des gens en utilisant des assertions plutôt que 'System.out' en questions –
Je pense que c'est parce que le programme fait une impression au lieu d'un println .. – Patrick
Quelle est la question? Quel est le problème ? –