Warum (oder wie) überschreitet die Anzahl der von root verwendeten offenen Dateideskriptoren ulimit -n?

13

Unserem Server sind kürzlich die Dateideskriptoren ausgegangen, und diesbezüglich habe ich einige Fragen. ulimit -nsoll mir die maximale Anzahl offener Dateideskriptoren geben. Diese Nummer ist 1024. Ich habe die Anzahl der geöffneten Dateideskriptoren überprüft, indem ich ausgeführt habe lsof -u root |wc -lund 2500 fds erhalten habe. Das ist viel mehr als 1024, also würde das bedeuten, dass die Zahl 1024 pro Prozess und nicht pro Benutzer ist, wie ich dachte. Nun, ich bin gelaufen lsof -p$PidOfGlassfish|wc -lund habe 1300. Das ist der Teil, den ich nicht bekomme. Wenn ulimit -nes nicht die maximale Anzahl von Prozessen pro Benutzer oder pro Prozess gibt, wofür ist es dann gut? Gilt das nicht für den Root-Benutzer? Und wenn ja, wie könnte ich dann die Fehlermeldungen erhalten, dass der Dateideskriptor ausgeht?

BEARBEITEN: Die einzige Möglichkeit, aus der ich einen Sinn ziehen kann, ulimit -nbesteht darin, die Anzahl der geöffneten Dateien (wie im Bash-Handbuch angegeben) anstelle der Anzahl der Dateizugriffsnummern anzuwenden (verschiedene Prozesse können dieselbe Datei öffnen). Wenn dies der Fall ist, dann Listing einfach die Anzahl der geöffneten Dateien (greppen auf ‚/‘, also ohne Speicherdateien abgebildet) ist nicht sufficent:

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

Um die Anzahl der geöffneten Dateien tatsächlich zu sehen, müsste ich nach der Namensspalte filtern, um nur die eindeutigen Einträge zu drucken. Daher ist das Folgende wahrscheinlich korrekter:

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

Der obige Befehl erwartet die Ausgabe in folgendem Format von 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

Dies gibt mir zumindest eine Zahl von weniger als 1024 (die von gemeldete Zahl ulimit -n), so dass dies ein Schritt in die richtige Richtung zu sein scheint. "Leider" habe ich keine Probleme damit, dass mir die Dateideskriptoren ausgehen. Daher werde ich es schwer haben, dies zu überprüfen.

Oligofren
quelle
2
lsof meldet sowohl Speicherzuordnungen als auch offene Dateien, sodass Ihre 'wc'-Pipeline eine Überschätzung der Anzahl der von diesem Prozess verwendeten Dateideskriptoren liefert.
Richard Kettlewell
Aha! nun das ist eine gute info. Aber ich bin mir nicht ganz sicher, ob ich das verstehe. Mit "Speicherzuordnungen" meinen Sie eine Speicherzuordnungsdatei? Dies würde nach meinem Verständnis ein Dateihandle erfordern, oder wie könnte das Betriebssystem die Datei sonst aktualisieren?
Oligofren
Und die zweite Folge: Was wäre ein guter Weg, um alle offenen Datei-Handles zu finden - diejenigen, die tatsächlich von den durch "ulimit -n" auferlegten Grenzen betroffen sind?
Oligofren
1
Speicherzuordnungen erfordern keine geöffnete Datei. Wenn Sie nur offene Dateien auflisten möchten, ist das Filtern der Ausgabe von lsof wahrscheinlich die einfachste Methode.
Richard Kettlewell
Danke, habe meine Antwort bearbeitet. Die Verwendung von ´lsof -u root | grep / | sort -k9 -u´ scheint eine vernünftige Antwort zu liefern. Dies ist mindestens eine Zahl kleiner als ulimit -n.
Oligofren

Antworten:

9

Ich habe dies in Linux Version 2.6.18-164.el5 - Red Hat 4.1.2-46 getestet. Ich konnte sehen, dass das Ulimit pro Prozess angewendet wird.

Der Parameter wird auf Benutzerebene festgelegt, jedoch für jeden Prozess angewendet.

