2010-07-19 18 views
28

मैं जावा के प्रोसेस बिल्डर का उपयोग लिनक्स में एक एप्लिकेशन लॉन्च करने की कोशिश कर रहा हूं जिसे "दीर्घकालिक" चलाना चाहिए। जिस तरह से यह प्रोग्राम चलता है वह एक कमांड लॉन्च करना है (इस मामले में, मैं एक मीडिया प्लेबैक एप्लिकेशन लॉन्च कर रहा हूं), इसे चलाने की अनुमति दें, और यह सुनिश्चित करने के लिए जांचें कि यह क्रैश नहीं हुआ है। उदाहरण के लिए, यह देखने के लिए जांचें कि पीआईडी ​​अभी भी सक्रिय है या नहीं, और फिर प्रक्रिया समाप्त हो जाती है, अगर यह मर गई है।जावा प्रोसेसबिल्डर: परिणामस्वरूप प्रक्रिया

मुझे जो समस्या हो रही है वह यह है कि पीआईडी ​​सिस्टम में जिंदा है, लेकिन आवेदन के लिए जीयूआई लटकता है। मैंने ProcessBuilder (cmd) .start() को एक अलग थ्रेड में स्थानांतरित करने का प्रयास किया, लेकिन ऐसा लगता है कि यह कुछ भी हल नहीं कर रहा है, जैसा कि मैंने आशा की थी कि यह होगा।

मूल रूप से परिणाम यह है कि, उपयोगकर्ता के लिए, प्रोग्राम अपरिपक्व हो गया है, लेकिन प्रक्रिया प्रक्रिया को चलाने वाली जावा प्रक्रिया को मारना वास्तव में प्रक्रिया को अपने सामान्य व्यवहार को फिर से शुरू करने की अनुमति देता है। इसका मतलब है कि जावा एप्लिकेशन में कुछ स्पॉन्डेड प्रोसेस के साथ हस्तक्षेप कर रहा है, लेकिन मुझे इस बात पर बिल्कुल कोई जानकारी नहीं है। (इसलिए मैंने इसे किसी अन्य धागे में अलग करने की कोशिश क्यों की, जो कुछ भी हल नहीं कर रहा था)

अगर किसी के पास कोई इनपुट/विचार है, तो कृपया मुझे बताएं, क्योंकि मैं अपने जीवन के लिए नहीं सोच सकता इस समस्या के समाधान के लिये।

संपादित करें: मुझे प्रक्रिया से बनाए गए I/O स्ट्रीम पर कोई चिंता नहीं है, और इस तरह से निपटने के लिए कोई कदम नहीं उठाया गया है - क्या यह प्रक्रिया में ही लटका सकता है?

+3

चूंकि आपने पहले से ही कहा है कि आप प्रक्रिया की धाराओं से निपट नहीं रहे हैं, मुझे यह कहना चाहिए कि "हां, यह संभावना है कि यह समस्या का कारण है। पढ़ना महत्वपूर्ण है। stdout और stderr की सामग्री, और अगर बच्चा आपको उम्मीद करता है तो stdin को भी लिखें "। इस SO प्रश्न को जांचने के लिए आपके समय के लायक होंगे: http://stackoverflow.com/questions/882772/capturing-stdout-when-calling-runtime-exec/882795#882795 –

उत्तर

30

यदि प्रक्रिया stderr या stdout को लिखती है, और आप इसे पढ़ नहीं रहे हैं - यह केवल "लटका" होगा, stdout/err पर लिखते समय अवरुद्ध होगा। या तो अनुप्रेषित stdout/अं/dev/बातिल करने के लिए एक खोल का उपयोग कर या redirectErrorStream (सही) के साथ stdout/अं विलय और एक अन्य धागा है कि इस प्रक्रिया

+5

यह बहुत महत्वपूर्ण लगता है!आपको ffmpeg से stdout/stderr पर विचार करना है। कम से कम मैंने आरटीएमपी कनेक्शन प्रकाशित/उपभोग करने के लिए ऐसा देखा। – Nicholi

2

संपादित करें: मुझे प्रक्रिया से बनाए गए I/O स्ट्रीम पर कोई चिंता नहीं है, और इस तरह से निपटने के लिए कोई कदम नहीं उठाया गया है - क्या यह प्रक्रिया में ही लटका सकता है?

यदि आप प्रक्रिया द्वारा बनाई गई आउटपुट स्ट्रीम नहीं पढ़ते हैं तो यह संभव है कि आवेदन के बफर भरने के बाद एप्लिकेशन ब्लॉक हो जाएगा। मैंने कभी यह लिनक्स पर नहीं देखा है (हालांकि मैं यह नहीं कह रहा हूं कि यह नहीं है) लेकिन मैंने विंडोज़ पर यह सटीक समस्या देखी है। मुझे लगता है कि यह संभवतः संबंधित है।

11

की stdout से पढ़ता अंडे आप चाल करना चाहते हैं?

ProcessBuilder.start() से अपनी प्रक्रिया शुरू न करें। धारा पुनर्निर्देशन/जावा से खपत के साथ गड़बड़ करने की कोशिश मत करो (विशेष रूप से यदि आप कोई है देना टी इसके बारे में **;)

