Tại sao (hoặc làm thế nào) số lượng mô tả tệp mở được sử dụng bởi root vượt quá ulimit -n?


13

Máy chủ của chúng tôi gần đây đã hết các mô tả tệp và liên quan đến việc tôi có một số câu hỏi. ulimit -nđược cho là cung cấp cho tôi số lượng mô tả tệp mở tối đa. Con số đó là 1024. Tôi đã kiểm tra số lượng mô tả tệp đang mở bằng cách chạy lsof -u root |wc -lvà nhận 2500 fds. Đó là nhiều hơn 1024, vì vậy tôi đoán điều đó có nghĩa là số 1024 là trên mỗi quy trình, không phải cho mỗi người dùng, như tôi nghĩ. Chà, tôi đã chạy lsof -p$PidOfGlassfish|wc -lvà nhận được 1300. Đây là phần tôi không nhận được. Nếu ulimit -nkhông phải là số lượng quy trình tối đa trên mỗi người dùng hoặc mỗi quy trình, thì nó tốt cho cái gì? Nó không áp dụng cho người dùng root? Và nếu vậy, làm thế nào tôi có thể nhận được thông báo lỗi về việc hết bộ mô tả tệp?

BIÊN TẬP: Cách duy nhất tôi có thể hiểu ulimit -nlà nếu nó áp dụng số lượng tệp đang mở (như đã nêu trong hướng dẫn bash) thay vì số lượng thẻ xử lý (các quy trình khác nhau có thể mở cùng một tệp). Nếu đây là trường hợp, thì chỉ cần liệt kê số lượng tệp đang mở (grepping trên '/', do đó loại trừ các tệp ánh xạ bộ nhớ) là không đủ:

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

Để thực sự thấy số lượng tệp đang mở, tôi sẽ cần lọc trên cột tên chỉ in các mục duy nhất. Do đó, có lẽ đúng hơn:

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

Lệnh trên mong đợi đầu ra ở định dạng sau từ 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

Điều này ít nhất mang lại cho tôi số ít hơn 1024 (số được báo cáo bởi ulimit -n ), vì vậy đây có vẻ như là một bước đi đúng hướng. "Thật không may" Tôi không gặp phải bất kỳ vấn đề nào với việc hết các phần mô tả tệp, vì vậy tôi sẽ gặp khó khăn khi xác nhận điều này.


2
lsof báo cáo ánh xạ bộ nhớ cũng như các tệp đang mở, do đó, đường ống 'wc' của bạn mang lại ước tính quá mức về số lượng mô tả tệp được sử dụng bởi quy trình đó.
Richard Kettlewell

aha bây giờ đó là thông tin tốt. Nhưng tôi không chắc là tôi hiểu. Theo "ánh xạ bộ nhớ", bạn có nghĩa là một tập tin ánh xạ bộ nhớ? Điều đó sẽ yêu cầu xử lý tệp theo sự hiểu biết của tôi hoặc hệ điều hành khác có thể cập nhật tệp như thế nào?
oligofren

Và tiếp theo hai: Điều gì sẽ là một cách tốt để tìm tất cả các thẻ điều khiển mở - những cái thực sự bị ảnh hưởng bởi các giới hạn được áp đặt bởi "ulimit -n"?
oligofren

1
Ánh xạ bộ nhớ không yêu cầu mở tệp. Nếu bạn chỉ muốn liệt kê các tệp đang mở, lọc đầu ra của lsof có lẽ là cách tiếp cận dễ dàng nhất.
Richard Kettlewell

Cảm ơn, chỉnh sửa câu trả lời của tôi. Sử dụng ọlsof -u root | grep / | sort -k9 -u dường như đưa ra số tiền cho một câu trả lời hợp lý. Đây là ít nhất một số ít hơn ulimit -n.
oligofren

Câu trả lời:


9

Tôi đã thử nghiệm điều này trong phiên bản Linux 2.6.18-164.el5 - Red Hat 4.1.2-46. Tôi có thể thấy rằng ulimit được áp dụng cho mỗi quá trình.

