现象

最近公司CI jenkins框架加上了sonarqube组件进行代码检测,但是jenkins运行sonarqube后,偶尔会出现下面的错误:

Process leaked file descriptors. See https://jenkins.io/redirect/troubleshooting/process-leaked-file-descriptors for more information
WARN: Unable to locate 'report-task.txt' in the workspace. Did the SonarScanner succeeded?
ERROR: SonarQube scanner exited with non-zero code: 137
Recording test results
Build step 'Publish N'SIQ Collector' marked build as failure

原因

最开始以为是内存不足,开启sonarqube设置了内存大小:SONAR_SCANNER_OPTS=-Xms2048m -Xmx4096m

但是还是报错,最后同事也再网上查了查资料,发现可能是“jenkins杀死衍生进程”。

原因就是这么一个情况:

       Jenkins任务结束时候自动关掉了所有的子进程,不过可以设置一些东西让其可以在后台运行,其实就是在脚本中加入一句:

BUILD_ID=DONTKILLME

 问题的根本在于是Jenkins使用processTreeKiller杀掉了所有子进程,而且这是Jenkins的默认行为。其实回头来看这个问题,就发现Jenkins的做法非常合理。当一次build异常结束,或被人终止时,必然需要结束所有这次build启动的子进程。下面的link提供了更多细节,以及解决方法。https://wiki.jenkins-ci.org/display/JENKINS/ProcessTreeKiller

解决方法

方法一

修改配置文件,启动jenkins时禁止其杀死衍生进程
在 /etc/sysconfig/jenkins 中加入参数
-Dhudson.util.ProcessTree.disable=true即
java -Dhudson.util.ProcessTree.disable=true -jar jenkins.war

方法二

修改构建号,使jenkins找不到衍生进程

BUILD_ID=dontKillMe

还有一种办法直接在shell(要后台执行命令前)加入:

BUILD_ID=dontKillMe

举例:

BUILD_ID=dontKillMe nohup java -Xms246m -Xmx500m -jar ?????.jar > log.log &

备注: 设置mvn编译的内存大小

在bin/mvn中添加如下参数
MAVEN_OPTS="$MAVEN_OPTS -Xms2048m -Xmx2048m -XX:ReservedCodeCacheSize=64m"

其他文献:https://www.cnblogs.com/ceshi2016/p/6044309.html

现象

Jenkins+jmeter 多线程测试java接口时爆错,导致无法生成html报告。

先介绍下场景:

在Jenkins中新建了一个Job,假设你在一些列Build Step之前/之后,启动了一个进程,打个比方说启动一个Jboss进程。等到Build完成,你去Console Output中查看显示启动成功,甚至PID也有了。但是当你去后台查看的时候,发现其实这个进程根本不存在,并没有启动成功。

不过如果你使用的是较早的Hudson版本(Ver 1.136),并且是直接在页面中的Build Session中(如Excute Shell)执行命令的话,你可能会得到如下的提示:

Process leaked file descriptors. See http://wiki.hudson-ci.org/display/HUDSON/Spawning+processes+from+build for more information

如果你看过这篇文章,那么你就会明白造成这种问题的原因是什么:Jenkins默认会在Build结束后Kill掉所有的衍生进程,用官方的话来说就是:

To reliably kill processes spawned by a job during a build, Jenkins contains a bit of native code to list up such processes and kill them.

问题分析:

The reason this problem happens is because of file descriptor leak and how they are inherited from one process to another. Jenkins and the child process are connected by three pipes (stdin/stdout/stderr.) This allows Jenkins to capture the output from the child process. Since the child process may write a lot of data to the pipe and quit immediately after that, Jenkins needs to make sure that it drained the pipes before it considers the build to be over. Jenkins does this by waiting for EOF.

When a process terminates for whatever reasons, the operating system closes all the file descriptors it owned. So even if the process didn't close stdout/stderr, Jenkins will nevertheless get EOF.

The complication happens when those file descriptors are inherited to other processes. Let's say the child process forks another process to the background. The background process (AKA daemon) inherits all the file descriptors of the parent, including the writing side of the stdout/stderr pipes that connect the child process and Jenkins. If the daemon forgets to close them, Jenkins won't get EOF for pipes even when the child process exits, because daemon still have those descriptors open. That's how this problem happens.

从官方的说明中可以看出,造成这种问题的原因,是由于文件描述符的丢失以及子进程是如何继承的。

