在Pipeline运行结束后,Jenkins缺省会kill掉该Pipeline的子进程。因此在pipeline中通过nohup java -jar app.jar > app.log &
的方式启动的java后台进程在Pipeline结束后会被Jenkins杀掉。
解决办法是:
stage('Deploy') {
steps {
script {
withEnv(['JENKINS_NODE_COOKIE=background_job']) {
sh """
nohup java -jar app.jar > app.log &
"""
}
}
}
}
注意:
- 在Pipeline中是通过设置JENKINS_NODE_COOKIE来让Jenkins不要kill掉Pipeline后台子进程,而在Freestyle job中是通过设置BUILD_ID。
- 如果要在一个Pipeline中后台启动多个是script,把多个
nohup
启动命令放到一个withEnv(['JENKINS_NODE_COOKIE=background_job']) {...}
中启动
上面的nohup
命令也可以替换为:
nohup java -jar app.jar > app.log 2>&1 &
或不输出日志
nohup java -jar app.jar > /dev/null 2>&1 &
Kill掉一个后台进程:
sh '''
if [ `ps -ef | grep runserver | grep venv | grep python3 | grep -v grep | awk '{print $2}'` ];then
. .venv/bin/activate
ps -ef | grep runserver | grep venv | grep python3 | grep -v grep | awk '{print $2}' | xargs kill -9
fi
'''
或
// Stop application through kill process
PROCESS_ID = sh (script: "ps -ef | grep ${GIT_REPO_PROJECT} | grep java | grep jar | grep -v grep | grep -v pipeline | awk -F ' ' '{print \$2}'", returnStdout: true).trim()
echo "PROCESS_ID=" + PROCESS_ID
if (PROCESS_ID != "") {
sh """
echo "Kill process: ${PROCESS_ID}"
sudo kill -9 ${PROCESS_ID}
"""
}
参考文档:
- https://wiki.jenkins.io/display/JENKINS/Spawning+processes+from+build
- https://devops.stackexchange.com/questions/1473/running-a-background-process-in-pipeline-job
- https://issues.jenkins-ci.org/browse/JENKINS-28182
- http://excid3.com/blog/running-background-daemon-scripts-with-jenkins
java not found问题
最近遇到一个古怪问题,运行 nohup java -jar app.jar > /dev/null 2>&1 &
命令后,进程没有启动。一开始怀疑是Jenkins在流水线结束后把后台进程杀掉了,搞了半天没有搞定。后面直接运行java -jar app.jar
才发现是java not found
。
原来这台机器上的jdk不是标准安装,导致/bin/java
不存在,而Jenkins运行时是到/bin
目下查找命令的。
解决方法:
# 检查java安装位置
which java
# 创建/bin/java的soft link,比如:
ln -s /home/bin/jdk-13/bin/java /bin/java
# 检查/bin/java文件类型
file /bin/java