क्यों (या कैसे) रूट द्वारा उपयोग किए गए खुले फ़ाइल डिस्क्रिप्टर की संख्या ulimit -n से अधिक है?


13

हमारा सर्वर हाल ही में फ़ाइल डिस्क्रिप्टर से बाहर चला गया, और इस संबंध में मेरे कुछ प्रश्न हैं। ulimit -nमुझे अधिक से अधिक ओपन फाइल डिस्क्रिप्टर देने वाले हैं। यह संख्या 1024 है। मैंने चलकर ओपन फाइल डिस्क्रिप्टर की संख्या की जाँच की lsof -u root |wc -lऔर 2500 fds प्राप्त किए। यह 1024 से बहुत अधिक है, इसलिए मैंने अनुमान लगाया कि प्रति नंबर 1024 का मतलब प्रति प्रक्रिया है, न कि उपयोगकर्ता के अनुसार, हालांकि मैं। खैर, मैं भाग गया lsof -p$PidOfGlassfish|wc -lऔर 1300 मिला। यह वह हिस्सा है जो मुझे नहीं मिलता है। यदि ulimit -nउपयोगकर्ता या प्रक्रिया के अनुसार प्रक्रियाओं की अधिकतम संख्या नहीं है, तो इसके लिए क्या अच्छा है? क्या यह रूट उपयोगकर्ता पर लागू नहीं होता है? और यदि हां, तो मैं फ़ाइल डिस्क्रिप्टर से बाहर निकलने के बारे में त्रुटि संदेश कैसे प्राप्त कर सकता हूं?

EDIT: जिस तरह से मैं समझ बना सकता हूं वह एकमात्र तरीका ulimit -nहै यदि यह फ़ाइल हैंडल की संख्या के बजाय खुली फाइलों की संख्या (जैसा कि बैश मैनुअल में कहा गया है) लागू होता है (विभिन्न प्रक्रियाएं एक ही फाइल को खोल सकती हैं)। यदि यह मामला है, तो बस खुली फाइलों की संख्या को सूचीबद्ध करना ('/' पर संक्षिप्त करना, इस प्रकार मेमोरी मैप की गई फ़ाइलों को छोड़कर) पर्याप्त नहीं है :

lsof -u root |grep /|sort  -k9  |wc -l #prints '1738'

वास्तव में खुली फाइलों की संख्या देखने के लिए, मुझे केवल अद्वितीय प्रविष्टियों को प्रिंट करने के लिए नाम कॉलम पर फ़िल्टर करना होगा। इस प्रकार निम्नलिखित शायद अधिक सही है:

lsof -u root |grep /|sort  -k9 -u |wc -l #prints '604'

उपरोक्त कमांड lsof से निम्न प्रारूप पर आउटपुट की अपेक्षा करता है:

java      32008 root  mem       REG                8,2 11942368      72721 /usr/lib64/locale/locale-archive
vmtoolsd   4764 root  mem       REG                8,2    18624     106432 /usr/lib64/open-vm-tools/plugins/vmsvc/libguestInfo.so

यह कम से कम मुझे 1024 से कम संख्या (द्वारा सूचित संख्या ulimit -n) देता है, इसलिए यह सही दिशा में एक कदम की तरह लगता है। "दुर्भाग्य से" मुझे फ़ाइल डिस्क्रिप्टर से बाहर निकलने में कोई समस्या नहीं हो रही है, इसलिए मेरे पास इसे सत्यापित करने में कठिन समय होगा।


2
lsof मैमोरी मैपिंग के साथ-साथ ओपन फाइल की रिपोर्ट करता है, इसलिए आपकी 'wc' पाइपलाइन उस प्रक्रिया द्वारा उपयोग किए जाने वाले फ़ाइल डिस्क्रिप्टर की संख्या का एक अधिक-अनुमान लगाती है।
रिचर्ड केटलवेल

अहा! अब यह अच्छी जानकारी है। लेकिन मुझे पूरा यकीन नहीं है कि मैं समझ सकता हूं। "मेमोरी मैपिंग" से, आपका मतलब मेमोरी मैप्ड फाइल से है? यह मेरी समझ के लिए एक फ़ाइल संभाल की आवश्यकता होगी, या ओएस कैसे फ़ाइल को अपडेट करने में सक्षम होगा?
oligofren

और फॉलोअप दो: सभी खुले फ़ाइल हैंडल को खोजने का एक अच्छा तरीका क्या होगा - जो वास्तव में "अलिमिट-एन" द्वारा लगाए गए सीमा से प्रभावित होते हैं?
oligofren