Jenkins和子进程之间的通信使用三根管道进行:stdin,stdout,stderr,由于Jenkins可以捕捉到子进程的输出,而子进程可能往stdout中写入大量数据然后立即退出,Jenkins为了完整的读取子进程的输出,会在用于子进程stdout的管道上等待EOF。这样,无论子进程由于什么原因退出,系统将关闭进程使用的文件描述符,因而Jenkins总是可以收到EOF。

但是当子进程在后台fork出另一个进程的时候(比如A fork出了B,启动一个daemon进程),情况就出现一些变化。由于进程B会继承进程A的文件描述 符,如果进程B没有关闭这些描述符,即使进程A退出,这些描述符依然是打开的,Jenkins将不会在相应管道上收到EOF。

通常一个实现良好的daemon会关闭所有文件描述符以避免这个问题,但是总有一些实现没有遵循这个规则。在更旧版本的Hudson上,这个问题甚至将导致Job无法结束,Jenkins一直在那等待EOF。

解决办法:

现在我们知道,Jboss之所以没有启动成功,是因为它没有关闭继承的文件描述符,Jenkins在Job构建过程结束后认为Jboss进程未终止,因而将其kill掉了。

1. 使用daemonize工具

在这个页面中https://wiki.jenkins-ci.org/display/JENKINS/Spawning+processes+from+build介绍了一种方法:

On Unix, you can use a wrapper like this to make the daemon behave.

在Unix上,你可以使用daemonize工具将程序作为实现良好的daemon进程运行以避免这个问题:

安装daemonize工具包,使用daemonize命令wrap 相应进程的启动指令,类似于:

  1. daemonize ${your.process} start

另外,页面中也给出了如何在Windows平台解决这个问题的方法,具体的看页面中的介绍就可以了。

2. 重设环境变量BUILD_ID

在研究这个问题的时候,找到了另外一篇文章:https://wiki.jenkins-ci.org/display/JENKINS/ProcessTreeKiller,这篇文章进一步描述了Hudson杀掉衍生进程的情况:

The ProcessTreeKiller takes advantage of the fact that by default a new process gets a copy of the environment variables of its spawning/creating process.

It sets a specific environment variable in the process executing the build job. Later, when the user requests to stop the build job's process it gets a list of all processes running on the computer and their environment variables, and looks for the environment variable that it initially set for the build job's process.

Every job with that environment variable in its environment is then terminated.

意思就是说,Jenkins会在执行Job时设置一系列的环境变量,这些环境变量将被Job衍生出的进程所继承。Jenkins在Kill掉衍生进程的时候会查看进程的环境变量,如果找到它之前设置的环境变量,就将其杀掉。

因此,Wiki中也给出了另外一个简单的方法来避免进程被杀掉:

A convenient way to achieve that is to change the environment variable BUILD_ID which Jenkins's ProcessTreeKiller is looking for. This will cause Jenkins to assume that your daemon is not spawned by the Jenkins build.

修改Hudson设置的环境变量BUILD_ID的值,从而让Jenkins认为此进程不是由Job的构建过程衍生的,如:

  1. BUILD_ID=dontKillMe /usr/apache/bin/httpd

后面的"/usr/apache/bin/httpd"可以省略,即只需要在parameter build trigger中加入一个string parameter,变量名为BUILD_ID,值为dontKillMe即可。

3. 启动时添加禁用参数

除以上两种方式以外,上面的Wiki页面中还提到了第三种解决办法,个人觉得这种方案最靠谱最彻底,不需要再去配置每个Job了:

you can disable this feature by setting a Java property named "hudson.util.ProcessTree.disable" to the value "true". This can be done as a parameter to the "Java" binary when starting Jenkins:

在启动Jenkins的时候直接通过Java选项来关闭Jenkins杀掉所有衍生进程的这个功能:

  1. java -Dhudson.util.ProcessTree.disable=true -jar jenkins.war

参考

https://wiki.jenkins.io/display/JENKINS/ProcessTreeKiller

https://blog.csdn.net/m0_37886429/article/details/81302200