ZB: 1024 war das Limit. Es wurden mehrere Prozesse gestartet und die jeweils geöffneten Dateien mit gezählt

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

Es gab keine Fehler, als die Summe der von mehreren Prozessen geöffneten Dateien 1024 überschritt. Ich habe auch die Anzahl der eindeutigen Dateien überprüft, wobei die Ergebnisse für verschiedene Prozesse kombiniert und eindeutige Dateien gezählt wurden. Die Fehler traten nur auf, wenn die Anzahl der Prozesse 1024 überschritt. (Java.net.SocketException: Zu viele offene Dateien in Prozessprotokollen)

Gewählt
quelle
Vielen Dank für das Testen. Hast du eine Idee, warum lsof -p$PidOfGlassfish|wc -lich 1300 bekommen habe? Ich vermute, die beiden Ansätze zum Zählen unterscheiden sich irgendwie. Wenn nicht, gilt das Limit möglicherweise nicht für den Root-Benutzer?
Oligofren
Einfach nur neugierig, warum ls -lstatt verwenden ls? Letzteres hat eine zusätzliche Zeile (zB total 5), wenn es 5 Dateien gibt. In einem solchen Fall würde die Verwendung ls -l in dem obigen Beispiel 6 und nicht 5 melden. Ich verwende ls /proc/<pid>/fd | wc -l.
Starfry
@starfry Das ist nur Schlamperei meinerseits. Normalerweise mache ich das schrittweise und ls -lgebe mir einen Eintrag pro Zeile, den ich dann in etwas anderes pipe. Natürlich passiert dies auch bei normaler Verrohrung ls(aber nicht anders).
Oligofren
3

Das ulimit ist für Dateihandles. Dies gilt für Dateien, Verzeichnisse, Sockets, Pipes, Epolls, Eventfds, Timerfds usw. usw.

Zu jedem Zeitpunkt während des Prozessstarts können sich die Grenzwerte geändert haben. Besuchen Sie /proc/<pid>/limitsund prüfen Sie, ob die Werte geändert wurden.

Matthew Ife
quelle
3

@oligofren

Ich habe auch einige Tests durchgeführt, um festzustellen, wie "ulimits -Sn"für "open files"erzwungen wurde.

  • Wie das im Link erwähnte Poster Chosen wird das ulimit for in der Tat pro Prozess angewendet. So ermitteln Sie die aktuellen Grenzen des Prozesses:"open files"

    cat /proc/__process_id__/limits

  • Um festzustellen, wie viele Dateien ein Prozess geöffnet hat, müssen Sie den folgenden Befehl verwenden:

    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

Erklärung der oben genannten und meiner Testmethode / Ergebnisse

Die "-P -M -l -n"Argumente zu lsof sind einfach dazu da, lsof so schnell wie möglich arbeiten zu lassen. Fühlen Sie sich frei, sie herauszunehmen.

-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

Das "-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"Argument weist lsofan, Dateideskriptoren des Typs auszuschließen: cwd / err / ltx / mem / mmap / pd / rtd / txt.

Aus der Manpage von 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;

Ich habe es "Lnn,jld,m86,tr,v86"als nicht zutreffend für Linux erachtet und habe mich daher nicht darum gekümmert, sie der Ausschlussliste hinzuzufügen. Da bin ich mir nicht sicher "Mxx".

Wenn Ihre Anwendung mit Speicher verknüpfte Dateien / Geräte verwendet, möchten Sie möglicherweise "^mem"und "^mmap"aus der Ausschlussliste entfernen .

BEARBEITEN --- Snip starten ---

Bearbeiten: Ich habe den folgenden Link gefunden, der darauf hinweist, dass:

Speicherabgebildete .so-Dateien sind technisch gesehen nicht dasselbe wie ein Dateihandle, über das die Anwendung die Kontrolle hat. / proc // fd ist der Messpunkt für offene Dateideskriptoren

Wenn in Ihrem Prozess Speicherzuordnungsdateien verwendet werden, müssen Sie * .so-Dateien herausfiltern.

Die JVM von Sun speichert JAR-Dateien