1
मेमोरी मैपिंग के लिए एक खुली फ़ाइल की आवश्यकता नहीं होती है। यदि आप केवल खुली फाइलों को सूचीबद्ध करना चाहते हैं, तो lsof के आउटपुट को फ़िल्टर करना शायद सबसे आसान तरीका है।
रिचर्ड केटलवेल

धन्यवाद, मेरे उत्तर को संपादित किया। /Lsof -u root | grep / | sort -k9 -u to का प्रयोग उचित मात्रा में क्या मात्रा देता है। यह ulimit -n से कम से कम संख्या में है।
ऑलिगॉफ्रेन

जवाबों:


9

मैंने इसे लिनक्स संस्करण 2.6.18-164.el5 - रेड हैट 4.1.2-46 में परीक्षण किया। मैं देख सकता था कि प्रति प्रक्रिया लागू की जाती है।

पैरामीटर को उपयोगकर्ता के स्तर पर सेट किया गया है, लेकिन प्रत्येक प्रक्रिया के लिए आवेदन किया गया है।

जैसे: 1024 की सीमा थी। एकाधिक प्रक्रियाओं को शुरू किया गया था और हर एक के द्वारा खोली गई फ़ाइलों का उपयोग करके गिना गया था

ls -l /proc/--$pid--/fd/ | wc -l

जब एकाधिक प्रक्रियाओं द्वारा खोली गई फ़ाइलों का योग 1024 से पार हो गया, तो कोई त्रुटि नहीं थी। मैंने विभिन्न प्रक्रियाओं के परिणामों के संयोजन के लिए अद्वितीय फ़ाइल गणना को सत्यापित किया और अद्वितीय फ़ाइलों की गिनती की। त्रुटियां केवल तभी दिखाई देने लगीं जब प्रत्येक प्रक्रिया के लिए गिनती 1024 पार कर गई। (java.net.SocketException: प्रक्रिया लॉग में बहुत सारी खुली हुई फ़ाइलें)


इस परीक्षण के लिए धन्यवाद। क्या आपके पास कोई आइडिया है कि lsof -p$PidOfGlassfish|wc -lमुझे 1300 क्यों दिए गए? मैं अनुमान लगा रहा हूं कि मतगणना के लिए दोनों दृष्टिकोण किसी न किसी तरह भिन्न हैं। यदि नहीं, तो हो सकता है कि यह सीमा रूट उपयोगकर्ता पर लागू न हो?
ऑलिगॉफ्रेन

बस जिज्ञासु, क्यों के ls -lबजाय का उपयोग करें ls? बाद में total 55 फाइलें होने पर एक अतिरिक्त लाइन (जैसे ) होती है। ऐसे मामले ls -l में उपरोक्त उदाहरण का उपयोग करते हुए 6 नहीं 5. रिपोर्ट करेगा ls /proc/<pid>/fd | wc -l
स्टार

@ स्टारफ्री यह मेरी ओर से सिर्फ फूहड़ता है। मैं आमतौर पर इस चरणबद्धता को करता हूं, और ls -lमुझे प्रति पंक्ति एक प्रविष्टि देता है, जिसे मैं फिर किसी और चीज में पाइप करता हूं। प्रांगणों में, यह तब भी होता है जब सामान्य पाइपिंग ls(लेकिन नहीं तो)।
ऑलिगॉफ्रेन

3

फ़ाइलहैंड्स के लिए ulimit है। यह फाइलों, निर्देशिकाओं, सॉकेट्स, पाइप्स एपॉल्स, इवेंटफीड्स, टाइमरफीड्स आदि पर लागू होता है।

किसी भी प्रक्रिया में स्टार्टअप के दौरान सीमाएं बदल दी गई हो सकती हैं। पर जाएँ /proc/<pid>/limitsऔर देखें कि मूल्यों को बदल दिया गया है।


3

@oligofren

मैंने यह निर्धारित करने के "ulimits -Sn"लिए कुछ परीक्षण भी किए कि कैसे "open files"लागू किया गया था।

  • लिंक में बताए गए पोस्टर चुना की तरह , वास्तव में प्रति प्रक्रिया के लिए लागू किया गया है। यह देखने के लिए कि प्रक्रिया की वर्तमान सीमाएँ क्या हैं:"open files"

    cat /proc/__process_id__/limits

  • यह निर्धारित करने के लिए कि एक प्रक्रिया में कितनी फाइलें खुली हैं, आपको निम्नलिखित कमांड का उपयोग करने की आवश्यकता है:

    lsof -P -M -l -n -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -p __process_id__ -a | awk '{if (NR>1) print}' | wc -l

