Dlaczego (lub jak) liczba otwartych deskryptorów plików używanych przez root przekracza ulimit -n?


13

Na naszym serwerze ostatnio zabrakło deskryptorów plików, w związku z czym mam kilka pytań. ulimit -nma dać mi maksymalną liczbę otwartych deskryptorów plików. Ta liczba to 1024. Sprawdziłem liczbę otwartych deskryptorów plików, uruchamiając lsof -u root |wc -li dostałem 2500 fds. To o wiele więcej niż 1024, więc przypuszczam, że oznaczałoby to, że liczba 1024 przypada na proces, a nie na użytkownika, jak myślałem. Cóż, pobiegłem lsof -p$PidOfGlassfish|wc -li dostałem 1300. Nie dostaję tej części. Jeśli ulimit -nnie jest maksymalna liczba procesów na użytkownika lub na proces, to po co to jest dobre? Czy nie dotyczy to użytkownika root? A jeśli tak, to jak mogę uzyskać komunikaty o błędach dotyczące braku deskryptora pliku?

EDYCJA: Jedynym sposobem, w jaki mogę to zrozumieć, ulimit -njest zastosowanie liczby otwartych plików (zgodnie z instrukcją bash) zamiast liczby uchwytów plików (różne procesy mogą otworzyć ten sam plik). W takim przypadku wystarczy podać liczbę otwartych plików (grepowanie na '/', wykluczając w ten sposób pliki mapowane w pamięci) nie jest wystarczające :

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

Aby zobaczyć liczbę otwartych plików, musiałbym przefiltrować kolumnę z nazwami, aby wydrukować tylko unikalne wpisy. Dlatego poniższe informacje są prawdopodobnie bardziej poprawne:

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

Powyższe polecenie oczekuje danych wyjściowych w następującym formacie od 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

To przynajmniej daje mi liczbę mniejszą niż 1024 (liczba zgłaszana przez ulimit -n), więc wydaje się to krokiem we właściwym kierunku. „Niestety” nie mam problemów z brakiem deskryptorów plików, więc trudno mi będzie to sprawdzić.


2
lsof zgłasza mapowania pamięci, a także otwarte pliki, więc Twój potok „wc” zwraca zawyżoną liczbę deskryptorów plików używanych przez ten proces.
— Richard Kettlewell,

Aha! to dobra informacja. Ale nie jestem pewien, czy rozumiem. Przez „odwzorowania pamięci” masz na myśli plik odwzorowany w pamięci? To wymagałoby uchwytu pliku, o ile mi wiadomo, w jaki sposób system operacyjny mógłby zaktualizować plik?
— oligofren

I następna druga: jaki byłby dobry sposób na znalezienie wszystkich uchwytów otwartych plików - tych, na które faktycznie wpływają ograniczenia nałożone przez „ulimit -n”?
— oligofren

1
Odwzorowania pamięci nie wymagają otwartego pliku. Jeśli chcesz wyświetlić listę tylko otwartych plików, filtrowanie danych wyjściowych lsof jest prawdopodobnie najłatwiejszym podejściem.
— Richard Kettlewell,

Dzięki, zredagowałem moją odpowiedź. Wydaje się, że użycie „-loot -u root | grep / | sort -k9 -u” daje rozsądną odpowiedź. Jest to co najmniej liczba mniejsza niż ulimit -n.
— oligofren

Odpowiedzi:


9

Testowałem to w Linuksie w wersji 2.6.18-164.el5 - Red Hat 4.1.2-46. Widziałem, że ulimit jest stosowany na proces.

Parametr jest ustawiany na poziomie użytkownika, ale stosowany dla każdego procesu.

Np .: 1024 był limitem. Uruchomiono wiele procesów, a pliki otwarte przy każdym z nich policzono za pomocą

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

Nie wystąpiły błędy, gdy suma plików otwartych przez wiele procesów przekroczyła 1024. Zweryfikowałem również unikalną liczbę plików łącząc wyniki dla różnych procesów i licząc unikalne pliki. Błędy zaczęły pojawiać się dopiero wtedy, gdy liczba każdego procesu przekroczyła 1024. (java.net.SocketException: Zbyt wiele otwartych plików w dziennikach procesów)


Dzięki za przetestowanie tego. Czy masz pojęcie, dlaczego lsof -p$PidOfGlassfish|wc -ldał mi 1300? Zgaduję, że oba podejścia do liczenia różnią się w jakiś sposób. Jeśli nie, to może limit nie dotyczy użytkownika root?
— oligofren

Ciekawe, po co używać ls -lzamiast ls? Ten ostatni ma dodatkową linię (np. total 5), Gdy jest 5 plików. W takim przypadku użycie ls -l w powyższym przykładzie spowoduje zgłoszenie 6, a nie 5. Używam ls /proc/<pid>/fd | wc -l.
— starfry

