title: Jenkins小坑之执行Shell tags:

  • Jenkins
  • ExecuteBash
  • daemonize
  • descriptors categories: ci date: 2017-12-04 22:44:37

背景

  1. 之前使用jenkins的大概率是作为远程部署,通常使用over ssh plugin作部署

问题

我们正常使用ssh时当Java应用运行时没有问题 但是在Execute Bash执行时发现输出如下

    Starting ...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    waitting for f6-insurance start...    2017-12-01 17:05:25.031  INFO 10067 --- [           main] b.c.e.u.UndertowEmbeddedServletContainer : Undertow started on port(s) 8078 (http)    f6-insurance start success!

但是当访问该进程是发现并没有该Java进程【初步怀疑脚本出现问题】

分析

  1. 手动通过执行脚本发现启动正常
  2. 通过jenkins调用发现输出正常但是当jenkins结束后java进程消失
  3. 首先怀疑脚本中没有使用后台命令启动【以前ssh碰到】可以参考  解决Linux关闭终端(关闭SSH等)后运行的程序自动停止
  4. 但是通过检查脚本使用了nohup 没有问题
  5. 多次启动jenkins任务发现都是在任务结束时java进程消失【排除oomkiller&nohup】
  6. 经过‘细心’观察发现如下日志
        Process leaked file descriptors. See https://jenkins.io/redirect/troubleshooting/process-leaked-file-descriptors for more information

  1. 经过相关文档说明总结如下
        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。
  1. 我们找到一个简单的工具称之为daemonize
  2. 安装daemonize
        $ git clone http://github.com/bmc/daemonize.git$ ./configure$ make$ make install

  1. 执行脚本时修改为如下
        daemonize -E BUILD_ID=dontKillcenter  /mnt/shell/restart-f6-insurance-web-prod-trial.sh

方案

    #!/bin/bashcp f6-insurance-web/target/f6-insurance-web-0.0.1-SNAPSHOT.jar /mnt/f6_jar/f6-insurance-web-0.0.1-SNAPSHOT-prod-trial.jarcd /mnt/f6-insurance-8078-prod-trial/daemonize -E BUILD_ID=dontKillcenter  /mnt/shell/restart-f6-insurance-web-prod-trial.sh

这样就可以成功运行!

Jenkins小坑之执行Shell相关推荐

  1. awk小技巧之执行shell命令

    方法一:system函数 1 ip add | grep enp0s8 | grep inet | awk '{print $2}' | awk -F"/" '{printf $1 ...

  2. jenkins shell 权限_jenkins执行shell问题

    问题1:在jenkins的Build--Execute shell中,将编译好的js拷贝到工作目录,没有权限. 原因分析:Jenkins默认会以Jenkins的用户来执行shell 解决办法:修改Ex ...

  3. jenkins 插件执行shell命令时,提示“Command not found”处理方法

    首先提示找不到"Command not found,可能我们第一反应是查看目标机器是否已支持该命令,不过如果相信能找到这里来的朋友估计遇到的跟我一样,其实目标机器是没有问题的通过一些远程工具 ...

  4. Jenkins执行shell脚本启动tomcat失败解决方法

    Jenkins执行shell脚本启动tomcat失败解决方法 参考文章: (1)Jenkins执行shell脚本启动tomcat失败解决方法 (2)https://www.cnblogs.com/wa ...

  5. Linux上用Jenkins执行shell

    目录 安装Jenkins Jdk安装 安装Jenkins 打开防火墙 自定义指定端口9000启动jenkins 浏览器登录 修改管理员密码 创建一个执行shell的任务 构建刚创建的Jenkins任务 ...

  6. for循环不执行的小坑

    最近在做小项目的时候,遇到这么一个小坑,上代码: 这个for循环的意思是:如果后台传的数组中某一个对象的某一个键值对和前端页面上的对象的键值对一致的话,我们就把数组中这个对象替换成前端页面的这一个对象 ...

  7. Jenkins执行shell脚本无法启动子进程解决

    例子:shell脚本 cd /home #test.jar目录 nohup java -jar test.jar --server.port=8081 >test.log 2>&1 ...

  8. windows下jenkins执行shell报错

    创建完Job之后,执行shell脚本报错 Publish] $ sh -xe C:\Windows\TEMP\jenkins1513512433272584870.sh 办法是修改 Manage Je ...

  9. jenkins执行shell文件_jenkins执行shell加载环境变量

    1. jenkins执行shell默认参数为bash -xe,先了解下面基础知识 1.1 什么是交互式shell(interactive shell)和非交互式shell(non-interactiv ...

最新文章

  1. Python列表排序 reverse、sort、sorted 操作方法详解
  2. ssh中添加隧道,访问目标机器上的地址
  3. 检测到磁盘可能为uefi引导_Win10创意者无法更新提示“磁盘布局不受uefi固件支持”怎么办?...
  4. *【牛客 1 - A】矩阵(字符串hash)
  5. 带刺的下沉市场:小镇青年要的不止是9块9包邮
  6. werkzeug Request
  7. 用JS实现的常见几种排序算法
  8. 优雅的使用springboot集成任务调度
  9. EventBus全面讲解和案例
  10. 目标检测(八)--Faster R-CNN
  11. JavaScript教程带你快速入门
  12. SystemVue介绍
  13. 【数据挖掘】 基于二手车交易价格预测-数据分析
  14. Python教程(麻瓜编程实用主义学)
  15. Android基础--ListView的刷新
  16. 公司计算机程序员英语怎么说,计算机程序员英文求职信范文模板
  17. 2009 年幸福的一年
  18. 程序员520❤七夕情人节表白代码Html+Js+Css花瓣相册网页模板❤程序员表白必备...
  19. IAP之boot实现
  20. 中富之命能有多少钱_算命中富 算命的说我是中富命,谁可以帮忙解释下

热门文章

  1. php 复选框 未选,php – 在表单发布时如何获取复选框元素中未选中复选框的值?...
  2. ios aes 128 解密 php,iOS AES加密 PHP解密
  3. Node.js 用户注册功能的实现
  4. python建模 决策_决策树python建模中的坑 :ValueError: Expected 2D array, got 1D array instead:...
  5. 腾讯云服务器CentOS 7安装Tomcat并部署JSP站点统计进入站点人数
  6. python 生成器原理_python生成器
  7. java线程本地变量_Java并发编程示例(九):本地线程变量的使用
  8. dplayer js控制 自动全屏_vue 中使用video.js 实现m3u8视频播放格式
  9. 推荐一个业界最小的可自定义算法的加密芯片
  10. VB 屏幕融化超级恶搞程序代码