उपरोक्त और मेरी परीक्षण विधि / परिणामों की व्याख्या

"-P -M -l -n"करने के लिए तर्क lsof बनाने के लिए बस देखते हैं lsof के रूप में तेजी से संभव के रूप में काम करते हैं। बेझिझक उन्हें बाहर निकालें।

-P - inhibits the conversion of port numbers to port names for network files
-M - disable reporting of portmapper registrations for local TCP, UDP and UDPLITE ports
-l - inhibits the conversion of user ID numbers to login names
-n - inhibits the conversion of network numbers to host names for network files

"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"तर्क का निर्देश lsofप्रकार की फ़ाइल वर्णनकर्ता बाहर करने के लिए: CWD / अं / LTX / सदस्य / mmap / पीडी / RTD / txt।

Lsof मैन पेज से:

   FD         is the File Descriptor number of the file or:

                   cwd  current working directory;
                   Lnn  library references (AIX);
                   err  FD information error (see NAME column);
                   jld  jail directory (FreeBSD);
                   ltx  shared library text (code and data);
                   Mxx  hex memory-mapped type number xx.
                   m86  DOS Merge mapped file;
                   mem  memory-mapped file;
                   mmap memory-mapped device;
                   pd   parent directory;
                   rtd  root directory;
                   tr   kernel trace file (OpenBSD);
                   txt  program text (code and data);
                   v86  VP/ix mapped file;

मैंने "Lnn,jld,m86,tr,v86"लिनक्स पर लागू नहीं माना और इसलिए उन्हें बहिष्करण सूची में जोड़ने की जहमत नहीं उठाई। मुझे यकीन नहीं है "Mxx"

यदि आपका एप्लिकेशन मेमोरी मैप्ड फ़ाइलों / उपकरणों का उपयोग करता है तो आप अपवर्जन सूची से हटाना "^mem"और निकालना चाह सकते हैं "^mmap"

EDIT --- स्निप शुरू करें ---

संपादित करें: मुझे निम्न लिंक मिला जो इंगित करता है कि:

मेमोरी मैप्ड .so-files तकनीकी रूप से एक फाइल हैंडल के रूप में एक ही नहीं होती है जिस पर एप्लिकेशन का नियंत्रण होता है। / proc // fd ओपन फाइल डिस्क्रिप्टर के लिए मापने का बिंदु है

इसलिए यदि आपकी प्रक्रिया मेमोरी मैप्ड फ़ाइलों का उपयोग करती है, तो आपको * .so फ़ाइलों को फ़िल्टर करने की आवश्यकता होगी।

इसके अलावा, सूर्य की JVM, jar फाइलों को मैप करेगी

एक मेमोरी-मैपेड JARfile, इस मामले में "JDK क्लासेस" रखने वाली फ़ाइल। जब आप एक JAR को मेमोरी-मैप करते हैं, तो आप इसके भीतर फ़ाइलों को बहुत कुशलता से एक्सेस कर सकते हैं (प्रत्येक बार शुरू से इसे पढ़ते हुए)। सूर्य JVM क्लासपाथ पर सभी JAR को मेमोरी-मैप करेगा; यदि आपके एप्लिकेशन कोड को JAR तक पहुंचने की आवश्यकता है, तो आप इसे मेमोरी-मैप भी कर सकते हैं।

तो टॉमकट / ग्लासफिश जैसी चीजें मेमोरी मैप्ड जार फाइलें भी दिखाएंगी। मैंने परीक्षण नहीं किया है कि क्या ये "ulimit -Sn"सीमा की ओर हैं ।

EDIT --- एंड स्निप ---

अनुभव, मैं पाया है कि "cwd,rtd,txt"कर रहे हैं की गिनती नहीं की प्रक्रिया के अनुसार फ़ाइल सीमा के संबंध (ulimit -Sn) के साथ।

मुझे यकीन नहीं है कि क्या "err,ltx,pd"फ़ाइल सीमा की ओर गिना जाता है क्योंकि मुझे नहीं पता कि इन डिस्क्रिप्टर प्रकारों के फ़ाइल हैंडल कैसे बनाए जाते हैं।

