ทำไม (หรือวิธี) จำนวนตัวอธิบายไฟล์แบบเปิดที่ใช้โดย root เกิน ulimit -n?


13

เมื่อเร็ว ๆ นี้เซิร์ฟเวอร์ของเราไม่มีตัวอธิบายไฟล์และในกรณีที่ฉันมีคำถาม ulimit -nฉันควรจะให้จำนวนตัวอธิบายไฟล์ที่เปิดสูงสุดให้ฉัน หมายเลขนั้นคือ 1024 ฉันตรวจสอบจำนวนตัวอธิบายไฟล์ที่เปิดอยู่โดยเรียกใช้lsof -u root |wc -lและได้ 2500 fds นั่นคือมากเกินกว่า 1024 ดังนั้นฉันเดาว่าจะหมายถึงจำนวน 1024 เป็นต่อกระบวนการไม่ใช่ต่อผู้ใช้อย่างที่ฉันคิด ฉันวิ่งlsof -p$PidOfGlassfish|wc -lและได้ 1,300 นี่คือส่วนที่ฉันไม่ได้รับ หากulimit -nไม่ใช่จำนวนสูงสุดของกระบวนการต่อผู้ใช้หรือต่อกระบวนการดังนั้นมันดีสำหรับอะไร? ไม่ได้ใช้กับผู้ใช้รูทหรือไม่? และถ้าเป็นเช่นนั้นฉันจะได้รับข้อความแสดงข้อผิดพลาดเกี่ยวกับการหมดไฟล์ descriptor ได้อย่างไร?

แก้ไข:วิธีเดียวที่ฉันสามารถทำให้เข้าใจได้ulimit -nคือถ้ามันใช้จำนวนไฟล์ที่เปิด (ตามที่ระบุไว้ในคู่มือทุบตี) มากกว่าจำนวนของการจัดการไฟล์ (กระบวนการที่แตกต่างกันสามารถเปิดไฟล์เดียวกัน) หากเป็นกรณีนี้เพียงแค่แสดงรายการจำนวนไฟล์ที่เปิด (grepping บน '/' ซึ่งไม่รวมไฟล์ที่แม็พหน่วยความจำ) ไม่เพียงพอ:

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' จะให้จำนวนของตัวอธิบายไฟล์ที่ใช้โดยกระบวนการนั้นมากเกินไป
Richard Kettlewell

AHA! ตอนนี้เป็นข้อมูลที่ดี แต่ฉันไม่แน่ใจว่าฉันเข้าใจ โดย "การแมปหน่วยความจำ" คุณหมายถึงไฟล์ที่แมปหน่วยความจำหรือไม่ นั่นจะต้องมีการจัดการกับไฟล์เพื่อความเข้าใจของฉันหรือระบบปฏิบัติการอื่นจะสามารถอัปเดตไฟล์ได้อย่างไร
oligofren

และติดตามสอง: อะไรจะเป็นวิธีที่ดีในการค้นหาตัวจัดการไฟล์ที่เปิดทั้งหมด - ตัวที่ได้รับผลกระทบจากขีด จำกัด ที่กำหนดโดย "ulimit -n" จริง ๆ ?
oligofren

1
การแม็พหน่วยความจำไม่ต้องการไฟล์เปิด หากคุณต้องการแสดงรายการไฟล์ที่เปิดอยู่เท่านั้นการกรองผลลัพธ์ของ lsof อาจเป็นวิธีที่ง่ายที่สุด
Richard Kettlewell

ขอบคุณแก้ไขคำตอบของฉัน การใช้´lsof -u root | grep / | sort -k9 -u´ ดูเหมือนจะให้คำตอบที่สมเหตุสมผล นี่คือตัวเลขอย่างน้อยน้อยกว่า ulimit -n
oligofren

คำตอบ:


9

ฉันทดสอบใน Linux เวอร์ชัน 2.6.18-164.el5 - Red Hat 4.1.2-46 ฉันจะเห็นว่า ulimit ถูกนำไปใช้ต่อกระบวนการ

พารามิเตอร์ถูกตั้งค่าที่ระดับผู้ใช้ แต่ใช้สำหรับแต่ละกระบวนการ

