2009-07-01 4 views
3

Ich versuche mit ProcessBuilder und Process einen Befehl auszuführen (zB. Ps -ef | grep apache). Der Code funktioniert solange die Ausgabe von 'ps -ef' klein ist. Aber wenn die Ausgabe zu groß ist, hängt das Programm. Gibt es eine Möglichkeit, das zu beheben? Hier ist mein Code basiert auf [http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html]Wie kann ich große Ausgabe in Process getOutputStream schreiben?

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

Danke,

Quadir

Antwort

3

Sie es nicht als String drucken, sondern die CommandExecuter einen optionalen Output geben (in Ihrem Fall passieren Sie System.out als Argument) und schreibe es in diesen Stream.

In Ihrem aktuellen Programm wird die Hauptmethode das Programm ausführen und nichts drucken (hängen), bis Ihre Laufmethode etwas zurückgibt.

+1

Daff, Vielen Dank für Ihre Antwort, aber können Sie das näher erläutern. Ich habe deine Antwort nicht verstanden. - Quadir – Quadir

+1

Sorry ... war nicht schnell genug. Ihre Lösung sieht jedoch ziemlich gut aus :) – Daff

5

Ok, ich habe es funktioniert. Unten ist der Code, der bei einer Liste von Befehlen die Ausgabe eines Befehls an den nächsten weiterleitet.

/* 
####### 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; 
     } 
    } 
} 
Verwandte Themen