Tham số được đặt ở cấp độ người dùng, nhưng được áp dụng cho từng quy trình.

Ví dụ: 1024 là giới hạn. Nhiều quy trình đã được bắt đầu và các tệp được mở bởi mỗi một được tính bằng cách sử dụng

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

Không có lỗi khi tổng số tệp được mở bởi nhiều quy trình vượt qua 1024. Tôi cũng đã xác minh số lượng tệp duy nhất kết hợp các kết quả cho các quy trình khác nhau và đếm các tệp duy nhất. Các lỗi bắt đầu chỉ xuất hiện khi số lượng cho mỗi quy trình vượt qua 1024. (java.net.SocketException: Quá nhiều tệp đang mở trong nhật ký quy trình)


Cảm ơn đã thử nghiệm này. Bạn có biết tại sao lsof -p$PidOfGlassfish|wc -lđã cho tôi 1300? Tôi đoán hai cách tiếp cận để đếm khác nhau bằng cách nào đó. Nếu không, thì có lẽ giới hạn không áp dụng cho người dùng root?
oligofren

Chỉ tò mò, tại sao sử dụng ls -lthay vì ls? Cái sau có thêm một dòng (ví dụ total 5) khi có 5 tệp. Trong trường hợp như vậy, sử dụng ls -l trong ví dụ trên sẽ báo cáo 6 không 5. Tôi sử dụng ls /proc/<pid>/fd | wc -l.
starfry

@starfry Đó chỉ là sự cẩu thả từ phía tôi. Tôi thường làm điều này từng bước và ls -lđưa cho tôi một mục nhập trên mỗi dòng, sau đó tôi chuyển sang một mục khác. Cours, điều này cũng xảy ra khi đường ống bình thường ls(nhưng không có gì khác).
oligofren

3

Các ulimit là dành cho filehandles. Nó áp dụng cho các tập tin, thư mục, ổ cắm, epolls ống, eventfds, timerfds, v.v.

Tại bất kỳ thời điểm nào trong quá trình khởi động, các giới hạn có thể đã được thay đổi. Truy cập /proc/<pid>/limitsvà xem nếu các giá trị đã được thay đổi.


3

@oligofren

Tôi cũng đã thực hiện một số thử nghiệm để xác định cách "ulimits -Sn"thức "open files"thi hành.

  • Giống như poster Chosen được đề cập trong liên kết , ulimit cho "open files"thực sự được áp dụng cho mỗi quy trình. Để xem giới hạn hiện tại của quy trình là gì:

    cat /proc/__process_id__/limits

  • Để xác định có bao nhiêu tệp một quy trình đã mở, bạn cần sử dụng lệnh sau:

    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

Giải thích về các kết quả / phương pháp thử nghiệm ở trên và của tôi

Các "-P -M -l -n"đối số cho lsof chỉ đơn giản là có để làm cho lsof hoạt động nhanh nhất có thể. Hãy đưa chúng ra ngoài.

-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

Đối "-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"số hướng dẫn lsofđể loại trừ các mô tả tệp loại: cwd / err / ltx / mem / mmap / pd / rtd / txt.

Từ trang lsof man:

   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;

Tôi coi "Lnn,jld,m86,tr,v86"là không áp dụng được với Linux và do đó không bận tâm thêm chúng vào danh sách loại trừ. Tôi không chắc chắn về "Mxx".

Nếu ứng dụng của bạn sử dụng các tệp / thiết bị được ánh xạ bộ nhớ thì bạn có thể muốn xóa "^mem""^mmap"khỏi danh sách loại trừ.

EDIT --- bắt đầu snip ---

Chỉnh sửa: Tôi tìm thấy liên kết sau chỉ ra rằng:

bộ nhớ được ánh xạ .so-files về mặt kỹ thuật không giống như một tệp xử lý ứng dụng có quyền kiểm soát. / Proc // fd là điểm đo cho các mô tả tệp mở

Vì vậy, nếu quy trình của bạn sử dụng các tệp ánh xạ bộ nhớ, bạn sẽ cần lọc ra các tệp * .so.