उपयोग ProcessBuilder.start() एक छोटे से खोल स्क्रिप्ट है कि सभी इनपुट gobbles शुरू करने के लिए/आउटपुट धाराओं।

कुछ इस तरह:

#!/bin/bash 

nohup $1 >/dev/null 2>error.log & 

यही कारण है: यदि आप stdout के बारे में परवाह नहीं है और अभी भी stderr लॉग इन करना चाहते एक फाइल करने के लिए (error.log यहाँ) (यदि आप करते हैं?)।

तुम भी stderr के बारे में परवाह नहीं है, बस इसे stdout के लिए अनुप्रेषित:

#!/bin/bash 

nohup $1 >/dev/null 2>1 & 

और तुम फोन है कि जावा से छोटे स्क्रिप्ट, एक तर्क के रूप में यह दे रही है प्रक्रिया आप चलाना चाहते हैं के नाम ।

एक प्रक्रिया लिनक्स पर चल रहा है कि/dev/बातिल करने के लिए दोनों stdout और stderr रीडायरेक्ट हो रहा है अभी भी कुछ भी तो उत्पादन आप एक टूटी हुई, अनुपालन न करने वाले मिल गया है, लिनक्स स्थापित कर लेते हैं;)

दूसरे शब्दों में : उपर्युक्त जस्ट वर्क्स [टीएम] और समस्याग्रस्त से छुटकारा पाएं "आपको इसमें धाराओं का उपभोग करने की आवश्यकता है और वह ऑर्डर ब्लै ब्ला ब्ल जावा-विशिष्ट गैर-भावना"

http://download.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

इस बीच, अगर तुम सच में/stderr stdout अभी नहीं करना चाहते हैं, यह सबसे अच्छा (लिनक्स पर) लगता है पर ProcessBuilder आह्वान करने के लिए:

+0

हमें एक अच्छा हंसी मिली - यह अब शुक्रवार की रात है और यह हमारी शाम हमें खर्च करता है :) –

2

JDK7 उपप्रक्रिया आई/ओ पुनर्निर्देशन के लिए अंतर्निहित समर्थन करना होगा एक आदेश जो दिखता है:

["/bin/bash", "-c", "exec YOUR_COMMAND_HERE >/dev/null 2>&1"] 
5

मुझे इसी तरह की समस्या के बाद बस इस पर ठोकर खाई। नोस के साथ सहमत होने पर, आपको आउटपुट को संभालने की आवश्यकता है। मेरे पास ऐसा कुछ था:

ProcessBuilder myProc2 = new ProcessBuilder(command); 
final Process process = myProc2.start(); 

और यह बहुत अच्छा काम कर रहा था। उत्पन्न प्रक्रिया ने आउटपुट कुछ आउटपुट भी किया लेकिन अधिक नहीं। जब मैंने बहुत अधिक उत्पादन शुरू किया, तो ऐसा हुआ कि मेरी प्रक्रिया अब और भी लॉन्च नहीं हुई थी। मैंने इसे अद्यतन किया:

ProcessBuilder myProc2 = new ProcessBuilder(command); 
myProc2.redirectErrorStream(true);   
final Process process = myProc2.start(); 
InputStream myIS = process.getInputStream(); 
String tempOut = convertStreamToStr(myIS); 

और यह फिर से काम करना शुरू कर दिया। (convertStreamToStr() कोड के लिए इस लिंक का संदर्भ लें: http://singztechmusings.wordpress.com/2011/06/21/getting-started-with-javas-processbuilder-a-sample-utility-class-to-interact-with-linux-from-java-program/)

11

अगर प्रक्रिया को चलाने वाला थ्रेड ब्लॉक हो सकता है तो यह आउटपुट को संभाल नहीं सकता है। यह प्रक्रिया के आउटपुट को पढ़ने वाले एक नए थ्रेड को बढ़ाकर किया जा सकता है।

final ProcessBuilder builder = new ProcessBuilder("script") 
        .redirectErrorStream(true) 
        .directory(workDirectory); 

    final Process process = builder.start(); 
    final StringWriter writer = new StringWriter(); 

    new Thread(new Runnable() { 
     public void run() { 
      IOUtils.copy(process.getInputStream(), writer); 
     } 
    }).start(); 

    final int exitValue = process.waitFor(); 
    final String processOutput = writer.toString(); 
+0

धागा खत्म नहीं होता – user1120007

0

मामले में आप stdout और stderr पर कब्जा है और इस प्रक्रिया का उपयोग कर तो Apache Commons Exec मुझे एक बहुत मदद की निगरानी करने के लिए की जरूरत है।

0

मुझे विश्वास है कि समस्या लिनक्स से ही बफरिंग पाइप है।

अपने निष्पादन

new ProcessBuilder().command("/usr/bin/stdbuf","-o0","*executable*","*arguments*");** 

-o0 उत्पादन बफ़र होना नहीं कहते के साथ stdbuf उपयोग करने के लिए प्रयास करें। यदि आप इनपुट और त्रुटि पाइप को अनबफर करना चाहते हैं तो -i0 और -e0 पर जाता है।

संबंधित मुद्दे