Jenkins CI - ไม่สามารถจัดสรรหน่วยความจำได้


9

ฉันทดสอบ jenkins-ci เรียบร้อยแล้วบน Ubuntu 10.4 (ด้วย vmware fusion) บนคอมพิวเตอร์ของฉัน ตอนนี้ฉันต้องการติดตั้งและใช้งานบนเซิร์ฟเวอร์เสมือนที่ hosteurope การติดตั้งพื้นฐานไม่มีปัญหา แต่ตอนนี้ฉันมีปัญหากับโครงการสร้างของฉัน

หลังจากดึงการอัปเดต Mercurial จากที่เก็บมดถูกเรียกใช้และโยนข้อผิดพลาดต่อไปนี้ในโครงการสร้างของฉัน:

"Buildfile: /var/lib/jenkins/workspace/concrete5-seed-clean/build.xml [คุณสมบัติ] java.io.IOException: ไม่สามารถเรียกใช้โปรแกรม" / usr / bin / env ": java.io.IOException: ข้อผิดพลาด = 12, ไม่สามารถจัดสรรหน่วยความจำได้ "

มีปัญหาที่ทราบเกี่ยวกับขนาดฮีปที่เซิร์ฟเวอร์เสมือนที่ hosteurope ( http://faq.hosteurope.de/index.php?cpid=13918 ) ดังนั้นฉันจึงพยายามตั้งค่าขนาดฮีพด้วยตนเอง:

# 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 

หลังจากตั้งค่านี้สำหรับ ant คำสั่ง "ant -diagnostics" ทำงานผ่านและไม่ทำให้เกิดข้อผิดพลาด แต่ข้อผิดพลาดยังคงเกิดขึ้นเมื่อฉันพยายามสร้างโครงการ

รายละเอียดเซิร์ฟเวอร์: - http://www.hosteurope.de/produkt/Virtual-Server-Linux-L

  • Ubuntu 10.4 LTS
  • RAM: 1GB / 2GB แบบไดนามิก

คำถามของฉัน: - 1GB เพียงพอสำหรับเจนกินส์หรือฉันต้องอัปเกรดเซิร์ฟเวอร์หรือไม่ - ข้อผิดพลาดนี้เกิดจากมดหรือเจนกินส์หรือไม่?

ปรับปรุง: ฉันได้รับมันทำงานด้วยตัวเลือกมด -Xmx128m -Xms128m แต่บางครั้งข้อผิดพลาดเกิดขึ้นอีกครั้ง (สิ่งนี้ทำให้ฉันประหลาดใจเพราะฉันไม่สามารถทำซ้ำได้ตอนนี้: /)

ช่วยชื่นชมมาก!

ไชโยแมทเธียสช


ฉันแก้ไขได้โดยตั้งไฟล์ config jenkins: JENKINS_JAVA_OPTIONS = "- Djava.awt.headless = true -Xms500m -Xmx1000m"
herbertD

คำตอบ:


10

Orien ถูกต้องมันคือการเรียกระบบ fork () ที่ถูกทริกเกอร์โดย ProcessBuilder หรือ Runtime.exec หรือวิธีการอื่นของ JVM ที่ดำเนินการกระบวนการภายนอก (เช่น JVM อื่นที่รัน ant คำสั่ง git ฯลฯ )

มีบางโพสต์ในรายชื่อผู้รับจดหมายของ Jenkins เกี่ยวกับเรื่องนี้: ไม่สามารถเรียกใช้โปรแกรม "git" ... error = 12, ไม่สามารถจัดสรรหน่วยความจำได้

มีคำอธิบายที่ดีของปัญหาในรายการ SCons dev: fork () + exec () vs posix_spawn ()

มีความยาวยืนรายงานข้อผิดพลาด JVM กับการแก้ปัญหาคือการใช้ posix_spawn ไม่แยกบน S10 ไปหมดแลกเปลี่ยนหลีกเลี่ยง แต่ฉันไม่แน่ใจว่าสิ่งนี้ทำให้มันกลายเป็น JDK7 ตามความเห็นที่แนะนำว่าเป็นแผนหรือไม่

โดยสรุปบนระบบที่คล้าย Unix เมื่อกระบวนการหนึ่ง (เช่น JVM) จำเป็นต้องเปิดใช้กระบวนการอื่น (เช่น git) การเรียกใช้ระบบจะทำfork()กระบวนการที่ซ้ำซ้อนอย่างมีประสิทธิภาพในปัจจุบันและหน่วยความจำทั้งหมด (Linux และกระบวนการอื่น ๆ -on-write ดังนั้นหน่วยความจำจะไม่ถูกคัดลอกจนกว่าเด็กจะพยายามเขียนลงไป) กระบวนการที่ซ้ำกันทำให้การเรียกของระบบอื่นexec()เพื่อเปิดใช้กระบวนการอื่น ๆ (เช่น git) ที่จุดทั้งหมดที่คัดลอกหน่วยความจำจากกระบวนการหลักอาจถูกทิ้งโดยระบบปฏิบัติการ หากกระบวนการหลักใช้หน่วยความจำจำนวนมาก (เนื่องจากกระบวนการ JVM มักจะทำ) การเรียกใช้fork()อาจล้มเหลวหากระบบปฏิบัติการพิจารณาว่าไม่มีหน่วยความจำ + swap เพียงพอที่จะเก็บสำเนาสองชุดแม้ว่ากระบวนการลูกจะไม่จริง ใช้หน่วยความจำที่คัดลอก

มีหลายวิธี:

  • เพิ่มหน่วยความจำกายภาพ / RAM ให้กับเครื่อง

  • เพิ่มพื้นที่สว็อปมากขึ้นเพื่อหลอกล่อfork()ให้ทำงานแม้ว่าพื้นที่สว็อปไม่จำเป็นสำหรับสิ่งใดก็ตาม นี่เป็นวิธีการแก้ปัญหาที่ฉันเลือกเพราะมันค่อนข้างง่ายในการเพิ่ม swapfile และฉันไม่ต้องการที่จะอยู่กับศักยภาพของกระบวนการที่จะถูกฆ่าเนื่องจาก overcommit

  • บน Linux ให้เปิดใช้งานovercommit_memoryตัวเลือกของระบบ vm ( / proc / sys / vm / overcommit_memory ) ด้วย overcommit การเรียกใช้fork()จะประสบความสำเร็จเสมอและเนื่องจากกระบวนการลูกไม่ได้ใช้สำเนาหน่วยความจำนั้นจริงทั้งหมดจึงเป็นไปได้ด้วยดี แน่นอนว่าเป็นไปได้ว่าด้วย overcommit กระบวนการของคุณจะพยายามใช้หน่วยความจำมากกว่าที่มีอยู่และเคอร์เนลจะถูกฆ่า ความเหมาะสมนี้ขึ้นอยู่กับการใช้งานอื่นของเครื่อง เครื่องที่มีภารกิจสำคัญไม่ควรเสี่ยงนักฆ่านอกจำที่ทำงานอาละวาด แต่เซิร์ฟเวอร์การพัฒนาภายในที่สามารถหยุดทำงานได้บางครั้งจะเป็นสถานที่ที่ดีในการเปิดใช้งานเกิน

  • เปลี่ยน JVM เป็นไม่ใช้fork()+ exec()แต่จะใช้posix_spawn()เมื่อพร้อมใช้งาน นี่เป็นวิธีการแก้ปัญหาที่ร้องขอในรายงานบั๊ก JVM ด้านบนและกล่าวถึงในรายชื่อผู้รับจดหมายของ SCons นอกจากนี้ยังดำเนินการในjava_posix_spawn

    ฉันพยายามค้นหาว่าการแก้ไขนั้นทำให้เป็น JDK7 หรือไม่ ถ้าไม่ฉันสงสัยว่าคนเจนกินส์จะสนใจงานที่ทำเช่น java_posix_spawn หรือไม่ ดูเหมือนจะมีความพยายามที่จะบูรณาการที่เป็นApache Commons-exec

    โปรแกรมฉันไม่แน่ใจ 100% แต่ลิงก์ของคุณแนะนำว่าการแก้ไขนั้นอยู่ใน JDK7 และ JDK6 1.6.0_23 และใหม่กว่า สำหรับบันทึกฉันใช้ OpenJDK 1.6.0_18

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


ขอบคุณสำหรับคำตอบที่ไม่ต้องชำระ! ในโพสต์ที่เกี่ยวข้อง Alf Høgemarkบอกว่าสิ่งนี้ได้รับการแก้ไขแล้วในตอนนี้: ( stackoverflow.com/a/9127548/809939 ) ใครบางคนสามารถยืนยันได้หรือไม่ ฉันจะพยายามอัปเดตเวอร์ชัน Java ของฉันเช่นกัน
Programmieraffe

คำถามเพิ่มเติม: คุณจะเสนออะไร overcommit หน่วยความจำตั้งค่า? ขอแสดงความนับถือแมทเธีย
โปรแกรม

1
การเพิ่ม swapfile นั้นง่ายและตรงไปตรงมา สำหรับ Ubuntu 12.04 (แต่ควรใช้กับ Linux เป็นส่วนใหญ่) บทความนี้ตายง่าย ๆ : digitalocean.com/community/articles/ …
davemyron

1

หมายเหตุข้อความข้อยกเว้น: Cannot run program "/usr/bin/env": java.io.IOException: error=12, Cannot allocate memory"กระบวนการ Java กำลังพยายามแยกกระบวนการใหม่เพื่อเรียกใช้คำสั่ง/usr/bin/envแต่ระบบปฏิบัติการมีทรัพยากรหน่วยความจำหมดเพื่อสร้างกระบวนการใหม่ สิ่งนี้ไม่เหมือนกับ Java VM ที่มีหน่วยความจำไม่เพียงพอดังนั้นจำนวนของการเล่นซอกับแฟล็ก -Xmx จะแก้ไขได้ คุณจะต้องตรวจสอบทรัพยากรหน่วยความจำของคุณในขณะที่เรียกใช้งานสร้าง การเพิ่มพื้นที่สว็อปจะช่วยแก้ปัญหาของคุณได้


เป็นเครื่อง Java Virtual (หนึ่งในกองหรือกองซ้อน) ที่มีหน่วยความจำไม่เพียงพอระบบคอมพิวเตอร์แม่ข่าย
mdpc

แก้ตัวสั้น ๆ ของคำตอบเดิมของฉัน ฉันได้อัปเดตเพื่ออธิบายว่าเพราะเหตุใดจึงไม่ใช่ JVM หน่วยความจำไม่เพียงพอ
orien

0

มีโอกาสที่ ANT_OPTS จะถูกเขียนโดย Jenkins คุณยังสามารถตั้งค่าตัวเลือกได้โดยตรงในไฟล์บิลด์เพื่อให้คุณสามารถควบคุมการจัดสรรหน่วยความจำได้อย่างอิสระจากสภาพแวดล้อม (เชลล์, เจนกินส์, ... ) ในไฟล์บิลด์ของคุณ (ตัวอย่าง:

<java fork="true" classname="..." >
    <jvmarg line="-Xms512M -Xmx512M" />
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.