Ngoài ra, JVM của Sun sẽ ghi lại các tệp jar

Một JARfile được ánh xạ bộ nhớ, trong trường hợp này là tệp chứa "các lớp JDK." Khi bạn ánh xạ bộ nhớ JAR, bạn có thể truy cập các tệp trong đó rất hiệu quả (so với việc đọc nó từ đầu mỗi lần). Sun JVM sẽ ánh xạ bộ nhớ tất cả các JAR trên đường dẫn lớp; nếu mã ứng dụng của bạn cần truy cập JAR, bạn cũng có thể ánh xạ bộ nhớ.

Vì vậy, những thứ như tomcat / thủy tinh cũng sẽ hiển thị các tệp jar được ánh xạ bộ nhớ. Tôi đã không kiểm tra xem những thứ này có được tính đến "ulimit -Sn"giới hạn hay không.

EDIT --- cuối snip ---

Theo kinh nghiệm, tôi đã phát hiện ra rằng "cwd,rtd,txt"đang không được tính liên quan đến các quá trình mỗi giới hạn tập tin (ulimit -Sn).

Tôi không chắc liệu có "err,ltx,pd"được tính vào giới hạn tệp hay không vì tôi không biết cách tạo xử lý tệp của các loại mô tả này.

Đối "-p __process_id__"số hạn chế lsofchỉ trả về thông tin cho __process_id__chỉ định. Xóa cái này nếu bạn muốn lấy số đếm cho tất cả các quy trình.

Đối "-a"số được sử dụng để các lựa chọn (tức là các đối số "-p" và "-d").

Câu "awk '{if (NR>1) print}'"lệnh được sử dụng để bỏ qua tiêu đề lsofin trong đầu ra của nó.

Tôi đã thử nghiệm bằng cách sử dụng tập lệnh perl sau:

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---

Tôi đã phải thực thi tập lệnh trong trình gỡ lỗi perl để đảm bảo tập lệnh không chấm dứt và giải phóng bộ mô tả tệp.

Để thực hiện: perl -d test.pl

Trong trình gỡ lỗi của perl, bạn có thể chạy chương trình bằng cách nhập cvà nhấn enter và nếu bạn ulimit -Sncó giá trị 1024 , bạn sẽ thấy chương trình dừng lại sau khi tạo Test1017.logtệp /tmp.

Nếu bây giờ bạn xác định pid của quá trình perl và sử dụng lsoflệnh trên, bạn sẽ thấy rằng nó cũng xuất ra 1024 .

Xóa "wc -l"và thay thế bằng a "less"để xem danh sách các tệp được tính theo giới hạn 1024 . Xóa "-d ^....."đối số cũng để thấy rằng các mô tả cwd,txtkhôngrtd được tính vào giới hạn.

Nếu bây giờ bạn chạy "ls -l /proc/__process_id__/fd/ | wc -l", bạn sẽ thấy giá trị 1025 được trả về. Điều này là do lsđã thêm một "total 0"tiêu đề vào đầu ra của nó đã được tính.

Ghi chú:

Để kiểm tra xem HĐH có hết bộ mô tả tệp hay không, tốt hơn là so sánh giá trị của:

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

với

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txt tài liệu gì file-nrfile-maxcó ý nghĩa.


0

Có vẻ như lý luận của bạn là một cái gì đó như, "Tôi phải hạ thấp giới hạn đó để tôi không hết những mô tả quý giá". Sự thật hoàn toàn ngược lại - nếu máy chủ của bạn hết bộ mô tả tệp, bạn cần tăng giới hạn đó từ 1.024 lên mức lớn hơn. Cho một thực tếglassfish hiện , 32.768 là hợp lý.

Cá nhân, tôi luôn tăng giới hạn lên khoảng 8.192 toàn hệ thống - 1.024 là vô lý. Nhưng bạn sẽ muốn nâng glassfishcao hơn. Kiểm tra /etc/security/limits.conf. Bạn có thể thêm một mục đặc biệt cho người dùng glassfishchạy như.


