Jenkins CI - Speicher kann nicht zugeordnet werden


9

Ich habe jenkins-ci erfolgreich auf einem Ubuntu 10.4 (mit VMware Fusion) auf meinem lokalen Computer getestet. Jetzt möchte ich es auf meinem virtuellen Server bei hosteurope installieren und verwenden. Die Grundinstallation war kein Problem, aber jetzt habe ich Probleme mit meinem Build-Projekt.

Nach dem Abrufen eines Mercurial-Updates aus einem Repository wird ant aufgerufen und gibt den folgenden Fehler in meinem Build-Projekt aus:

"Buildfile: /var/lib/jenkins/workspace/concrete5-seed-clean/build.xml [Eigenschaft] java.io.IOException: Programm kann nicht ausgeführt werden" / usr / bin / env ": java.io.IOException: error = 12, Speicher kann nicht zugeordnet werden "

Es ist ein Problem mit der Heap-Größe auf virtuellen Servern bei Hosteurope bekannt ( http://faq.hosteurope.de/index.php?cpid=13918 ). Daher habe ich versucht, die Heap-Größe manuell festzulegen :

# for ant
export ANT_OPTS="-Xms512m -Xmx512m"

# jenkins
# edited /etc/default/jenkins, added line 
JAVA_ARGS="-Xms512m -Xmx512m"
# restarted jenkins via /etc/init.d/jenkins restart 

Nachdem Sie dies für ant festgelegt haben, wird der Befehl "ant -diagnostics" ausgeführt und verursacht keinen Fehler. Der Fehler tritt jedoch weiterhin auf, wenn ich versuche, das Projekt zu erstellen.

Server-Details: - http://www.hosteurope.de/produkt/Virtual-Server-Linux-L

  • Ubuntu 10.4 LTS
  • RAM: 1 GB / Dynamisch 2 GB

Meine Fragen: - Reicht 1 GB für Jenkins aus oder muss ich den Server aktualisieren? - Wird dieser Fehler durch Ameisen oder Jenkins verursacht?

Update: Ich habe es mit den Ant-Optionen -Xmx128m -Xms128m zum Laufen gebracht, aber manchmal tritt der Fehler erneut auf. (das macht mich verrückt, weil ich es jetzt nicht reproduzieren kann: /)

Hilfe sehr geschätzt!

Prost, Matthias


Ich habe dies gelöst, indem ich jenkins Konfigurationsdateien gesetzt habe: JENKINS_JAVA_OPTIONS = "- Djava.awt.headless = true -Xms500m -Xmx1000m"
herbertD

Antworten:


10

Orien ist korrekt, es ist der Systemaufruf fork (), der von ProcessBuilder oder Runtime.exec oder anderen Mitteln der JVM ausgelöst wird, die einen externen Prozess ausführen (z. B. eine andere JVM, auf der ant ausgeführt wird, ein git-Befehl usw.).

Es gab einige Beiträge in den Jenkins-Mailinglisten zu diesem Thema: Programm "git" kann nicht ausgeführt werden ... error = 12, Speicher kann nicht zugeordnet werden

Es gibt eine schöne Beschreibung des Problems auf der SCons- Entwicklerliste : fork () + exec () vs posix_spawn ()

Es gibt einen langjährigen JVM-Fehlerbericht mit Lösungen: Verwenden Sie posix_spawn, nicht fork, auf S10, um eine Erschöpfung des Swaps zu vermeiden . Aber ich bin mir nicht sicher, ob dies tatsächlich in JDK7 geschafft hat, wie aus den Kommentaren hervorgeht.

Zusammenfassend lässt sich sagen, dass auf Unix-ähnlichen Systemen, wenn ein Prozess (z. B. die JVM) einen anderen Prozess (z. B. git) starten muss, ein Systemaufruf ausgeführt wird, fork()der den aktuellen Prozess und seinen gesamten Speicher effektiv dupliziert (Linux und andere optimieren dies durch Kopieren) -on-write, damit der Speicher erst kopiert wird, wenn das Kind versucht, darauf zu schreiben). Der doppelte Prozess führt dann einen weiteren Systemaufruf durch, exec()um den anderen Prozess (z. B. git) zu starten. An diesem Punkt kann der gesamte vom übergeordneten Prozess kopierte Speicher vom Betriebssystem verworfen werden. Wenn der übergeordnete Prozess viel Speicher verwendet (wie dies bei JVM-Prozessen fork()der Fall ist ), schlägt der Aufruf möglicherweise fehl, wenn das Betriebssystem feststellt, dass nicht genügend Speicher + Swap für zwei Kopien vorhanden ist, auch wenn der untergeordnete Prozess dies tatsächlich nie tun wird Verwenden Sie diesen kopierten Speicher.