@starfry To po prostu niechlujstwo z mojej strony. Zazwyczaj robię to krok po kroku i ls -ldaje mi jeden wpis w wierszu, który następnie łączę w coś innego. Oczywiście dzieje się tak również podczas normalnego orurowania ls(ale nie inaczej).
— oligofren

3

Ulimit dotyczy uchwytów plików. Ma zastosowanie do plików, katalogów, gniazd, epolls potoków, eventfds, timerfds itp.

W dowolnym momencie uruchamiania procesów limity mogły zostać zmienione. Odwiedź /proc/<pid>/limitsi sprawdź, czy wartości zostały zmienione.


3

@oligofren

Ja też przeprowadzić kilka testów w celu ustalenia, w jaki sposób "ulimits -Sn"za "open files"było egzekwowane.

  • Podobnie jak plakat Wybrany wymieniony w linku , ulimit "open files"jest rzeczywiście stosowany dla każdego procesu. Aby zobaczyć, jakie są obecne limity procesu:

    cat /proc/__process_id__/limits

  • Aby ustalić liczbę plików otwartych przez proces, musisz użyć następującego polecenia:

    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

Wyjaśnienie powyższego i moja metoda / wyniki testowania

Te "-P -M -l -n"argumenty lsof są po prostu tam, aby lsof działać tak szybko, jak to możliwe. Zapraszam do ich wyjęcia.

-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

W "-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"przesyła zlecenie argumentów lsofwykluczyć deskryptorów plików typu: CWD / err / LTX / mem / mmap / PD / BRT / txt.

Ze strony 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;

Uznałem, że "Lnn,jld,m86,tr,v86"nie dotyczy Linuksa i dlatego nie zadałem sobie trudu, aby dodać je do listy wykluczeń. Nie jestem pewien "Mxx".

Jeśli twoje uzależnia zastosowanie do korzystania z pamięci mapowane plików / devices to może chcesz usunąć "^mem"i "^mmap"z listy wykluczeń.

EDYCJA --- rozpocząć wycinanie ---

Edycja: Znalazłem następujący link, który wskazuje, że:

odwzorowane w pamięci pliki .so technicznie nie są tym samym co uchwyt pliku, nad którym aplikacja ma kontrolę. / proc // fd to punkt pomiarowy dla otwartych deskryptorów plików

Jeśli więc proces używa plików zmapowanych w pamięci, konieczne będzie odfiltrowanie plików * .so.

Ponadto JVM firmy Sun zapisze w pamięci pliki jar

Plik JAR odwzorowany w pamięci, w tym przypadku plik zawierający „klasy JDK”. Kiedy mapujesz pamięć JAR, możesz bardzo wydajnie uzyskiwać dostęp do plików w nim zawartych (w porównaniu z odczytywaniem go od początku za każdym razem). Sun JVM zmapuje w pamięci wszystkie pliki JAR w ścieżce klasy; jeśli twój kod aplikacji musi uzyskać dostęp do pliku JAR, możesz go również zmapować w pamięci.

Rzeczy takie jak tomcat / glassfish będą również wyświetlać pliki jar zamapowane w pamięci. Nie testowałem, czy liczą się one do "ulimit -Sn"limitu.

EDYCJA --- koniec snipa ---

Empirycznie, znalazłem, że nie"cwd,rtd,txt" są liczone w odniesieniu do limitu pliku na proces (ulimit -Sn).

Nie jestem pewien, czy "err,ltx,pd"są wliczane do limitu plików, ponieważ nie wiem, jak utworzyć uchwyty plików tych typów deskryptorów.

Do "-p __process_id__"ogranicza argumentów lsofaby tylko zwrócić informacji za __process_id__określony. Usuń to, jeśli chcesz uzyskać liczbę wszystkich procesów.

"-a"Argumentem jest używany do I wybory (czyli „p” i „-d” argumenty).

"awk '{if (NR>1) print}'"Zestawienie służy do pominąć nagłówek, który lsofdrukuje w swoim wyjściu.

Testowałem przy użyciu następującego skryptu 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---

Musiałem wykonać skrypt w debugerze Perla, aby upewnić się, że skrypt się nie kończy i zwolnić deskryptory plików.

Wykonać: perl -d test.pl

W debugerze Perla możesz uruchomić program, wprowadzając ci naciskając enter, a jeśli miałeś ulimit -Snwartość 1024 , przekonasz się, że program zatrzymuje się po utworzeniu Test1017.logpliku /tmp.

Jeśli teraz zidentyfikujesz pid procesu perla i użyjesz powyższego lsofpolecenia, zobaczysz, że wyprowadza on również 1024 .

Usuń "wc -l"i zamień na, "less"aby wyświetlić listę plików zaliczanych do limitu 1024 . Usuń również "-d ^....."argument, aby zobaczyć, że deskryptory cwd,txti nie liczą się do limitu.rtd