Tôi không chắc làm thế nào bạn có thể giải thích tôi có nghĩa là :-) Điều tôi đã tự hỏi là tại sao nó dường như không áp dụng. Tôi sẽ đặt nó cao hơn, nhưng tôi muốn hiểu làm thế nào nó hoạt động tốt. Nếu giới hạn là 1024, thì Glassfish có thể có 1300 tay cầm như thế nào?
oligofren

'lsof -u root | grep / | sort -k9 -u' in các mục mô tả tệp duy nhất. Tôi đoán số lượng dòng từ đây là số ulimit thực tế áp dụng cho.
oligofren

0

Bạn muốn xem các giới hạn trên toàn hệ thống được đặt trong / Proc / sys / fs / file-max và điều chỉnh nó ở đó (cho đến khi khởi động lại tiếp theo) hoặc đặt fs.file-max trong sysctl.conf để biến nó thành vĩnh viễn. Điều này có thể hữu ích - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
Nhận xét về bash không chính xác. ulimit áp đặt một bộ giới hạn cho mỗi id người dùng, cho các quy trình được khởi tạo thông qua shell, về cơ bản là hầu hết mọi thứ nhờ vào cách cây quy trình được sinh ra trên Unix như các hệ điều hành. Đó không phải là bash.
EightBitTony

Xin lỗi - sẽ chỉnh sửa, nhưng bình luận về giới hạn toàn hệ thống vẫn đứng, mặc dù.
rnxrx

Rất khó có khả năng anh ta đạt đến giới hạn toàn hệ thống. Có thể, nhưng rất khó xảy ra.
David Schwartz

EightBitTony: ulimit không đặt ulimit cho mỗi bộ giới hạn id người dùng. Mỗi quá trình của nó khi pam_limits được áp dụng. Cái ulimit đó là "trên mỗi người dùng" là "ulimit -u" "Số lượng quy trình tối đa có sẵn cho một người dùng"
Không có tên người dùng

0

Lỗi phổ biến để so sánh kết quả của cuộc gọi lsof thô với giới hạn giả định.

Đối với giới hạn toàn cầu (/ Proc / sys / fs / file-max), bạn nên xem / Proc / sys / fs / file-nr -> giá trị nắm tay cho biết những gì được sử dụng và giá trị cuối cùng là giới hạn

Giới hạn OpenFile dành cho mỗi quy trình nhưng có thể được xác định trên người dùng, xem lệnh "ulimit -Hn" để biết giới hạn người dùng và xem /etc/security/limits.conf để biết định nghĩa. Thường được áp dụng với "người dùng ứng dụng", ví dụ: "tomcat": đặt giới hạn thành 65000 cho người dùng tomcat sẽ áp dụng cho quy trình java mà nó chạy.

Nếu bạn muốn kiểm tra giới hạn được áp dụng trên một quy trình, hãy lấy PID của nó và sau đó: cat / Proc / $ {PID} / giới hạn Nếu bạn muốn kiểm tra có bao nhiêu tệp được mở bởi một quy trình, hãy lấy PID của nó và sau đó: ls -1 / Proc / {PID} / fd | wc -l (lưu ý cho ls đó là 'trừ đi một', không được kết luận với 'minus el')

Nếu bạn muốn biết chi tiết với lsof nhưng chỉ đối với những người xử lý tệp tính giới hạn, hãy thử với thoses: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a

Lưu ý: 'tệp' là các tệp / kết nối ống / tcp / v.v.

Lưu ý rằng đôi khi bạn có thể cần phải root hoặc sử dụng sudo để có kết quả chính xác cho các lệnh, không có đặc quyền đôi khi bạn không gặp lỗi, chỉ cần ít kết quả hơn.

và cuối cùng nếu bạn muốn biết 'tập tin' nào trên hệ thống tập tin của bạn được truy cập bởi một quy trình, hãy xem: lsof -p {PID} | grep / | awk '{in $ 9}' | sắp xếp | uniq

chúc vui vẻ !

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.