Es gibt verschiedene Lösungen:

  • Fügen Sie dem Computer mehr physischen Speicher / RAM hinzu.

  • Fügen Sie mehr Swap-Speicherplatz hinzu, um das fork()Arbeiten zu erleichtern, obwohl der Swap-Speicherplatz für nichts unbedingt benötigt wird. Dies ist die Lösung, die ich gewählt habe, weil es ziemlich einfach ist, eine Swap-Datei hinzuzufügen, und ich wollte nicht mit dem Potenzial leben, dass Prozesse aufgrund von Überbindung abgebrochen werden.

  • Aktivieren Sie unter Linux die overcommit_memoryOption des VM-Systems ( / proc / sys / vm / overcommit_memory ). Mit Overcommit fork()würde der Aufruf von immer erfolgreich sein, und da der untergeordnete Prozess diese Kopie des Speichers nicht wirklich verwenden wird, ist alles in Ordnung. Natürlich ist es möglich, dass Ihre Prozesse bei Overcommit tatsächlich versuchen, mehr Speicher als verfügbar zu verwenden, und vom Kernel beendet werden. Ob dies angemessen ist, hängt von den anderen Verwendungszwecken der Maschine ab. Missionskritische Maschinen sollten wahrscheinlich nicht riskieren, dass der Killer mit zu wenig Speicher Amok läuft. Ein interner Entwicklungsserver, der sich Ausfallzeiten leisten kann, ist jedoch ein guter Ort, um eine Überbindung zu ermöglichen.

  • Ändern Sie die JVM so, dass sie nicht fork()+ verwendet, exec()sondern verwendet wird, posix_spawn()wenn verfügbar. Dies ist die Lösung, die im obigen JVM-Fehlerbericht angefordert und in der SCons-Mailingliste aufgeführt ist. Es ist auch in java_posix_spawn implementiert .

    Ich versuche herauszufinden, ob dieses Update es in JDK7 geschafft hat. Wenn nicht, frage ich mich, ob die Jenkins-Leute an einer Arbeit wie java_posix_spawn interessiert wären. Es scheint Versuche gegeben zu haben, dies in Apache commons-exec zu integrieren .

    Programmieraffe, ich bin nicht 100% sicher, aber Ihr Link deutet darauf hin, dass das Update in JDK7 und JDK6 1.6.0_23 und höher enthalten ist. Für die Aufzeichnung habe ich OpenJDK 1.6.0_18 ausgeführt.

Siehe /programming/1124771/how-to-solve-java-io-ioexception-error-12-cannot-allocate-memory-calling-run


Vielen Dank für die detaillierte Antwort! In dem verwandten Beitrag sagt Alf Høgemark, dass dies jetzt behoben ist: ( stackoverflow.com/a/9127548/809939 ) Kann jemand dies bestätigen? Ich werde versuchen, auch meine Java-Version zu aktualisieren.
Programmieraffe

Zusätzliche Frage: Was würden Sie vorschlagen? Overcommit-Memory-Einstellung? Grüße, Matthias
Programmieraffe

1
Das Hinzufügen einer Swap-Datei ist einfach und unkompliziert. Für Ubuntu 12.04 (obwohl es im Allgemeinen weitgehend für Linux gelten sollte) war dieser Artikel ganz einfach: digitalocean.com/community/articles/…
davemyron

1

Beachten Sie die Ausnahmemeldung: Cannot run program "/usr/bin/env": java.io.IOException: error=12, Cannot allocate memory"Der Java-Prozess versucht, einen neuen Prozess zum Ausführen des Befehls zu verzweigen, /usr/bin/envaber das Betriebssystem verfügt nicht über genügend Speicherressourcen, um einen neuen Prozess zu erstellen. Dies ist nicht dasselbe wie bei der Java-VM, die nicht über genügend Arbeitsspeicher verfügt. Daher wird dies nicht durch das Herumspielen mit -Xmx-Flags behoben. Sie müssen Ihre Speicherressourcen überwachen, während Sie Ihren Build ausführen. Durch Erhöhen des Swap-Bereichs wird Ihr Problem wahrscheinlich behoben.


Es ist die Java Virtual Machine (einer der Haufen oder Stapel), die nicht genügend Speicher hat, NICHT das Host-Computersystem.
Mdpc

Entschuldigen Sie die Kürze meiner ursprünglichen Antwort. Ich habe es aktualisiert, um zu beschreiben, warum der JVM nicht der Speicher ausgeht.
Orien

0

Es ist wahrscheinlich, dass ANT_OPTS von Jenkins überschrieben werden. Sie können die Optionen auch direkt in Ihrer Build-Datei festlegen, sodass Sie die Speicherzuordnung unabhängig von der Umgebung (Shell, Jenkins, ...) steuern können. In Ihrer Build-Datei (Beispiel:

<java fork="true" classname="..." >
    <jvmarg line="-Xms512M -Xmx512M" />
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.