我正在尝试使用ProcessBuilder和Process执行命令(例如ps -ef | grep apache)。只要'ps -ef'的输出很小,代码就可以工作。但如果输出太大,程序就会挂起。有没有办法来解决这个问题?以下是基于[http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html]
的代码#### Program.java ####
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class Program {
private List<String> command;
public Program(String commandString) throws IOException {
this(commandString, null);
}
public List<String> getCommand() {
return this.command;
}
private void setCommand(String filename, String location, String commandString, List<String> parameters) throws IOException {
if(filename != null) {
commandString = new File(location, filename).getCanonicalPath();
}
this.command =
Collections.synchronizedList(new ArrayList<String>());
this.command.add(commandString);
if (parameters != null) {
for (String arg: parameters) {
command.add(arg);
}
}
}
public String[] run() throws IOException, InterruptedException {
return this.run(null);
}
public String[] run(String input) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder(this.command);
List<String> commandList = processBuilder.command();
Process process = processBuilder.start();
if(input != null) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(process.getOutputStream())), true);
writer.println(input);
writer.flush();
writer.close();
}
process.getOutputStream().close();
Gobbler outGobbler = new Gobbler(process.getInputStream());
Gobbler errGobbler = new Gobbler(process.getErrorStream());
Thread outThread = new Thread(outGobbler);
Thread errThread = new Thread(errGobbler);
outThread.start();
errThread.start();
outThread.join();
errThread.join();
int exitVal = process.waitFor();
System.out.println("PROCESS WAIT FOR: " + exitVal);
List<String> output = outGobbler.getOuput();
return output.toArray(new String[output.size()]);
}
}
#### CommandExecutor.java ####
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class CommandExecutor {
public List<List<Object>> programs;
public static void main(String[] args) {
try {
CommandExecutor ce = new CommandExecutor(args[0]);
String output = ce.run();
System.out.println("Command: " + args[0]);
System.out.println("Output: " + output);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println(e.getLocalizedMessage());
e.printStackTrace();
} catch (InterruptedException ie) {
// TODO Auto-generated catch block
System.out.println(ie.getLocalizedMessage());
ie.printStackTrace();
}
}
public CommandExecutor(String command) throws IOException {
this.setPrograms(command);
}
private void setPrograms(String command) throws IOException {
this.programs = new ArrayList<List<Object>>();
//String cmdstring = "";
String[] commands = command.split("\\s*;\\s*");
for(String c: commands) {
//String subcmdstr = "";
String file = null;
String[] chainedCommands = c.split("\\s*\\|\\s*");
String lastCmd = chainedCommands[chainedCommands.length-1];
String[] fileCmd = lastCmd.split("\\s*>\\s*");
if(fileCmd.length > 1) {
chainedCommands[chainedCommands.length-1] = fileCmd[0];
file = fileCmd[1];
}
List<Object> l = new ArrayList<Object>();
for(String p: chainedCommands) {
/*if(subcmdstr.equals("")) {
subcmdstr = p;
}
else {
subcmdstr += " redirects to " + p;
}*/
String[] cmdparams = p.split(" ");
String cmd = cmdparams[0];
List<String> params = new ArrayList<String>();
for(int j = 1; j < cmdparams.length; j++) {
params.add(cmdparams[j]);
}
Program prog = new Program(cmd, params);
l.add(prog);
}
if(file != null) {
//subcmdstr += " redirects to file: " + file;
l.add(file);
}
this.programs.add(l);
//cmdstring += "new command: " + subcmdstr + "\n";
}
//System.out.println("Actual Command: " + command);
//System.out.println("Command String:\n" + cmdstring);
}
public String run() throws IOException, InterruptedException {
String output = "";
for(List<Object> l: this.programs) {
String[] out = new String[0];
int count = 0;
boolean filenotfound = true;
for(Object o: l) {
if(o instanceof Program) {
Program p = (Program) o;
if(count == 0) {
out = p.run();
}
else {
out = p.run(CommandExecutor.arrayToString(out));
}
}
else if(o instanceof String) {
PrintWriter f = new PrintWriter(new File((String)o));
f.print(CommandExecutor.arrayToString(out));
f.close();
filenotfound = false;
}
count++;
}
if(filenotfound) {
output += CommandExecutor.arrayToString(out);
}
}
return output;
}
public static String arrayToString(String[] strArray) {
String str = "";
for(String s: strArray) {
str += s;
}
return str;
}
}
谢谢,
奎德
答案 0 :(得分:5)
好的,我明白了。下面是代码,给定一个命令列表,它将一个命令的输出传递给下一个命令。
/*
####### PipeRedirection.java
*/
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class PipeRedirection {
public static void main(String[] args) throws FileNotFoundException {
if(args.length < 2) {
System.err.println("Need at least two arguments");
System.exit(1);
}
try {
String input = null;
for(int i = 0; i < args.length; i++) {
String[] commandList = args[i].split(" ");
ProcessBuilder pb = new ProcessBuilder(commandList);
//pb.redirectErrorStream(true);
Process p = pb.start();
if(input != null) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true);
writer.println(input);
writer.flush();
writer.close();
}
InputProcess.Gobbler outGobbler = new InputProcess.Gobbler(p.getInputStream());
InputProcess.Gobbler errGobbler = new InputProcess.Gobbler(p.getErrorStream());
Thread outThread = new Thread(outGobbler);
Thread errThread = new Thread(errGobbler);
outThread.start();
errThread.start();
outThread.join();
errThread.join();
int exitVal = p.waitFor();
System.out.println("\n****************************");
System.out.println("Command: " + args[i]);
System.out.println("Exit Value = " + exitVal);
List<String> output = outGobbler.getOuput();
input = "";
for(String o: output) {
input += o;
}
}
System.out.println("Final Output:");
System.out.println(input);
} catch (IOException ioe) {
// TODO Auto-generated catch block
System.err.println(ioe.getLocalizedMessage());
ioe.printStackTrace();
} catch (InterruptedException ie) {
// TODO Auto-generated catch block
System.err.println(ie.getLocalizedMessage());
ie.printStackTrace();
}
}
public static class Gobbler implements Runnable {
private BufferedReader reader;
private List<String> output;
public Gobbler(InputStream inputStream) {
this.reader = new BufferedReader(new InputStreamReader(inputStream));
}
public void run() {
String line;
this.output = new ArrayList<String>();
try {
while((line = this.reader.readLine()) != null) {
this.output.add(line + "\n");
}
this.reader.close();
}
catch (IOException e) {
// TODO
System.err.println("ERROR: " + e.getMessage());
}
}
public List<String> getOuput() {
return this.output;
}
}
}
答案 1 :(得分:3)
不要将它作为String打印,而是给CommandExecuter一个可选的OutputStream(在你的Case中传递System.out作为参数)并将其写入该流。
在当前程序中,Main方法将执行程序,并且在run方法返回之前不会打印任何内容(挂起)。