Eine speicherabgebildete JAR-Datei, in diesem Fall die Datei, die die "JDK-Klassen" enthält. Wenn Sie eine JAR-Datei im Speicher zuordnen, können Sie sehr effizient auf die darin enthaltenen Dateien zugreifen (anstatt sie jedes Mal von vorn zu lesen). Die Sun-JVM ordnet alle JARs auf dem Klassenpfad im Speicher zu. Wenn Ihr Anwendungscode auf eine JAR zugreifen muss, können Sie auch eine Speicherzuordnung vornehmen.

Dinge wie Tomcat / Glassfish zeigen daher auch JAR-Dateien mit Speicherzuordnungen an. Ich habe nicht getestet, ob diese zum "ulimit -Sn"Limit zählen.

BEARBEITEN --- Snip beenden ---

Empirisch habe ich festgestellt, dass "cwd,rtd,txt"im Hinblick auf das Pro-Prozess-Dateilimit (ulimit-Sn) nicht gezählt wird .

Ich bin mir nicht sicher, ob diese "err,ltx,pd"auf das Dateilimit angerechnet werden, da ich nicht weiß, wie Dateizugriffsnummern dieser Deskriptortypen erstellt werden.

Das "-p __process_id__"Argument beschränkt sich darauf lsof, nur Informationen für die __process_id__angegebene zurückzugeben. Entfernen Sie diese Option, wenn Sie eine Zählung für alle Prozesse erhalten möchten.

Das "-a"Argument wird zur UND-Verknüpfung der Auswahlen verwendet (dh die Argumente "-p" und "-d").

Die "awk '{if (NR>1) print}'"Anweisung wird verwendet, um die Kopfzeile zu überspringen, die lsofin der Ausgabe gedruckt wird.

Ich habe mit dem folgenden Perl-Skript getestet:

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

Ich musste das Skript im Perl-Debugger ausführen, um sicherzustellen, dass das Skript nicht beendet und die Dateideskriptoren freigegeben werden.

Ausführen: perl -d test.pl

Im Perl-Debugger können Sie das Programm ausführen, indem cSie die Eingabetaste drücken. Wenn Sie ulimit -Snden Wert 1024 hatten , wird das Programm nach dem Erstellen der Test1017.logDatei in angehalten /tmp.

Wenn Sie jetzt die PID des Perl-Prozesses identifizieren und den obigen lsofBefehl verwenden, werden Sie sehen, dass er auch 1024 ausgibt .

Entfernen Sie das Symbol "wc -l"und ersetzen Sie es durch ein Symbol "less", um die Liste der Dateien anzuzeigen, die bis zum Grenzwert von 1024 gezählt haben . Entfernen Sie auch das "-d ^....."Argument, um zu sehen, dass die cwd,txtund rtd-Deskriptoren nicht zum Limit gezählt haben.

Wenn Sie jetzt ausführen "ls -l /proc/__process_id__/fd/ | wc -l", wird der Wert 1025 zurückgegeben. Dies liegt daran , dass der Ausgabe lsein "total 0"Header hinzugefügt wurde , der gezählt wurde.

Hinweis:

Um zu überprüfen, ob dem Betriebssystem die Dateideskriptoren ausgehen, ist es besser, den Wert von zu vergleichen :

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

mit

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txt dokumentiert, was file-nrund was file-maxbedeutet.

Jinesh Choksi
quelle
0

Es scheint, als ob Ihre Argumentation so etwas wie "Ich muss diese Grenze senken, damit mir nicht die wertvollen Deskriptoren ausgehen". Die Wahrheit ist genau das Gegenteil: Wenn auf Ihrem Server keine Dateideskriptoren mehr verfügbar sind, müssen Sie diese Grenze von 1.024 auf etwas Größeres erhöhen . Für eine realistische glassfishImplementierung sind 32.768 sinnvoll.

Persönlich erhöhe ich das Limit immer auf ungefähr 8.192 im gesamten System - 1.024 ist einfach lächerlich. Aber du wirst glassfishhöher erhöhen wollen . Überprüfen Sie /etc/security/limits.conf. Sie können einen speziellen Eintrag für den Benutzer hinzufügen, glassfishder als ausgeführt wird.

