2009-07-01 156 views
3

我正在嘗試使用ProcessBuilder和Process來執行命令(例如.ps -ef | grep apache)。只要'ps -ef'的輸出很小,代碼就會工作。但是如果輸出太大,程序就會掛起。有沒有辦法來解決這個問題?這是基於[http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html]如何將大輸出寫入Process getOutputStream?

#### 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; 
    } 
} 

感謝,

奎德

回答

3

不打印它作爲一個字符串,但給CommandExecuter可選的OutputStream(你的情況,你通過System.out的我的代碼作爲參數)並將其寫入該流。

在您當前的程序中,主方法將執行該程序,並且不會打印任何東西(掛起),直到您的運行方法返回某些內容。

+1

DAFF, 感謝您的答覆,但你能否詳細說明。我不太明白你的答案。 - Quadir – Quadir 2009-07-01 18:22:28

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; 
     } 
    } 
}