"-p __process_id__"तर्क सम्बन्धी सीमाओं lsofके लिए ही जानकारी लौटाने के लिए __process_id__निर्दिष्ट। इसे निकालें यदि आप सभी प्रक्रियाओं के लिए एक गिनती प्राप्त करना चाहते हैं।

"-a"तर्क करने के लिए प्रयोग किया जाता है और चयन (यानी "-p" और "-d" तर्कों)।

"awk '{if (NR>1) print}'"बयान है कि शीर्ष लेख को छोड़ने के लिए प्रयोग किया जाता है lsofइसके उत्पादन में प्रिंट।

मैंने निम्नलिखित पर्ल स्क्रिप्ट का उपयोग करके परीक्षण किया:

File: test.pl
---snip---
#!/usr/bin/perl -w
foreach $i (1..1100) {
  $FH="FH${i}";
  open ($FH,'>',"/tmp/Test${i}.log") || die "$!";
  print $FH "$i\n";
}
---snip---

मुझे यह सुनिश्चित करने के लिए पर्ल डिबगर में स्क्रिप्ट निष्पादित करनी थी कि स्क्रिप्ट विवरण को समाप्त न करें और जारी न करें।

निष्पादन हेतु: perl -d test.pl

पर्ल के डिबगर में, आप दर्ज करके cऔर दबाकर प्रोग्राम चला सकते हैं और यदि आपका ulimit -Snमूल्य 1024 था , तो आप पाएंगे कि Test1017.logफ़ाइल बनाने के बाद प्रोग्राम बंद हो जाता है /tmp

यदि आप अब perl प्रक्रिया के pid की पहचान करते हैं और उपरोक्त lsofकमांड का उपयोग करते हैं, तो आप देखेंगे कि यह 1024 आउटपुट भी करता है ।

1024 सीमा की ओर गिनती करने वाली फ़ाइलों की सूची देखने के लिए इसे निकालें "wc -l"और इसे बदलें । यह देखने के लिए कि विवरण और विवरणक सीमा से दूर नहीं थे, यह तर्क निकालें ।"less""-d ^....."cwd,txtrtd

यदि आप अब चलाते हैं "ls -l /proc/__process_id__/fd/ | wc -l", तो आपको 1025 का मान लौटा दिखाई देगा । ऐसा इसलिए है क्योंकि इसके आउटपुट में lsएक "total 0"हेडर जोड़ा जाता है जो कि गिना जाता है।

ध्यान दें:

यह जाँचने के लिए कि OS फ़ाइल डिस्क्रिप्टर से बाहर चल रहा है या नहीं, इसकी कीमत की तुलना करना बेहतर है :

cat /proc/sys/fs/file-nr | awk '{print $1}'

साथ में

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txt दस्तावेजों का क्या file-nrऔर क्या file-maxमतलब है।


0

ऐसा लगता है कि आपका तर्क कुछ इस तरह है, "मुझे उस सीमा को कम करना होगा ताकि मैं अनमोल विवरणकों से बाहर न चला जाऊं"। सच्चाई बिल्कुल विपरीत होता है - यदि आपके सर्वर फ़ाइल वर्णनकर्ता से बाहर भाग, आप की जरूरत बढ़ा बड़ा कुछ करने के लिए 1,024 से उस सीमा। यथार्थवादी glassfishकार्यान्वयन के लिए, 32,768 उचित है।

व्यक्तिगत रूप से, मैं हमेशा 8,192 सिस्टम-वाइड - 1,024 की सीमा को बढ़ाता हूं, बस हास्यास्पद है। लेकिन आप glassfishऊंचा उठाना चाहते हैं । जाँच करें /etc/security/limits.conf। आप उपयोगकर्ता glassfishरन के लिए एक विशेष प्रविष्टि जोड़ सकते हैं ।


मुझे यकीन नहीं है कि आप मुझे कैसे समझा सकते हैं इसका मतलब है कि :-) मैं क्या सोच रहा था कि यह लागू क्यों नहीं हुआ। मैं इसे उच्चतर सेट करूंगा, लेकिन मैं समझना चाहता हूं कि यह कैसे काम करता है। यदि सीमा 1024 है, तो ग्लासफिश के पास 1300 हैंडल कैसे हो सकते हैं?
ओलिगोफ़्रेन

'lsof -u root | grep / | Sort -k9 -u' अनूठे फ़ाइल डिस्क्रिप्टर प्रविष्टियों को प्रिंट करता है। मुझे लगता है कि इस से लाइनों की संख्या वास्तविक संख्या ulimit -n पर लागू होती है।
ऑलिगॉफ्रेन

0

