2010-01-11 20 views
22

मैं लिनक्स पर जेट्टी 7.0.1 में चल रहे जावा वेबैप में फ़ाइल डिस्क्रिप्टर रिसाव डीबग करने का प्रयास कर रहा हूं।IOException: बहुत सारी खुली फ़ाइलें

ऐप खुशी से एक महीने या उससे भी अधिक समय तक चल रहा था जब के कारण अनुरोध विफल होने लगे,, और जेटी को पुनरारंभ करना पड़ा।

java.io.IOException: Cannot run program [external program]: java.io.IOException: error=24, Too many open files 
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:459) 
    at java.lang.Runtime.exec(Runtime.java:593) 
    at org.apache.commons.exec.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58) 
    at org.apache.commons.exec.DefaultExecutor.launch(DefaultExecutor.java:246) 

पहले तो मैंने सोचा था कि इस मुद्दे को कोड है कि बाहरी कार्यक्रम की शुरूआत के साथ था, लेकिन यह commons-exec उपयोग कर रहा है और मैं इसके साथ कुछ भी गलत नहीं दिखाई देता है: पर खुली फ़ाइलों लिस्टिंग

CommandLine command = new CommandLine("/path/to/command") 
    .addArgument("..."); 
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream(); 
Executor executor = new DefaultExecutor(); 
executor.setWatchdog(new ExecuteWatchdog(PROCESS_TIMEOUT)); 
executor.setStreamHandler(new PumpStreamHandler(null, errorBuffer)); 
try { 
    executor.execute(command); 
} catch (ExecuteException executeException) { 
    if (executeException.getExitValue() == EXIT_CODE_TIMEOUT) { 
     throw new MyCommandException("timeout"); 
    } else { 
     throw new MyCommandException(errorBuffer.toString("UTF-8")); 
    } 
} 

सर्वर मैं FIFOs की बड़ी संख्या में देख सकते हैं:

# lsof -u jetty 
... 
java 524 jetty 218w FIFO  0,6  0t0 19404236 pipe 
java 524 jetty 219r FIFO  0,6  0t0 19404008 pipe 
java 524 jetty 220r FIFO  0,6  0t0 19404237 pipe 
java 524 jetty 222r FIFO  0,6  0t0 19404238 pipe 

जब जेट्टी शुरू होता है सिर्फ 10 FIFOs कुछ दिनों के बाद उनमें से सैकड़ों देखते हैं देखते हैं,।

मुझे पता है कि यह इस चरण में थोड़ा अस्पष्ट है, लेकिन क्या आपके पास आगे देखने के लिए कोई सुझाव है, या उन फाइल डिस्क्रिप्टरों के बारे में अधिक विस्तृत जानकारी कैसे प्राप्त करें?

+0

चलिए कुछ कोड देखें –

+0

बाहरी प्रोग्राम लॉन्च करने वाला कोड जोड़ा गया। –

+0

informaiton netstat -anp --tcp के अतिरिक्त स्रोत के रूप में | grep - रंग – zaletniy

उत्तर

7

आपका बाहरी प्रोग्राम ठीक से व्यवहार नहीं करता है। एक नज़र डालें कि ऐसा क्यों नहीं करता है।

+0

तो आप कह रहे हैं कि यह बाहरी प्रोग्राम है जो फाइल डिस्क्रिप्टर को रिसाव करता है? लेकिन जेटी को तब तक सभी एफआईएफओ को क्यों रोक दिया जाता है? –

+0

यह वास्तव में कुछ मामलों में असामान्य रूप से समाप्त हो सकता है, और मैं इससे बच नहीं सकता: यह उपयोगकर्ता इनपुट पर निर्भर करता है। लेकिन यह तब भी मुद्दा हो सकता है। –

+0

यहां हडसन समस्या है: https://hudson.dev.java.net/issues/show_bug.cgi?id=715 –

8

जैसा कि आप लिनक्स पर चल रहे हैं, मुझे संदेह है कि आप फ़ाइल डिस्क्रिप्टर से बाहर हैं। उलमिट देखें। यहां एक आलेख है जो समस्या का वर्णन करता है: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

+6