Jeśli teraz uruchomisz "ls -l /proc/__process_id__/fd/ | wc -l", zobaczysz wartość 1025 . Jest tak, ponieważ lsdodano "total 0"nagłówek do jego wyniku, który został policzony.

Uwaga:

Aby sprawdzić, czy w systemie operacyjnym brakuje deskryptorów plików, lepiej porównać wartość:

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

z

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txt dokumentuje, co file-nri co file-maxoznacza.


0

Wygląda na to, że twoje rozumowanie brzmi: „Muszę obniżyć ten limit, aby nie zabrakło cennych deskryptorów”. Prawda jest dokładnie odwrotna - jeśli na twoim serwerze zabrakło deskryptorów plików, musisz podnieść ten limit z 1024 do czegoś większego. W celu realistycznego glassfishwdrożenia 32 768 jest rozsądne.

Osobiście zawsze podwyższam limit do około 8 192 systemu - 1024 to po prostu śmieszne. Ale będziesz chciał podnieść glassfishwyżej. Sprawdzić /etc/security/limits.conf. Możesz dodać specjalny wpis dla użytkownika, który glassfishdziała jako.


Nie jestem pewien, jak mógłbyś mnie zinterpretować w ten sposób :-) Zastanawiałem się, dlaczego tak się nie stało. Ustawię go wyżej, ale chcę również zrozumieć, jak to działa. Jeśli limit wynosi 1024, to jak Glassfish może mieć 1300 uchwytów?
— oligofren

'lsof -u root | grep / | sort -k9 -u' drukuje unikalne wpisy deskryptora pliku. Myślę, że liczba wierszy z tego jest rzeczywistą liczbą, której dotyczy ulimit -n.
— oligofren

0

Chcesz spojrzeć na ogólnosystemowe limity ustawione w / proc / sys / fs / file-max i dostosować je tam (do następnego ponownego uruchomienia) lub ustawić fs.file-max w sysctl.conf, aby uczynić go trwałym. Może to być pomocne - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
Ten komentarz na temat bash nie jest dokładny. ulimit narzuca zestaw limitów dla identyfikatora użytkownika dla procesów inicjowanych przez powłokę, co w zasadzie jest praktycznie wszystkim dzięki temu, jak drzewo procesów jest spawnowane w systemach operacyjnych typu Unix. To nie jest bzdura.
— EightBitTony

Przepraszam - edytuje, ale komentarz na temat limitów systemowych nadal obowiązuje.
— rnxrx

Jest bardzo mało prawdopodobne, że osiągnie granice całego systemu. Możliwe, ale bardzo mało prawdopodobne.
— David Schwartz

EightBitTony: ulimit nie ustawia ulimit na zestaw limitów dla identyfikatora użytkownika. Jest to proces, gdy stosowane są pam_limits. Ulimit, który jest „na użytkownika”, to „ulimit -u” „Maksymalna liczba procesów dostępna dla jednego użytkownika”
— brak

0

Często popełniany błąd przy porównywaniu wyniku surowego wywołania lsof z domniemanym limitem.

W przypadku globalnego limitu (/ proc / sys / fs / file-max) powinieneś spojrzeć na / proc / sys / fs / file-nr -> wartość pięści wskazuje, co jest używane, a ostatnia wartość jest granicą

Limit OpenFile dotyczy każdego procesu, ale można go zdefiniować dla użytkownika, patrz komenda „ulimit -Hn” dla limitów użytkownika i definicje w pliku /etc/security/limits.conf. Zazwyczaj stosowane z „użytkownikiem aplikacji”, np .: „tomcat”: ustaw limit 65000 na użytkownika tomcat, który będzie obowiązywał w uruchomionym procesie Java.

Jeśli chcesz sprawdzić limit zastosowany w procesie, uzyskaj jego PID, a następnie: cat / proc / $ {PID} / limit Jeśli chcesz sprawdzić, ile plików jest otwieranych przez proces, uzyskaj jego PID, a następnie: ls -1 / proc / {PID} / fd | wc -l (uwaga dla ls to „minus jeden”, nie mylić z „minus el”)

Jeśli chcesz poznać szczegóły z lsof, ale tylko dla tych osób, które liczą się dla limitu, wypróbuj te: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a

Uwaga: „pliki” to pliki / połączenia / połączenia TCP / itp.

Zauważ, że czasami będziesz musiał być rootem lub użyć sudo, aby uzyskać poprawny wynik dla poleceń, bez przywileju czasami nie masz błędu, tylko mniej wyników.

i na koniec, jeśli chcesz wiedzieć, do jakich „plików” w systemie plików ma dostęp proces, spójrz na: lsof -p {PID} | grep / | awk '{print 9 $}' | sortuj | uniq

baw się dobrze !

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.