Dies ist meine Hilfsklasse, die ich seit Jahren benutze. Eine kleine Klasse. Sie hat die JavaWorld-StreamGobbler-Klasse, um JVM-Ressourcenlecks zu beheben. Ich weiß nicht, ob sie immer noch für JVM 6 und JVM 7 gültig ist, aber es schadet nicht. Der Helfer kann den Ausgabepuffer zur späteren Verwendung lesen.
import java.io.*;
/**
* Führt einen externen Prozess aus und liest optional den Ausgabepuffer.
*/
public class ShellExec {
private int exitCode;
private boolean readOutput, readError;
private StreamGobbler errorGobbler, outputGobbler;
public ShellExec() {
this(false, false);
}
public ShellExec(boolean readOutput, boolean readError) {
this.readOutput = readOutput;
this.readError = readError;
}
/**
* Führt einen Befehl aus.
* @param command Befehl ("c:/some/folder/script.bat" oder "some/folder/script.sh")
* @param workdir Arbeitsverzeichnis oder NULL, um das Befehlsverzeichnis zu verwenden
* @param wait Warte auf das Ende des Prozesses
* @param args 0..n Befehlszeilenargumente
* @return Prozess-Exitcode
*/
public int execute(String command, String workdir, boolean wait, String...args) throws IOException {
String[] cmdArr;
if (args != null && args.length > 0) {
cmdArr = new String[1+args.length];
cmdArr[0] = command;
System.arraycopy(args, 0, cmdArr, 1, args.length);
} else {
cmdArr = new String[] { command };
}
ProcessBuilder pb = new ProcessBuilder(cmdArr);
File workingDir = (workdir==null ? new File(command).getParentFile() : new File(workdir) );
pb.directory(workingDir);
Process process = pb.start();
// Streams verbrauchen, ältere JVMs hatten ein Speicherleck, wenn die Streams nicht gelesen wurden,
// einige andere JVM+OS-Kombinationen können blockieren, es sei denn, die Streams werden konsumiert.
errorGobbler = new StreamGobbler(process.getErrorStream(), readError);
outputGobbler = new StreamGobbler(process.getInputStream(), readOutput);
errorGobbler.start();
outputGobbler.start();
exitCode = 0;
if (wait) {
try {
process.waitFor();
exitCode = process.exitValue();
} catch (InterruptedException ex) { }
}
return exitCode;
}
public int getExitCode() {
return exitCode;
}
public boolean isOutputCompleted() {
return (outputGobbler != null ? outputGobbler.isCompleted() : false);
}
public boolean isErrorCompleted() {
return (errorGobbler != null ? errorGobbler.isCompleted() : false);
}
public String getOutput() {
return (outputGobbler != null ? outputGobbler.getOutput() : null);
}
public String getError() {
return (errorGobbler != null ? errorGobbler.getOutput() : null);
}
//********************************************
//********************************************
/**
* StreamGobbler liest den InputStream, um ihn zu "verschlucken".
* Dies wird von der Executor-Klasse verwendet, wenn
* Befehlszeilenanwendungen ausgeführt werden. Gobblers müssen die INSTR- und ERRSTR-Prozessstreams lesen.
* http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4
*/
private class StreamGobbler extends Thread {
private InputStream is;
private StringBuilder output;
private volatile boolean completed; // mark volatile to guarantee a thread safety
public StreamGobbler(InputStream is, boolean readStream) {
this.is = is;
this.output = (readStream ? new StringBuilder(256) : null);
}
public void run() {
completed = false;
try {
String NL = System.getProperty("line.separator", "\r\n");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ( (line = br.readLine()) != null) {
if (output != null)
output.append(line + NL);
}
} catch (IOException ex) {
// ex.printStackTrace();
}
completed = true;
}
/**
* Gibt den InputStream-Puffer zurück oder null, wenn der Stream
* nicht verbraucht wurde.
* @return
*/
public String getOutput() {
return (output != null ? output.toString() : null);
}
/**
* Ist der InputStream abgeschlossen.
* @return
*/
public boolean isCompleted() {
return completed;
}
}
}
Hier ist ein Beispiel zum Lesen der Ausgabe aus einem .vbs-Skript, das jedoch ähnlich für Linux-sh-Skripte funktioniert.
ShellExec exec = new ShellExec(true, false);
exec.execute("cscript.exe", null, true,
"//Nologo",
"//B", // Batch-Modus, keine Eingabeaufforderungen
"//T:320", // Timeout in Sekunden
"c:/my/script/test1.vbs", // Unix-Pfad-Trennzeichen funktioniert für script.exe
"Skript-Argument 1",
"Skript-Argument 2",
);
System.out.println(exec.getOutput());
0 Stimmen
Schauen Sie sich diesen Artikel an.