Python-Subprozess.Popen-Fehler bei OSError: [Errno 12] Speicher kann nach Zeit nicht zugeordnet werden

8

Hinweis : Diese Frage wurde erneut mit einer Zusammenfassung aller Debugging-Versuche gestellt hier .

Ich habe ein Python-Skript, das alle 60 Sekunden als Hintergrundprozess ausgeführt wird. Ein Teil davon ist ein Aufruf von subprocess.Popen , um die Ausgabe von ps .

%Vor%

Nach einigen Tagen läuft der Aufruf mit:

%Vor%

Die Ausgabe von kostenlos auf dem Server lautet jedoch:

%Vor%

Ich habe nach dem Problem gesucht und dieser Artikel , der sagt:

Lösung ist es, mehr Swap-Speicherplatz zu Ihrem Server hinzuzufügen. Wenn der Kernel versucht, den Modellierer- oder Erkennungsprozess zu starten, stellt er zunächst sicher, dass genügend Platz auf dem Tauschspeicher vorhanden ist, um den neuen Prozess bei Bedarf zu speichern.

Ich bemerke, dass es keinen verfügbaren Swap von der obigen freien Ausgabe gibt. Ist das wahrscheinlich das Problem und / oder welche anderen Lösungen gibt es?

Update 13.8.09 Der obige Code wird alle 60 Sekunden als Teil einer Reihe von Überwachungsfunktionen aufgerufen. Der Prozess ist daemonisiert und die Überprüfung wird mithilfe von geplant geplant. Der spezifische Code für die obige Funktion lautet:

%Vor%

Dies ist Teil einer größeren Klasse namens checks, die einmalig beim Start des Daemon initialisiert wird.

Die gesamte Check-Klasse kann unter Ссылка mit der Funktion getProcesses gefunden werden Zeile 442. Dies wird von doChecks () ab Zeile 520 aufgerufen.

    
DavidM 01.08.2009, 15:14
quelle

9 Antworten

3

Wenn Sie popen verwenden, müssen Sie close_fds = True übergeben, wenn Sie zusätzliche Dateideskriptoren schließen möchten.

Das Erstellen einer neuen Pipe, die in der _get_handles-Funktion aus der Back-Trace erfolgt, erstellt zwei Dateideskriptoren, aber Ihr aktueller Code schließt sie nie und Sie treffen schließlich Ihr System max fd limit.

Nicht sicher, warum der Fehler, den Sie erhalten, eine nicht ausreichende Speicherbedingung anzeigt: Es sollte ein Dateibeschreibungsfehler sein, da der Rückgabewert von pipe() einen Fehlercode für dieses Problem hat.

    
Mark 19.08.2009, 04:18
quelle
6

Sie haben vielleicht ein Speicherleck, das von einigen Ressourcenbeschränkungen begrenzt wird ( RLIMIT_DATA , RLIMIT_AS ?) geerbt von Ihrem Python-Skript. Überprüfen Sie Ihre * ulimit (1) * s, bevor Sie Ihr Skript ausführen, und profilieren Sie die Speichernutzung des Skripts wie von anderen vorgeschlagen.

Was machen Sie mit der Variablen ps nach dem Codeausschnitt, den Sie uns zeigen? Behalten Sie einen Hinweis darauf, niemals frei zu werden? Zitieren Sie die subprocess -Dokumentation :

  

Hinweis: Die gelesenen Daten werden im Speicher zwischengespeichert. Verwenden Sie diese daher nicht   Methode, wenn die Datengröße groß oder unbegrenzt ist.

... und ps aux können bei einem ausgelasteten System sehr ausführlich sein ...

Aktualisieren

Sie können rlimits mit Ihrem Python-Skript überprüfen, indem Sie das Modul verwenden:

%Vor%

Wenn diese "unbegrenzt" zurückgeben - (-1, -1) - dann ist meine Hypothese falsch und Sie können weitermachen!

Siehe auch resource.getrusage , insb. Die Felder ru_??rss , die Ihnen helfen können, die Speicherbelegung mit dem Python-Skript zu instrumentieren, ohne auf ein externes Programm zuzugreifen.

    
pilcrow 13.08.2009 07:02
quelle
3

Diese Swap-Space-Antwort ist falsch. Historisch gesehen, wollten Unix-Systeme Swap-Space zur Verfügung stellen, aber sie funktionieren nicht mehr so ​​(und Linux hat nie so funktioniert). Sie sind nicht einmal knapp davor, nicht mehr genügend Arbeitsspeicher zu haben. Das ist wahrscheinlich nicht das eigentliche Problem - Ihnen geht eine andere begrenzte Ressource aus.

