Jenkins CI - Không thể phân bổ bộ nhớ


9

Tôi đã thử nghiệm jenkins-ci thành công trên Ubuntu 10,4 (với phản ứng tổng hợp vmware) trên máy tính cục bộ của tôi. Bây giờ tôi muốn cài đặt và sử dụng nó trên máy chủ ảo của mình tại hosteurope. Việc cài đặt cơ bản không có vấn đề gì, nhưng bây giờ tôi gặp vấn đề với dự án xây dựng của mình.

Sau khi lấy bản cập nhật đồng bộ từ kho lưu trữ, ant được gọi và đưa ra lỗi sau trong dự án xây dựng của tôi:

"Buildfile: /var/lib/jenkins/workspace/concittle5-seed-clean/build.xml [property] java.io.IOException: Không thể chạy chương trình" / usr / bin / env ": java.io.IOException: error = 12, Không thể phân bổ bộ nhớ "

Có một vấn đề được biết đến với kích thước heap tại các máy chủ ảo tại hosteurope ( http://faq.hosteurope.de/index.php?cpid=13918 ), vì vậy tôi đã cố gắng đặt kích thước heap theo cách thủ công:

# 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 

Sau khi thiết lập điều này cho ant, lệnh "ant -diagnostics" chạy qua và không gây ra lỗi, nhưng lỗi vẫn xảy ra khi tôi cố gắng xây dựng dự án.

Chi tiết máy chủ: - http://www.hosteurope.de/produkt/Virtual-Server-Linux-L

  • Ubuntu 10,4 LTS
  • RAM: 1GB / động 2GB

Câu hỏi của tôi: - 1GB có đủ cho Jenkins hay tôi phải nâng cấp máy chủ? - Đây có phải là lỗi do kiến ​​hoặc jenkins?

Cập nhật: Tôi đã nhận được nó chạy với các tùy chọn ant -Xmx128m -Xms128m, nhưng đôi khi lỗi lại xảy ra. (điều này làm tôi bối rối, vì bây giờ tôi không thể tái tạo nó: /)

Giúp nhiều đánh giá cao!

Chúc mừng, Matthias


Tôi đã giải quyết vấn đề này bằng cách đặt các tệp cấu hình jenkins: JENKINS_JAVA_OPTIONS = "- Djava.awt.headless = true -Xms500m -Xmx1000m"
herbertD

Câu trả lời:


10

Orien là chính xác, đó là lệnh gọi hệ thống fork () được kích hoạt bởi ProcessBuilder hoặc Runtime.exec hoặc các phương tiện khác của JVM thực thi một quy trình bên ngoài (ví dụ: một JVM khác đang chạy ant, lệnh git, v.v.).

Đã có một số bài đăng trên danh sách gửi thư của Jenkins về điều này: Không thể chạy chương trình "git" ... error = 12, Không thể phân bổ bộ nhớ

Có một mô tả hay về vấn đề trong danh sách dev của SCons: fork () + exec () vs posix_spawn ()

Có một báo cáo lỗi JVM lâu dài với các giải pháp: Sử dụng posix_spawn, không phải fork, trên S10 để tránh cạn kiệt trao đổi . Nhưng tôi không chắc liệu điều này có thực sự đưa nó vào JDK7 hay không vì các ý kiến ​​cho rằng đó là kế hoạch.

Tóm lại, trên các hệ thống giống Unix, khi một tiến trình (ví dụ JVM) cần khởi chạy một tiến trình khác (ví dụ git), một cuộc gọi hệ thống được thực hiện để fork()sao chép hiệu quả quy trình hiện tại và tất cả bộ nhớ của nó (Linux và các bộ nhớ khác tối ưu hóa điều này bằng bản sao -on-write để bộ nhớ không thực sự được sao chép cho đến khi đứa trẻ cố gắng ghi vào nó). Quá trình trùng lặp sau đó thực hiện một cuộc gọi hệ thống khác, exec()để khởi chạy tiến trình khác (ví dụ git) tại điểm mà tất cả bộ nhớ được sao chép từ tiến trình cha mẹ có thể bị hệ điều hành loại bỏ. Nếu tiến trình cha mẹ đang sử dụng một lượng lớn bộ nhớ (vì các quy trình JVM có xu hướng thực hiện), cuộc gọi đến fork()có thể thất bại nếu hệ điều hành xác định nó không có đủ bộ nhớ + trao đổi để giữ hai bản sao, ngay cả khi tiến trình con sẽ không bao giờ thực sự sử dụng bộ nhớ sao chép đó.

Có một số giải pháp:

  • Thêm bộ nhớ vật lý / RAM cho máy.

  • Thêm nhiều không gian hoán đổi để lừa fork()làm việc, mặc dù không gian trao đổi không thực sự cần thiết cho bất cứ điều gì. Đây là giải pháp tôi chọn vì khá dễ dàng để thêm một tệp hoán đổi và tôi không muốn sống với tiềm năng cho các quy trình bị giết do quá mức.

  • Trên Linux, bật overcommit_memorytùy chọn của hệ thống vm ( / Proc / sys / vm / overcommit_memory ). Với overcommit, lời kêu gọi fork()sẽ luôn thành công và vì quá trình con không thực sự sử dụng bản sao của bộ nhớ đó, tất cả đều ổn. Tất nhiên, có thể với overcommit, các quy trình của bạn sẽ thực sự cố gắng sử dụng nhiều bộ nhớ hơn mức có sẵn và sẽ bị kernel giết chết. Điều này có phù hợp hay không phụ thuộc vào các mục đích sử dụng khác của máy. Các cỗ máy quan trọng có lẽ không nên mạo hiểm với kẻ giết người hết bộ nhớ đang chạy điên cuồng. Nhưng một máy chủ phát triển nội bộ có thể đủ khả năng cho một số thời gian chết sẽ là một nơi tốt để kích hoạt quá mức.

  • Thay đổi JVM để không sử dụng fork()+ exec()mà sử dụng posix_spawn()khi khả dụng. Đây là giải pháp được yêu cầu trong báo cáo lỗi JVM ở trên và được đề cập trong danh sách gửi thư của SCons. Nó cũng được thực hiện trong java_poseix_spawn .

    Tôi đang cố gắng tìm hiểu xem bản sửa lỗi đó có được đưa vào JDK7 không. Nếu không, tôi tự hỏi liệu người Jenkins có quan tâm đến một tác phẩm xung quanh như java_posix_spawn không. Dường như đã có những nỗ lực để tích hợp nó vào Apache commons-exec .

    Lập trình viên, tôi không chắc chắn 100%, nhưng liên kết của bạn cho thấy rằng bản sửa lỗi nằm trong JDK7 và JDK6 1.6.0_23 trở lên. Để ghi lại, tôi đã chạy OpenJDK 1.6.0_18.

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


Cảm ơn câu trả lời bừa bãi! Trong bài đăng liên quan Alf Høgemark nói rằng hiện tại đã được sửa: ( stackoverflow.com/a/9127548/809939 ) Ai đó có thể xác nhận điều này không? Tôi cũng sẽ cố gắng cập nhật phiên bản java của mình.
Chương trình

Câu hỏi thêm: Bạn sẽ đề xuất gì? Thiết lập bộ nhớ quá mức? Trân trọng, Matthias
Programmieraffe

1
Thêm một hoán đổi là dễ dàng và đơn giản. Đối với Ubuntu 12.04 (mặc dù nó nên áp dụng phần lớn cho Linux nói chung), bài viết này rất đơn giản: digitalocean.com/community/articles/ợi
davemyron

1

Lưu ý thông báo ngoại lệ: Cannot run program "/usr/bin/env": java.io.IOException: error=12, Cannot allocate memory"Quá trình Java đang cố gắng phân tách một quy trình mới để chạy lệnh /usr/bin/envnhưng hệ điều hành đã hết tài nguyên bộ nhớ để tạo quy trình mới. Điều này không giống như Java VM hết bộ nhớ nên không có số lượng nào thay đổi với các cờ -Xmx sẽ khắc phục nó. Bạn sẽ cần theo dõi tài nguyên bộ nhớ trong khi chạy bản dựng. Tăng không gian hoán đổi có thể sẽ khắc phục vấn đề của bạn.


Đó là máy ảo Java (một trong những đống hoặc ngăn xếp) hết bộ nhớ KHÔNG phải là hệ thống máy tính chủ.
mdpc

Xin lỗi vì câu trả lời ban đầu của tôi. Tôi đã cập nhật nó để mô tả lý do tại sao nó không phải là JVM hết bộ nhớ.
orien

0

Có khả năng ANT_OPTS bị Jenkins ghi đè. Bạn cũng có thể đặt các tùy chọn trực tiếp trong tệp xây dựng của mình để có thể kiểm soát phân bổ bộ nhớ độc lập với môi trường (shell, Jenkins, ...). Trong tệp xây dựng của bạn (ví dụ:

<java fork="true" classname="..." >
    <jvmarg line="-Xms512M -Xmx512M" />
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.