यह आपको 2 महीने तक रन-टाइम तक ले सकता है! (यह सबसे अच्छा बैंड-एड्स है।) –

+1

आपने लक्षण को दोबारा दोहराया है लेकिन असली इलाज नहीं है। –

+0

असल में मैंने अन्य कारणों से '/ etc/security/limit.conf' में सीमा बढ़ा दी है। –

5

अपने ऐप की प्रकृति को नहीं जानते हैं, लेकिन मैंने कनेक्शन पूल रिसाव के कारण यह त्रुटि कई बार प्रकट की है, इसलिए यह जांचने योग्य होगा। लिनक्स पर, सॉकेट कनेक्शन फाइल डिस्क्रिप्टर के साथ ही फाइल सिस्टम फाइलों का उपभोग करते हैं। सिर्फ एक विचार।

2

आप स्वयं fds को संभाल सकते हैं। जावा में निष्पादन एक प्रक्रिया वस्तु देता है। अंततः जांच करें कि प्रक्रिया अभी भी चल रही है या नहीं। एक बार यह प्रक्रिया पूरी हो गई है एसटीडीईआरआर, एसटीडीआईएन, और एसटीडीओयूटी धाराओं (उदाहरण के लिए proc.getErrorStream.close())। इससे लीक कम हो जाएगी।

22

समस्या आपके जावा एप्लिकेशन (या एक लाइब्रेरी जिसका आप उपयोग कर रहे हैं) से आती है।

पहले, आपको पूरे आउटपुट (StreamGobbler के लिए Google), और pronto पढ़ना चाहिए!

Javadoc का कहना है:

माता पिता प्रक्रिया इन धाराओं का उपयोग करता है के लिए इनपुट फ़ीड और उपप्रक्रिया से उत्पादन प्राप्त करने के लिए। क्योंकि कुछ देशी प्लेटफार्मों केवल सीमित बफर मानक इनपुट और आउटपुट धाराओं, विफलता तुरंत इनपुट धारा लिखने या उपप्रक्रिया के उत्पादन में धारा पढ़ ब्लॉक करने के लिए उपप्रक्रिया का कारण हो सकता करने के लिए के लिए आकार, और यहां तक ​​कि गतिरोध प्रदान करते हैं।

दूसरे, waitFor() अपने प्रक्रिया समाप्त करने के लिए। फिर आपको इनपुट, आउटपुट और त्रुटि स्ट्रीम बंद करनी चाहिए।

अंत मेंdestroy() आपकी प्रक्रिया।

मेरे सूत्रों:

+1

यह सही उत्तर है जिसमें वास्तव में उपयोगी जानकारी होती है। –

+2

यदि प्रतीक्षा करें() 'सफल हो गया है तो आपको प्रक्रिया को नष्ट करने की आवश्यकता नहीं है। प्रक्रिया पहले से ही बाहर हो चुकी है। – EJP

4

एक तरफ करने के लिए एक वैध वृद्धि करने के लिए फ़ाइल लीक, आदि जैसे मूल कारण मुद्दों की जांच कर रहे से " फाइलें खोलें "सीमा और रीबूट पर बने रहें,

01 संपादित करने पर विचार करें
/etc/security/limits.conf 
इस

jetty soft nofile 2048 
jetty hard nofile 4096 

जहां "घाट" इस मामले में उपयोगकर्ता नाम है की तरह कुछ जोड़कर

। limits.conf के बारे में अधिक जानकारी के लिए, http://linux.die.net/man/5/limits.conf

लॉग बंद देख सकते हैं और फिर पुनः लॉग इन और

ulimit -n 

सत्यापित करने के लिए कि परिवर्तन हुआ है चलाते हैं। इस उपयोगकर्ता द्वारा नई प्रक्रियाओं को अब इस परिवर्तन का पालन करना चाहिए। This link वर्णन करता है कि पहले से चल रही प्रक्रियाओं पर सीमा को कैसे लागू किया जाए, लेकिन मैंने कोशिश नहीं की है।

डिफ़ॉल्ट जावा अनुप्रयोगों के लिए डिफ़ॉल्ट सीमा 1024 बहुत कम हो सकती है।

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