Gegeben, wo der Fehler auftritt (_get_handles ruft os.pipe () auf, um Pipes für das Kind zu erstellen), das einzige wirkliche Problem, auf das Sie stoßen könnten, sind nicht genügend freie Dateideskriptoren. Ich würde stattdessen nach nicht abgeschlossenen Dateien suchen (lsof -p auf der PID des Prozesses, der den popen ausführt). Wenn Ihr Programm wirklich viele Dateien gleichzeitig geöffnet halten muss, dann erhöhen Sie das Benutzerlimit und / oder das Systemlimit für offene Dateideskriptoren.

    
Christopher 13.08.2009 05:30
quelle
2

Wenn Sie einen Hintergrundprozess ausführen, haben Sie wahrscheinlich Ihre Prozesse stdin / stdout / stderr umgeleitet.

Hängen Sie in diesem Fall die Option "close_fds = True" an Ihren Popen-Aufruf an, wodurch verhindert wird, dass der untergeordnete Prozess die umgeleitete Ausgabe erbt. Dies ist möglicherweise die Grenze, auf die Sie stoßen.

    
jmanning2k 14.08.2009 16:54
quelle
1

Sie möchten möglicherweise tatsächlich warten, bis alle diese PS-Prozesse abgeschlossen sind, bevor Sie den Swap-Space hinzufügen.

Es ist überhaupt nicht klar, was "Ausführen als Hintergrundprozess, der alle 60 Sekunden ausgeführt wird" bedeutet.

Aber Ihr Aufruf an subprocess.Popen ist das Forking eines neuen Prozesses jedes Mal.

Aktualisieren .

Ich würde vermuten, dass du all diese Prozesse irgendwie im Stich lässt oder in einem Zombie-Zustand gehst. Die communicate Methode sollte jedoch die erzeugten Subprozesse bereinigen.

    
S.Lott 01.08.2009 15:29
quelle
0

Haben Sie Ihren Prozess im Laufe der Zeit beobachtet?

  • lsof
  • ps -aux | grep -i pname
  • oben

Alle sollten interessante Informationen geben. Ich denke, dass der Prozess Ressourcen bindet, die freigesetzt werden sollten. Besteht die Möglichkeit, dass Ressourcen-Handles (Speicherblöcke, Streams, Datei-Handles, Thread- oder Prozess-Handles) gebunden werden? stdin, stdout, stderr aus dem erstellten "ps". Speicher behandelt, ... aus vielen kleinen Zuweisungen. Ich wäre sehr interessiert zu sehen, was die obigen Befehle für Ihren Prozess anzeigen, wenn er gerade erst gestartet und ausgeführt wurde und nach 24 Stunden "dort" den Unterprozess regelmäßig startet.

Da es nach einigen Tagen abbricht, können Sie es nur für einige wenige Schleifen ausführen und es dann einmal pro Tag als Workaround neu starten. Das würde dir in der Zwischenzeit helfen.

Jacob

    
TheJacobTaylor 13.08.2009 03:08
quelle
0

Sie müssen

%Vor%

Ressourcen freizugeben.

Hinweis: Dies funktioniert nicht unter Windows.

    
Jonas Byström 13.08.2009 08:50
quelle
0

Ich glaube nicht, dass die Umstände, die in dem Zenoss-Artikel angegeben sind, der einzige Grund für diese Nachricht ist, also ist es noch nicht klar, dass Swap-Space definitiv das Problem ist. Ich rate Ihnen, noch mehr Informationen zu sammeln, selbst bei erfolgreichen Anrufen, so dass Sie jederzeit vor dem Aufruf von ps den Status des freien Speichers sehen können.

Noch eine Sache - wenn Sie shell=True im Popen-Aufruf angeben, sehen Sie ein anderes Verhalten?

Update: Wenn nicht Speicher, der nächste mögliche Täter ist in der Tat Dateigriffe. Ich würde empfehlen, den fehlgeschlagenen Befehl unter strace auszuführen, um genau zu sehen, welche Systemaufrufe fehlschlagen.

    
Vinay Sajip 01.08.2009 16:15
quelle
0

Virtueller Speicher ist wichtig !!!

Ich habe das gleiche Problem vor dem Hinzufügen von Swap zu meinem Betriebssystem festgestellt. Die Formel für virtuellen Speicher lautet normalerweise: SwapSize + 50% * PhysicalMemorySize. Ich löse das schließlich, indem ich entweder mehr physischen Speicher hinzufüge oder eine Swap-Platte hinzufüge. close_fds wird in meinem Fall nicht funktionieren.

    
Haoran 02.03.2012 08:56
quelle

Tags und Links