2010-07-01 8 views
20

मैं जावा के साथ बाहरी रूप से एक प्रक्रिया शुरू करने की कोशिश कर रहा हूं और इसके इनपुटस्ट्रीम से कुछ भी नहीं पढ़ सकता।जावा प्रक्रिया से इनपुटस्ट्रीम पढ़ने में असमर्थ (Runtime.getRuntime()। Exec() या ProcessBuilder)

यदि मैं "एलएस", "पीएस" या "मार" जैसे कमांड के साथ एक प्रक्रिया शुरू कर रहा हूं तो सब ठीक काम करता है। मैं प्रक्रिया शुरू कर सकता हूं और या तो इनपुटस्ट्रीम या प्रक्रिया के त्रुटि प्रवाह पर जानकारी प्राप्त कर सकता हूं।

यदि मैं "ftp" या "टेलनेट" जैसे कमांड का उपयोग करने का प्रयास करता हूं तो इनपुट इनपुट और त्रुटि स्ट्रीम दोनों पढ़ने के लिए प्रयास करते समय मेरे प्रोग्राम को अवरुद्ध कर रहे हैं। किसी भी समय इन धाराओं के माध्यम से कोई जानकारी नहीं दी जाती है।

क्या कोई व्यक्ति व्यवहार को समझा सकता है? क्या इन आदेशों के साथ यह संभव नहीं है या क्या मुझे अपने कार्यान्वयन के साथ कोई समस्या है?

 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

क्या आपको यह समस्या हल हो गई? क्या आप समाधान में पोस्ट कर सकते हैं? –

उत्तर

6

आपको इस काम को थ्रेड में करने की आवश्यकता है। उदाहरण के लिए मानक आउटपुट लॉग करने के लिए:

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

फिर आपको इनपुट हैंडलिंग के लिए दूसरे थ्रेड की आवश्यकता है। और आप stdout की तरह stderr से निपटना चाह सकते हैं।

+0

आपके उत्तर के लिए धन्यवाद। असल में मैं इसे सभी धागे में, धागे के भीतर परीक्षण कर रहा हूं। मैंने पूरी लाइनें पढ़ने, एकल वर्ण पढ़ने और बाइट पढ़ने की कोशिश की। कोई प्रभाव नहीं। मुझे इस इनपुटस्ट्रीम से थोड़ा सा नहीं मिल सकता है, और इसे निश्चित रूप से प्रतिक्रिया देनी चाहिए। यह केवल तभी काम करता है जब प्रारंभ प्रक्रिया समाप्त हो रही है (जैसे "ps", "ls")। लेकिन मुझे इसे "इंटरैक्टिव" प्रक्रियाओं जैसे एफटीपी और टेलनेट के साथ चलाने की भी आवश्यकता है, वहां एक मुद्दा होना चाहिए जिसके बारे में मुझे पता नहीं है। कोई भविष्य विचार? – msg

9

मुझे एहसास है कि यह प्रश्न पुराना है, लेकिन मुझे बस एक ही समस्या का अनुभव हुआ। इसे ठीक करने के लिए मैंने इस कोड का उपयोग किया ..

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

ऐसा प्रतीत होता है कि प्रक्रिया आपको त्रुटि स्ट्रीम से भी पढ़ने की उम्मीद कर रही है। इसके लिए सबसे अच्छा फिक्स इनपुट और त्रुटि स्ट्रीम को एक साथ मर्ज करना है।

अद्यतन

मैं नहीं देखा था कि आप भी त्रुटि स्ट्रीम से पढ़ने का प्रयास किया। यह सिर्फ हो सकता है कि आप उनके साथ redirectErrorStream(true)

4

मैं एक सी कार्यक्रम मुद्रण stdout के साथ इस मुद्दे पर था मैन्युअल रूप से विलय करने की आवश्यकता है ...

सी कोड में एक fflush(stdout) साथ redirectErrorStream(true) समाधान मेरे लिए चाल किया ।

+0

यह मेरे लिए तय है। धन्यवाद – Darc

1

मुझे एक ही समस्या थी। दुर्भाग्यवश

processBuilder.redirectErrorStream(true); 

मेरे लिए काम नहीं किया; यह मुझे एक गलत विचार है कि हालांकि क्या गलत है। stderr सामग्री प्रदर्शित करने के कोड की निम्न पंक्ति उपयोग करके देखें:

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

यह मुझे यह पता लगाने की क्या मेरी टर्मिनल प्रत्येक थ्रेड के माध्यम से चल आदेशों के साथ गलत था मदद की।

2

मुझे एफटीपी के साथ एक ही समस्या थी, जब तक मैंने देखा कि एफटीपी पता चलता है कि इसे टर्मिनल से नहीं कहा जाता है या नहीं।

जब टर्मिनल से ftp नहीं कहा जाता है, तो यह किसी भी आउटपुट को stdout को निलंबित करता है, जब तक वर्बोज़ (-v) विकल्प प्रदान नहीं किया जाता है।

धाराओं को अवरुद्ध करने का कारण यह है कि उन्हें कुछ भी नहीं लिखा गया है।

4

दिनों के लिए संघर्ष करने के बाद, और कई विकल्प पर प्रयास करने के बाद मुझे समाधान मिला। Jbk 8 u 25 के साथ उबंटू 14.04 x64 पर काम करना।This codereview post ने मुझे संकेत दिया।

चाल BufferedReader के साथ कुछ भी पढ़ने से पहले उपयोग करना है। मेरे पास व्यक्तिगत रूप से दो धागे हैं, एक stdout के लिए और दूसरा stderr के लिए। यहां एक सरल चलने वाला स्निपेट है जो मैंने अपने प्रोग्राम से निकाला है। यदि आप सभी को पढ़ना नहीं चाहते हैं, तो बस 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; 
    } 
} 
संबंधित मुद्दे