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

oligofren
źródło
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)

Wybrany
źródło
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.

Matthew Ife
źródło
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"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.

Jinesh Choksi
źródło
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.

David Schwartz
źródło
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

rnxrx
źródło
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 !

Ronan Kerdudou
źródło