เช่น 1024 คือขีด จำกัด กระบวนการหลายรายการเริ่มขึ้นและไฟล์ที่เปิดโดยแต่ละรายการจะถูกนับโดยใช้

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

ไม่มีข้อผิดพลาดเมื่อผลรวมของไฟล์ที่เปิดโดยหลายกระบวนการข้าม 1024 ฉันยังตรวจสอบการนับไฟล์ที่ไม่ซ้ำกันรวมผลลัพธ์สำหรับกระบวนการที่แตกต่างกันและการนับไฟล์ที่ไม่ซ้ำกัน ข้อผิดพลาดเริ่มปรากฏขึ้นเมื่อการนับสำหรับแต่ละกระบวนการข้าม 1024 (java.net.SocketException: ไฟล์ที่เปิดมากเกินไปในบันทึกกระบวนการ)


ขอบคุณสำหรับการทดสอบนี้ คุณมีความคิดใดบ้างที่lsof -p$PidOfGlassfish|wc -lให้ 1300 ฉัน ฉันเดาว่าทั้งสองวิธีในการนับนั้นต่างกันอย่างไร ถ้าไม่เช่นนั้นข้อ จำกัด อาจใช้ไม่ได้กับผู้ใช้รูท?
oligofren

แค่สงสัยใช้ทำไมls -lแทนls? หลังมีบรรทัดพิเศษ (เช่นtotal 5) เมื่อมี 5 ไฟล์ ในกรณีดังกล่าวใช้ในตัวอย่างข้างต้นจะรายงานผลการใช้ls -l 6 ไม่ 5. ฉัน ls /proc/<pid>/fd | wc -l
starfry

@starfry นั่นเป็นเพียงความสะเพร่าในส่วนของฉัน ฉันมักจะทำตามขั้นตอนนี้และls -lให้ฉันหนึ่งรายการต่อบรรทัดซึ่งฉันท่อไปอย่างอื่น แน่นอนว่าสิ่งนี้เกิดขึ้นได้เมื่อท่อปกติls(แต่ไม่มีอย่างอื่น)
oligofren

3

ulimit สำหรับ filehandles มันใช้กับไฟล์, ไดเรกทอรี, ซ็อกเก็ต, epolls ท่อ, eventfds, timerfds ฯลฯ ฯลฯ

ณ จุดใด ๆ ในระหว่างกระบวนการเริ่มต้นข้อ จำกัด อาจมีการเปลี่ยนแปลง เยี่ยมชม/proc/<pid>/limitsและดูว่ามีการเปลี่ยนแปลงค่าหรือไม่


3

@oligofren

ฉันยังทำการทดสอบเพื่อกำหนดวิธี"ulimits -Sn"การ"open files"บังคับใช้

  • เช่นเดียวกับโปสเตอร์ที่ได้รับการกล่าวถึงในลิงค์ ulimit สำหรับ"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 / PD / 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"ไม่สามารถใช้ได้กับ Linux และด้วยเหตุนี้จึงไม่ต้องสนใจเพิ่มลงในรายการยกเว้น "Mxx"ผมไม่แน่ใจว่าเกี่ยวกับ

หากแอปพลิเคชันของคุณใช้ประโยชน์จากไฟล์ / อุปกรณ์ที่แมปหน่วยความจำคุณอาจต้องการลบ"^mem"และออก"^mmap"จากรายการยกเว้น

แก้ไข --- เริ่ม snip ---

แก้ไข: ฉันพบลิงค์ต่อไปนี้ซึ่งระบุว่า:

หน่วยความจำที่แมป. so-files ในทางเทคนิคนั้นไม่เหมือนกับที่จัดการกับไฟล์ที่แอปพลิเคชันควบคุมได้ / proc // fd เป็นจุดวัดสำหรับตัวอธิบายไฟล์แบบเปิด

ดังนั้นหากกระบวนการของคุณใช้ไฟล์ที่แม็พหน่วยความจำคุณจะต้องกรองไฟล์ * .so ออก

นอกจากนี้ JVM ของ Sun จะจดจำไฟล์ jar ของแม็พด้วย

