我在本地计算机上的 ubuntu 10.4(带有 vmware fusion)上成功测试了 jenkins-ci。现在我想在 hosteurope 的虚拟服务器上安装并使用它。基本安装没有问题,但现在我的构建项目出现了问题。
从存储库中提取 mercurial 更新后,调用 ant 并在我的构建项目中引发以下错误:
“构建文件:/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
- 内存:1GB / 动态2GB
我的问题: - 1GB 对 Jenkins 来说够用吗,还是我必须升级服务器? - 这个错误是由 ant 还是 jenkins 引起的?
更新:我使用 ant 选项 -Xmx128m -Xms128m 运行它,但有时会再次出现错误。(这让我很害怕,因为我现在无法重现它 :/)
非常感谢帮助!
欢呼吧,马蒂亚斯
答案1
Orien 是正确的,它是由 ProcessBuilder 或 Runtime.exec 或 JVM 执行外部进程的其他方式(例如另一个运行 ant、git 命令等的 JVM)触发的 fork() 系统调用。
Jenkins 邮件列表中有一些关于此问题的帖子:无法运行程序“git”...错误=12,无法分配内存
SCons 开发列表中对该问题进行了很好的描述:fork()+exec() 与 posix_spawn()
这里有一个长期存在的 JVM 错误报告及其解决方案:在 S10 上使用 posix_spawn,而不是 fork,以避免交换耗尽。但我不确定这是否真的像评论所暗示的计划那样进入了 JDK7。
总之,在类 Unix 系统上,当一个进程(例如 JVM)需要启动另一个进程(例如 git)时,会进行系统调用,从而fork()
有效地复制当前进程及其所有内存(Linux 和其他系统使用写时复制对此进行了优化,因此在子进程尝试写入之前不会真正复制内存)。 然后,复制的进程进行另一个系统调用,exec()
以启动另一个进程(例如 git),此时操作系统可能会丢弃从父进程复制的所有内存。 如果父进程正在使用大量内存(正如 JVM 进程倾向于做的那样),fork()
如果操作系统确定它没有足够的内存+交换来容纳两个副本,即使子进程实际上永远不会使用复制的内存,调用也可能失败。
有几种解决方案:
为机器添加更多物理内存/RAM。
添加更多交换空间以诱使它
fork()
工作,即使交换空间并非绝对需要。这是我选择的解决方案,因为添加交换文件相当容易,而且我不想忍受由于过度使用而导致进程被终止的可能性。在 Linux 上,启用
overcommit_memory
vm 系统的选项(/proc/sys/vm/overcommit_memory)。如果使用过量使用,对的调用fork()
将始终成功,并且由于子进程实际上不会使用该内存副本,因此一切正常。当然,如果使用过量使用,您的进程实际上可能会尝试使用超过可用内存的内存,并将被内核终止。这是否合适取决于机器的其他用途。关键任务机器可能不应该冒内存不足杀手失控的风险。但是,可以承受一些停机时间的内部开发服务器将是启用过量使用的好地方。将 JVM 更改为不使用
fork()
+exec()
,而是在可用时使用posix_spawn()
。这是上述 JVM 错误报告中请求的解决方案,并在 SCons 邮件列表中提到。它也在java_posix_spawn。我正在尝试找出该修复是否已进入 JDK7。如果没有,我想知道 Jenkins 人员是否会对 java_posix_spawn 之类的解决方法感兴趣。似乎有人尝试将其集成到Apache commons-exec。
Programmieraffe,我并不是 100% 确定,但您的链接确实表明修复是在 JDK7 和 JDK6 1.6.0_23 及更高版本中。顺便说一下,我当时运行的是 OpenJDK 1.6.0_18。
答案2
请注意异常消息:Cannot run program "/usr/bin/env": java.io.IOException: error=12, Cannot allocate memory"
Java 进程正在尝试分叉一个新进程来运行命令/usr/bin/env
,但操作系统已耗尽内存资源来创建新进程。这与 Java VM 耗尽内存不同,因此无论摆弄多少 -Xmx 标志都无法修复它。您需要在运行构建时监视内存资源。增加交换空间可能会解决您的问题。
答案3
ANT_OPTS 很可能被 Jenkins 覆盖。您还可以直接在构建文件中设置选项,以便可以独立于环境(shell、Jenkins 等)控制内存分配。在您的构建文件中(例如:
<java fork="true" classname="..." >
<jvmarg line="-Xms512M -Xmx512M" />