आप / proc / sys / fs / file-max में सेट किए गए सिस्टम-वाइड लिमिट्स पर एक नज़र डालना चाहते हैं और इसे तब तक एडजस्ट करते हैं (जब तक कि रिबूट न ​​हो) या इसे स्थायी बनाने के लिए sysctl.conf में fs.file-max सेट करें। यह उपयोगी हो सकता है - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
बैश के बारे में टिप्पणी सटीक नहीं है। ulimit शेल के माध्यम से शुरू की गई प्रक्रियाओं के लिए प्रति उपयोगकर्ता-आईडी सेट की सीमा को लागू करता है, जो अनिवार्य रूप से सब कुछ धन्यवाद है कि ऑपरेटिंग सिस्टम की तरह Unix पर प्रक्रिया ट्री को कैसे चलाया जाता है। यह बैश नहीं है।
आठबिटटनी

क्षमा करें - संपादित करेंगे, लेकिन सिस्टम विस्तृत सीमाओं के बारे में टिप्पणी अभी भी खड़ा है, हालांकि।
15

यह बहुत संभावना नहीं है कि वह सिस्टम की व्यापक सीमाओं को मार रहा है। संभव है, लेकिन बहुत संभावना नहीं है।
डेविड श्वार्ट्ज

एइटबिटटनी: एलिमिट प्रति यूजर आईडी की सीमा के अनुसार एलिमिट सेट नहीं करता है। Pam_limits लागू होने पर इसकी प्रति प्रक्रिया। वह ulimit जो "प्रति उपयोगकर्ता" है, "ulimit -u" "एकल उपयोगकर्ता के लिए उपलब्ध अधिकतम प्रक्रियाएँ"
No Username

0

माना जाता है कि कच्चे lsof कॉल के परिणाम की तुलना करने के लिए सामान्य गलती।

वैश्विक सीमा (/ proc / sys / fs / file-max) के लिए आपको / proc / sys / fs / file-nr पर एक नजर डालनी चाहिए -> मुट्ठी का उपयोग क्या इंगित करता है और अंतिम मान सीमा है

OpenFile सीमा प्रत्येक प्रक्रिया के लिए है, लेकिन इसे उपयोगकर्ता पर परिभाषित किया जा सकता है, उपयोगकर्ता सीमाओं के लिए "ulimit -Hn" कमांड देखें और परिभाषाओं के लिए /etc/security/limits.conf देखें। आम तौर पर "ऐप उपयोगकर्ता" के साथ लागू किया जाता है: उदाहरण के लिए: "टॉमकैट": उपयोगकर्ता टॉमकैट पर 65000 की सीमा निर्धारित करें जो इसे चलाने वाली जावा प्रक्रिया पर लागू होगा।

यदि आप किसी प्रक्रिया पर लागू सीमा की जाँच करना चाहते हैं, तो उसका PID प्राप्त करें और फिर: cat / proc / $ {PID} / सीमाएँ यदि आप जाँचना चाहते हैं कि किसी प्रक्रिया द्वारा कितनी फ़ाइल खोली गई हैं, तो उसका PID प्राप्त करें और फिर: ls -1 / proc / {PID} / fd | wc -l (ls के लिए ध्यान दें कि यह 'माइनस वन' है, 'माइनस एल' के साथ मेल खाने के लिए नहीं)

यदि आप lsof के साथ विवरण जानना चाहते हैं, लेकिन केवल उन फ़ाइल हैंडर्स के लिए जो सीमा के लिए गणना करते हैं, तो थोस के साथ प्रयास करें: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ इरेट, ^ ltx, ^ मेम, ^ mmap, ^ pd, ^ rtd। ^ txt '-ए

टिप्पणी: 'फाइलें' फाइलें / पाइप / टीसीपी कनेक्शन / आदि हैं।

ध्यान दें कि कभी-कभी आपको संभवतः रूट के लिए या कमांडो के लिए सही परिणाम प्राप्त करने के लिए sudo का उपयोग करने की आवश्यकता होगी, विशेषाधिकार के बिना कभी-कभी आपको त्रुटि नहीं होती है, बस कम परिणाम।

और अंत में अगर आप यह जानना चाहते हैं कि आपके फाइल सिस्टम पर कौन सी 'फाइलें' एक प्रक्रिया द्वारा एक्सेस की जाती हैं, तो एक नज़र डालें: lsof -p {PID} | grep / | awk '{प्रिंट $ 9}' | सॉर्ट | uniq

मज़े करो !

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.