JARfile ที่แม็พหน่วยความจำในกรณีนี้ไฟล์ที่เก็บ "คลาส JDK" เมื่อหน่วยความจำแมป JAR คุณสามารถเข้าถึงไฟล์ที่อยู่ในนั้นได้อย่างมีประสิทธิภาพ (เทียบกับการอ่านตั้งแต่เริ่มต้นแต่ละครั้ง) Sun JVM จะทำการแมป JAR ทั้งหมดไว้บน classpath หากรหัสแอปพลิเคชันของคุณจำเป็นต้องเข้าถึง JAR คุณยังสามารถแมปหน่วยความจำได้

ดังนั้นสิ่งต่างๆเช่น Tomcat / glassfish จะแสดงไฟล์ jar ที่แม็พหน่วยความจำด้วย ฉันไม่ได้ทดสอบว่าจำนวนเหล่านี้มีค่าถึง"ulimit -Sn"ขีด จำกัด หรือไม่

แก้ไข --- end snip ---

สังเกตุฉันพบว่า"cwd,rtd,txt"จะไม่ถูกนับโดยคำนึงถึงขีด จำกัด ของไฟล์ต่อกระบวนการ (ulimit -Sn)

ฉันไม่แน่ใจว่า"err,ltx,pd"ถูกนับรวมในขีด จำกัด ของไฟล์หรือไม่เนื่องจากฉันไม่ทราบวิธีสร้างตัวจัดการไฟล์ประเภทตัวอธิบายเหล่านี้

"-p __process_id__"อาร์กิวเมนต์ข้อกำหนดด้านlsofข้อมูลกลับมาเฉพาะสำหรับ__process_id__ระบุ ลบสิ่งนี้ถ้าคุณต้องการได้รับการนับสำหรับกระบวนการทั้งหมด

"-a"อาร์กิวเมนต์จะใช้ในการและการเลือก (เช่น "-p" และ "-d" ข้อโต้แย้ง)

"awk '{if (NR>1) print}'"คำสั่งที่ใช้ในการข้ามส่วนหัวที่lsofพิมพ์ในการส่งออกของ

ฉันทดสอบโดยใช้สคริปต์ perl ต่อไปนี้:

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 เพื่อให้แน่ใจว่าสคริปต์จะไม่ยุติและปล่อยไฟล์ descriptors

ในการดำเนินการ: perl -d test.pl

ในการดีบักของ Perl คุณสามารถเรียกใช้โปรแกรมโดยการป้อนcและกด Enter และหากคุณulimit -Snมีค่าของ1024 , คุณจะพบว่าโปรแกรมหยุดหลังจากที่สร้างแฟ้มในTest1017.log/tmp

ถ้าตอนนี้คุณระบุ pid ของกระบวนการ Perl และใช้ข้างต้นlsofคำสั่งคุณจะเห็นว่ามันยังเอาท์พุท1024

ลบ"wc -l"และแทนที่ด้วย a "less"เพื่อดูรายการไฟล์ที่นับจนถึงขีด จำกัด1024 ลบ"-d ^....."อาร์กิวเมนต์ด้วยเพื่อดูว่าตัวให้คำอธิบายcwd,txtและrtdคำไม่นับรวมในขีด จำกัด

หากคุณรันตอนนี้"ls -l /proc/__process_id__/fd/ | wc -l"คุณจะเห็นค่า1025 ที่ส่งคืน นี่เป็นเพราะlsเพิ่ม"total 0"ส่วนหัวไปยังเอาต์พุตที่นับไว้

บันทึก:

ในการตรวจสอบว่าระบบปฏิบัติการไม่ทำงานกับตัวให้คำอธิบายถึงไฟล์จะเป็นการดีกว่าที่จะเปรียบเทียบค่าของ:

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 แล้ว Glassfish จะมีที่จับได้ 1,300 ตัวอย่างไร
oligofren

'lsof -u root | grep / | sort -k9 -u' พิมพ์รายการไฟล์ descriptor ที่ไม่ซ้ำกัน ฉันเดาว่าจำนวนบรรทัดจากนี้คือจำนวน ulimit -n ที่ใช้จริง
oligofren

0