David Schwartz
quelle
Ich bin mir nicht sicher, wie du mich so interpretieren könntest :-) Was ich mich gefragt habe, ist, warum es anscheinend nicht zutrifft. Ich werde es höher setzen, aber ich möchte verstehen, wie es auch funktioniert. Wenn das Limit 1024 ist, wie könnte Glassfish dann 1300 Griffe haben?
Oligofren
'lsof -u root | grep / | sort -k9 -u' gibt die eindeutigen Dateideskriptoreinträge aus. Ich denke, die Anzahl der Zeilen ist die tatsächliche Anzahl, für die ulimit -n gilt.
Oligofren
0

Sie möchten einen Blick auf die systemweiten Grenzwerte werfen, die in / proc / sys / fs / file-max festgelegt sind, und sie dort anpassen (bis zum nächsten Neustart) oder fs.file-max in sysctl.conf festlegen, um sie dauerhaft zu machen. Dies könnte hilfreich sein - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html

rnxrx
quelle
1
Dieser Kommentar zu bash ist nicht korrekt. ulimit setzt für Prozesse, die über die Shell initiiert werden, eine Reihe von Grenzwerten pro Benutzer-ID fest. Dies ist praktisch alles, da der Prozessbaum unter Unix-ähnlichen Betriebssystemen erstellt wird. Es ist keine Bash.
EightBitTony
Entschuldigung - wird bearbeitet, aber der Kommentar zu systemweiten Beschränkungen bleibt bestehen.
rnxrx
Es ist sehr unwahrscheinlich, dass er die systemweiten Grenzen überschreitet. Möglich, aber sehr unwahrscheinlich.
David Schwartz
EightBitTony: ulimit setzt ulimit nicht pro Benutzer-ID. Es ist pro Prozess, wenn die pam_limits angewendet werden. Das ulimit, das "pro Benutzer" ist, ist das "ulimit -u". "Die maximale Anzahl von Prozessen, die einem einzelnen Benutzer zur Verfügung stehen"
Kein Benutzername
0

Häufiger Fehler beim Vergleichen des Ergebnisses von Raw-Lsof-Aufrufen mit dem angenommenen Limit.

Für das globale Limit (/ proc / sys / fs / file-max) sollten Sie sich / proc / sys / fs / file-nr ansehen -> der erste Wert gibt an, was verwendet wird und der letzte Wert ist das Limit

Das OpenFile-Limit gilt für jeden Prozess, kann jedoch für einen Benutzer definiert werden. Die Benutzerlimits finden Sie unter "ulimit -Hn" und die Definitionen unter /etc/security/limits.conf. Wird im Allgemeinen mit "app user" angewendet, z. B .: "tomcat": Setzen Sie das Limit auf 65000 für den Benutzer tomcat, der auf den von ihm ausgeführten Java-Prozess angewendet wird.

Wenn Sie die auf einen Prozess angewendete Begrenzung überprüfen möchten, ermitteln Sie die PID und dann: cat / proc / $ {PID} / limits Wenn Sie überprüfen möchten, wie viele Dateien von einem Prozess geöffnet werden, ermitteln Sie die PID und dann: ls -1 / proc / {PID} / fd | wc -l (Anmerkung für ls ist es 'minus eins', nicht mit 'minus el' zu verwechseln)

Wenn Sie Details mit lsof wissen möchten, aber nur für die Datei-Handler, die für das Limit zählen, probieren Sie Folgendes aus: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a

Bemerkung: die 'files' sind files / pipe / tcp connections / etc.

Beachten Sie, dass Sie manchmal wahrscheinlich root sein müssen oder sudo verwenden müssen, um ein korrektes Ergebnis für die Befehle zu erhalten. Manchmal haben Sie ohne Berechtigung keinen Fehler, nur weniger Ergebnisse.

Und wenn Sie wissen möchten, auf welche 'Dateien' in Ihrem Dateisystem ein Prozess zugreift, schauen Sie sich Folgendes an: lsof -p {PID} | grep / | awk '{print $ 9}' | sortieren | uniq

habe Spaß !

Ronan Kerdudou
quelle