2010-07-01 47 views
20

Tôi đang cố bắt đầu một quá trình bên ngoài với Java và không thể đọc bất cứ thứ gì từ InputStream của nó.Không thể đọc InputStream từ Java Process (Runtime.getRuntime(). Exec() hoặc ProcessBuilder)

Nếu tôi bắt đầu quá trình với các lệnh như "ls", "ps" hoặc "kill", mọi thứ hoạt động tốt. Tôi có thể bắt đầu quá trình và nhận thông tin trên InputStream hoặc ErrorStream của Process.

Nếu tôi cố sử dụng lệnh như "ftp" hoặc "telnet", cả InputStream và ErrorStream đều chặn chương trình của tôi khi cố gắng đọc. Không có thông tin nào được truyền qua các luồng này bất kỳ lúc nào.

Có ai có thể giải thích về hành vi không? Là nó chỉ không thể với các lệnh này hoặc tôi có một vấn đề với việc thực hiện của tôi?

 String processName = _configuration.getProgramCommand().getCommand(); 
    ProcessBuilder procBuilder = new ProcessBuilder(processName); 

    System.out.println("Starting process "+processName); 
    _proc = Runtime.getRuntime().exec(processName);// procBuilder.start();    

    if(!procBuilder.redirectErrorStream()) {  
    _errorWorker = new ProcessErrorWorker(_proc); 
    _errorWorker.start(); 
    } 

    String proc_start_answer = _configuration.getNextCommand().getCommand(); 
    System.out.println("Waiting for process answer '"+proc_start_answer+"'"); 
    BufferedReader input = new BufferedReader(new InputStreamReader(_proc.getInputStream()));  

    String answer = ""; 

    try {   
    System.out.println("inputstream ready: "+input.ready()); 
    answer+=input.readLine(); 
    System.out.println("process answer: "+answer); 
    input.close();   

    } catch(Exception e) { 
    System.out.print(e.getMessage());  
    } 
+0

Bạn có gặp phải vấn đề này không? Bạn có thể đăng bài trong giải pháp không? –

Trả lời

6

Bạn cần thực hiện thao tác này trong một chuỗi. Ví dụ để ghi lại đầu ra tiêu chuẩn:

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

Sau đó, bạn cần một chuỗi thứ hai để xử lý đầu vào. Và bạn có thể muốn đối phó với stderr giống như stdout.

+0

Cảm ơn bạn đã trả lời. Trên thực tế, tôi đã thử nghiệm nó trong một chủ đề, trong tất cả các biến thể. Tôi đã thử đọc toàn bộ các dòng, đọc các ký tự đơn và đọc các byte. Không có hiệu lực. Tôi không thể nhận được một chút từ InputStream này, và nó chắc chắn sẽ phản ứng. Nó chỉ hoạt động nếu quá trình bắt đầu kết thúc (như "ps", "ls"). Nhưng tôi cũng cần nó để chạy với các quá trình "tương tác" như ftp và telnet, phải có một vấn đề mà tôi không biết. bất kỳ ý tưởng nào khác? – msg

9

Tôi nhận thấy đây là câu hỏi cũ, nhưng tôi chỉ gặp vấn đề tương tự. Để khắc phục điều này, tôi đã sử dụng mã này ..

List<String> commandAndParameters = ...; 
File dir = ...; // CWD for process 

ProcessBuilder builder = new ProcessBuilder(); 
builder.redirectErrorStream(true); // This is the important part 
builder.command(commandAndParameters); 
builder.directory(dir); 

Process process = builder.start(); 

InputStream is = process.getInputStream(); 

Dường như quá trình này cũng mong bạn cũng đọc từ luồng Lỗi. Cách khắc phục tốt nhất cho điều này là hợp nhất đầu vào và luồng lỗi với nhau.

Cập nhật

Tôi không thấy rằng bạn đã cố gắng để đọc từ stream lỗi cũng có. Nó chỉ có thể là bạn cần phải kết hợp chúng bằng tay với redirectErrorStream(true)

4

Tôi có vấn đề này với một chương trình in C đến thiết bị xuất chuẩn ...

Giải pháp redirectErrorStream(true) với một fflush(stdout) trong mã C đã làm các trick cho tôi .

+0

Điều này đã sửa nó cho tôi. Cảm ơn – Darc

1

Tôi gặp vấn đề tương tự. Rất tiếc,

processBuilder.redirectErrorStream(true); 

không hoạt động cho tôi; nó đã cho tôi một ý tưởng về những gì là sai mặc dù. Hãy thử sử dụng dòng mã sau đây để hiển thị nội dung stderr:

BufferedReader err= 
      new BufferedReader(new InputStreamReader(process.getErrorStream())); 

Nó giúp tôi tìm ra điều gì sai với các lệnh đầu cuối chạy qua mỗi luồng.

2

Tôi đã có cùng một vấn đề với ftp, cho đến khi tôi nhận thấy rằng ftp phát hiện nếu nó được gọi từ một thiết bị đầu cuối hay không.

Khi ftp không được gọi từ thiết bị đầu cuối, nó sẽ tạm dừng bất kỳ đầu ra nào để thoát ra, trừ khi tùy chọn tiết (v) được cung cấp.

Lý do chặn luồng là không có gì được ghi vào chúng.

4

Sau khi đấu tranh trong nhiều ngày và thử nhiều tùy chọn Tôi đã tìm thấy giải pháp. Làm việc trên Ubuntu 14.04 x64, với jdk 8 u 25.This codereview post đã cho tôi gợi ý.

Bí quyết là sử dụng InputStream#available() trước khi đọc bất kỳ thứ gì với số BufferedReader. Cá nhân tôi có hai chủ đề, một cho stdout và một cho stderr. Đây là một đoạn trích đơn giản mà tôi đã ngoại suy từ chương trình của mình. Nếu bạn không muốn đọc tất cả, chỉ cần nhảy tới readLine()

import org.apache.commons.io.IOUtils; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.InputStream; 
import java.io.BufferedReader; 
import java.nio.charset.Charset; 


public class LogHandler { 
    private BufferedReader bufferedReader; 
    private InputStream inputStream; 
    private Thread thread; 
    private boolean isRunning; 

    public void open (InputStream inputStream) { 
     this.inputStream = inputStream; 
     this.bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset())); 
     isRunning = true ; 

     if(thread!=null){ 
      thread = new Thread (()->{ 
       while(isRunning) { 
        String line = null; 
        try { 
         line = readLine(); 
        } catch (IOException e) { 
         isRunning = false; 
        } 
        if(line == null) { 
         try { 
          Thread.sleep(150); 
         } catch (InterruptedException ie) { 
          isRunning=false; 
          Thread.currentThread().interrupt(); 
         } 
        } else { 
         System.out.println(line); 
        } 
       } 
      }); 
     } else throw new IllegalStateException("The logger is already running"); 
     thread.start(); 
    } 

    public void close() throws InterruptedException { 
     if(thread!=null){ 
      thread.interrupt(); 
      thread.join(); 
      thread = null; 
      IOUtils.closeQuietly(inputStream); 
     } else throw new IllegalStateException("The logger is not running");   } 

    private String readLine() throws IOException { 
     if(inputStream.available()>0) { // <--------- THIS IS IT 
      int kar = bufferedReader.read(); 
      if (kar != -1) { 
       StringBuilder buffer = new StringBuilder(30); 
       while (kar != -1 && kar != (int) '\n') { 
        buffer.append((char) kar); 
        kar = bufferedReader.read(); 
       } 
       return buffer.toString(); 
      } 
     } 
     return null; 
    } 
} 
Các vấn đề liên quan