คุณต้องการดูข้อ จำกัด ของทั้งระบบที่ตั้งค่าใน / proc / sys / fs / file-max และปรับที่นั่น (จนกระทั่งรีบูตครั้งต่อไป) หรือตั้งค่า fs.file-max ใน sysctl.conf เพื่อให้ถาวร สิ่งนี้อาจมีประโยชน์ - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
ความคิดเห็นเกี่ยวกับ bash นั้นไม่ถูกต้อง ulimit กำหนดขีด จำกัด ของ user-id ต่อขีด จำกัด สำหรับกระบวนการที่เริ่มต้นผ่านเชลล์ซึ่งโดยพื้นฐานแล้วแทบทุกอย่างต้องขอบคุณต้นไม้กระบวนการถูกวางบน Unix เช่นระบบปฏิบัติการ มันไม่ได้ทุบตี
EightBitTony

ขออภัย - จะแก้ไข แต่แสดงความคิดเห็นเกี่ยวกับข้อ จำกัด ทั้งระบบยังคงมีอยู่
rnxrx

มันไม่น่าเป็นไปได้มากที่เขาจะตีระบบ จำกัด เป็นไปได้ แต่ไม่น่าเป็นไปได้มาก
David Schwartz

EightBitTony: ulimit ไม่ได้ตั้ง ulimit ตามข้อ จำกัด ของ user-id มันต่อกระบวนการเมื่อใช้ pam_limits ulimit ที่เป็น "ต่อผู้ใช้" คือ "ulimit -u" "จำนวนสูงสุดของกระบวนการสำหรับผู้ใช้คนเดียว"
ไม่มีชื่อผู้ใช้

0

ข้อผิดพลาดทั่วไปในการเปรียบเทียบผลลัพธ์ของการโทร lsof ดิบที่มีขีด จำกัด ที่ควรจะเป็น

สำหรับขีด จำกัด โกลบอล (/ proc / sys / fs / file-max) คุณควรดู / proc / sys / fs / file-nr -> ค่ากำปั้นระบุสิ่งที่ใช้และค่าสุดท้ายคือขีด จำกัด

ขีด จำกัด OpenFile สำหรับแต่ละกระบวนการ แต่สามารถกำหนดได้บนผู้ใช้ดูคำสั่ง "ulimit -Hn" สำหรับข้อ จำกัด ของผู้ใช้และดู /etc/security/limits.conf สำหรับคำจำกัดความ โดยทั่วไปจะใช้กับ "ผู้ใช้แอป" เช่น: "tomcat": ตั้งค่าขีด จำกัด เป็น 65000 กับผู้ใช้ tomcat ที่จะใช้กับกระบวนการจาวาที่ทำงาน

หากคุณต้องการตรวจสอบข้อ จำกัด ที่ใช้กับกระบวนการรับ PID แล้ว: cat / proc / $ {PID} / จำกัด หากคุณต้องการตรวจสอบจำนวนไฟล์ที่เปิดโดยกระบวนการให้รับ PID แล้ว: ls -1 / proc / {PID} / fd | wc -l (หมายเหตุสำหรับ ls คือ 'ลบหนึ่ง' เพื่อไม่ให้ต้องเผชิญหน้ากับ 'ลบ el')

หากคุณต้องการทราบรายละเอียดด้วยคำสั่ง lsof แต่สำหรับผู้จัดการไฟล์ที่นับถึงขีด จำกัด เท่านั้นให้ลองเหล่านี้: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a

หมายเหตุ: 'files' คือ files / pipe / tcp connections / เป็นต้น

โปรดทราบว่าบางครั้งคุณอาจจำเป็นต้องรูทหรือใช้ sudo เพื่อรับผลลัพธ์ที่ถูกต้องสำหรับคำสั่งโดยไม่มีสิทธิ์บางครั้งคุณไม่มีข้อผิดพลาดผลลัพธ์ที่น้อยลง

และสุดท้ายถ้าคุณต้องการทราบว่า 'ไฟล์' ในระบบไฟล์ของคุณถูกเข้าถึงโดยกระบวนการให้ดูที่: lsof -p {PID} | grep / | awk '{พิมพ์ $ 9}' | จัดเรียง | UNIQ

มีความสุข !

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.