2013-06-11 2 views
4
public class LinuxInteractor { 

public static String executeCommand(String command) 
{ 
System.out.println("Linux command: " + command); 

try 
{ 
    Process p = Runtime.getRuntime().exec(command); 
    p.waitFor(); 
    BufferedReader bf=new BufferedReader(new InputStreamReader(p.getInputStream())); 
    String str=bf.readLine(); 
    System.out.println("inputStream is::"+str); 
    while((str=bf.readLine()) != null) 
    { 
     System.out.println("input stream is::"+str);   
    } 
    System.out.println("process started"); 
} 
catch (Exception e) { 
System.out.println("Error occured while executing Linux command. Error  Description: " 
    + e.getMessage()); 
    e.printStackTrace(); 
} 
} 

Когда я запускаю скрипт через консоль, он работает. Но через Java-программу InputStream(Str) идет как null.Не удается получить getInputStream из Runtime.getRunTime.exec()

Есть ли какой-либо другой подход, который я могу использовать?

+1

1) Прочитайте (и внесите) * все * рекомендации [Когда Runtime.exec() не будет] (http://www.javaworld.com/jw-12-2000/jw-1229-traps. HTML). Это может решить проблему. Если нет, он должен предоставить дополнительную информацию о причине отказа. Затем проигнорируйте, что он ссылается на 'exec' и создает' Process' с помощью 'ProcessBuilder'. Также разбивайте 'String arg' на' String [] args' для учета аргументов, которые сами содержат пробелы. 2) Я подозреваю, что вызов 'waitFor' должен быть после потребления потока. –

+1

Это немного бессмысленное ожидание выхода процесса * до того, как вы прочитали какой-либо из своих результатов. Если его выходной буфер заполняется, он никогда не сможет выйти вообще. В вашем коде нет 'InputStream (Str)', но если вы утверждаете, что 'Process.getInputStream()' возвращает null, трудно поверить, что вы правы. – EJP

+0

@EJP InputStream is = Process.getInputStream; , если я прочитал его через buffer-reader.its, поступив как null. его решить сейчас, нужно сделать это в другом потоке. – kin

ответ

5

Решение
Вы должны попытаться сделать чтение и выполнение в разных потоках.

Лучшей альтернативой является использование ProcessBuilder, который заботится о «грязной» работе для вас.
Код внутри блока try может выглядеть примерно так:

/* Create the ProcessBuilder */ 
ProcessBuilder pb = new ProcessBuilder(commandArr); 
pb.redirectErrorStream(true); 

/* Start the process */ 
Process proc = pb.start(); 
System.out.println("Process started !"); 

/* Read the process's output */ 
String line;    
BufferedReader in = new BufferedReader(new InputStreamReader(
     proc.getInputStream()));    
while ((line = in.readLine()) != null) { 
    System.out.println(line); 
} 

/* Clean-up */ 
proc.destroy(); 
System.out.println("Process ended !"); 

См, также, это short demo.


Причина проблемы
Согласно Java Docs, waitFor():

вызывает текущий поток ждать, если это необходимо, до тех пор, процесс, представленный этим объектом процесса не прекращается ,

Итак, вы пытаетесь получить выходной поток процесса после его завершения, поэтому null.


(. Извините за основной обновляют ответа)

+0

Все, что начинается с «try», является хорошим кандидатом на комментарий, и плохой кандидат на ответ. –

+0

Без waitFor() и после выхода процесса, я попытался. Но такая же проблема возникает.InputStream Stirng приходит как null. – kin

+0

Я знаю :) Этот ответ полностью ошибочен и скоро будет удален. Мне просто любопытно, сколько упущений этот неправильный ответ может получить. Извините за беспокойство. Вы лучше прочитаете это в отдельном потоке, как предлагает Юнед Ахсан. – gkalpak

1

Вы должны сделать это в отдельной теме:

Process process = Runtime.getRuntime().exec(command); 
LogStreamReader lsr = new LogStreamReader(process.getInputStream()); 
Thread thread = new Thread(lsr, "LogStreamReader"); 
thread.start(); 


public class LogStreamReader implements Runnable { 

    private BufferedReader reader; 

    public LogStreamReader(InputStream is) { 
     this.reader = new BufferedReader(new InputStreamReader(is)); 
    } 

    public void run() { 
     try { 
      String line = reader.readLine(); 
      while (line != null) { 
       System.out.println(line); 
       line = reader.readLine(); 
      } 
      reader.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Тогда вам нужен второй поток для обработки входных данных. И вы можете иметь дело с stderr так же, как stdout.