禁止jenkins杀死衍生进程相关推荐

  1. 修改Jenkins启动衍生进程的生命周期

    先介绍下场景: 在Jenkins中新建了一个Job,假设你在一些列Build Step之前/之后,启动了一个进程,打个比方说启动一个Jboss进程.等到Build完成,你去Console Output ...

  2. jenkins 安装以及Jenkins无法在界面关闭跨站请求伪造保护(CSRF)解决403以及如何关闭Jenkins杀掉所有衍生进程

    Jenkins的安装可以通过tomcat作为容器安装,由于Jenkins包就自带了servlet,所以我们只需要下载安装就可以直接启动. 1.下载war包: 官方地址下载:http://mirrors ...

  3. python获取进程编号(目的、获取当前进程编号、根据编号杀死指定进程号、获取当前父进程编号)

    1. 获取进程编号的目的         获取进程编号的目的是验证主进程和子进程的关系,可以得知子进程是由那个主进程创建出来的. 获取进程编号的两种操作 获取当前进程编号 获取当前父进程编号 2. 获 ...

  4. 在ASP.Net中如何彻底杀死Excel进程

    今天在一个项目中使用Dcom的方式获取数据,但是发现Excel进程有时候能杀死,有时候杀不死,导致上传文件时出错的偶发性BUG,经过多次测试,调用API的方式可以彻底杀死Excel进程的方法! 方法体 ...

  5. VC对话框禁止关闭按钮和禁止任务管理中关闭进程

    1.BOOL C***Dlg::OnInitDialog() { //禁止关闭对话框  CMenu* pMenu = this->GetSystemMenu(FALSE);  pMenu-> ...

  6. Linux 命令之 killall 命令-使用进程的名称来杀死一组进程

    文章目录 介绍 语法格式 常用选项 参数 参考示例 介绍 killall 命令使用进程的名称来杀死进程,使用此指令可以杀死一组同名进程.我们可以使用kill命令杀死指定进程 PID 的进程,如果要找到 ...

  7. oracle安装 衍生进程已退出,linux安装oracle 出现问题

    linux安装oracle 出现问题0 出现错误以后, 图片已经插入 请看,然后 我查过资料,说要安装 binutils-2.15.92.0.2-13.0.0.0.2.x86_64.rpm 但是我安装 ...

  8. Linux kill 杀死指定进程

    Linux kill 杀死指定进程 一  杀死指定进程 现知道有一个php线程正在运行,需要杀死 root 26278 1 0 2015 ? 00:00:31 /usr/local/php/bin/p ...

  9. linux杀死vi进程,Linux下关闭所有终端的方法(killall和kill大全)

    一.killall使用方法(结束大多数进程) 参考:http://www..com/peida/archive/2012/12/21/2827366.html Linux系统中的killall命令用于 ...

最新文章

  1. crytojs加密 java解密,使用CryptoJS在Javascript中加密并在Java中解密
  2. Spring cloud系列之Zuul配置项中sensitiveHeaders和ignoredHeaders
  3. [内核编程] 内核环境及其特殊性,驱动编程基础篇
  4. uni-app更新某个组件版本;uni-app更新插件版本;uni-app更新uni_modules插件;uni-app小程序更新某一个组件的版本库
  5. 数列分块入门 2(LibreOj-6278)
  6. sed 执行错误:sed: 1: “…”: Invalid command code f
  7. matlab历史指示穿作用,重新学习MATLAB——相见恨晚的重要应用技巧
  8. 学习C#十五天的总结
  9. [原]CentOS 6.5 上安装 MySQL 5.6
  10. Camshift算法原理及其Opencv实现
  11. 真人拳皇项目第七次Scrum总结——史经浩
  12. centos7更改默认的python版本,安装python3.6.4
  13. 微软服务器系统版本有几个,windows系统有几个版本
  14. RocketMQ创建topic流程解析
  15. 证明不同特征值的实对称矩阵的特征向量相互正交的
  16. 科普向-----验证码
  17. 【系统分析师之路】企业信息化章节错题集锦
  18. PCPNET与POINTNET的比较
  19. Linux内核模块管理
  20. 3.Spring Boot使用Apache Curator实现leader选举「第四章 ZooKeeper Curator应用场景实战」「架构之路ZooKeeper理论和实战」

热门文章

  1. RESTful API的设计原则
  2. python比matlab的优点_python与matlab的优势对比
  3. 斐波那契数列递归思路
  4. 阿联酋·实拍迪拜世界最大最奢侈购物的天堂
  5. Android中视频录制设置录制方向(记录)
  6. PS照片美容:给MM一双美丽的大眼睛
  7. mysql scheme是什么意思_数据库Schema两种含义~~
  8. 在Android上运行Windows XP
  9. mysql 分区 效率_【MySQL】MySQL分区表效率测试对比
  10. 一小时:手把手教你入门express【建议收藏】