近期项目交接,接手了个SpringBoot项目。生产环境里,jar包是通过软链接做成linux服务来启动和停用。

然而,每次通过jenkins构建发版,项目构建完毕,还要手动再去重启服务。

听交接的同事说,可能是有一个钩子阻止服务停用了。

但是,我还是有点纳闷的,既然阻止了服务停用,按道理服务是还能再运行的,不可能构建完了服务就不可用,然后还要手动重启。

随后,我就开始了漫长的搜索……最后还是找到答案了。

步骤重现:

jenkins构建项目,执行脚本,停用服务

service crm-base stop

等了大约一分钟,窗口返回:

Unable to kill process [*****]

脚本执行完停止命令,随后执行启动命令

Unable to kill process [*****]

结果提示,服务正在运行。

Already running [*****]

然而,过了一会儿,去访问服务接口时,服务没有响应了。去查Eureka,微服务的状态此时是Down。

查服务的状态

service crm-base status

结果服务是没有启动的

Not running

显然,执行了服务停止的命令是有效的,感觉是一段时间内服务没有停下来而提示“Unable to kill process”。

接下来,在看到了SpringBoot的内嵌启动脚本源码,也印证了我的想法。

stop() {
working_dir=$(dirname "$jarfile")
pushd "$working_dir" > /dev/null
[[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return ; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return ; }
do_stop "$pid" "$pid_file"
} do_stop() {
kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return ; }
for i in $(seq $STOP_WAIT_TIME); do
isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return ; }
[[ $i -eq STOP_WAIT_TIME/ ]] && kill "$1" &> /dev/null
sleep
done
echoRed "Unable to kill process $1";
return ;
}

可以看到,执行停止方法,本质是做kill操作。方法内有一个for循环,从1遍历到$STOP_WAIT_TIME,每次循环休眠1秒。提示“Unable to kill process”有两处,一处是for循环前,一次是for循环后。

至于$STOP_WAIT_TIME的默认值是多少,我们用Ctrl+F搜脚本

# Initialize stop wait time if not provided by the config file
[[ -z "$STOP_WAIT_TIME" ]] && STOP_WAIT_TIME="{{stopWaitTime:60}}"

可以看到,如果没有配置设置停止等待时间,默认就是60秒。正好印证了这一问题,服务停止约一分钟就提示杀进程失败,而实际上是进程还在处理,需要等待,并非是钩子的问题。

解决方法:

在jar包路径下加jar包同名的配置文件(e.g.:jar包文件名为crm-base.jar,则添加配置的文件名称为crm-base.conf),在配置中调整停止等待时间为120秒

STOP_WAIT_TIME=

再次尝试用jenkins构建,服务终于能顺利重启了。

开始关闭服务
-------------
Stopped []
-------------
开始启动服务
Started []

所以,遇到问题的时候,百度是能短时间解决同类问题,但是找不到解决方法的,还是通过阅读源码最可靠。

参考文档:

[1]. https://github.com/spring-projects/spring-boot/issues/4369

[2]. https://github.com/spring-projects/spring-boot/issues/10159

[3]. https://www.jianshu.com/p/e21b95006371

[4]. https://www.jianshu.com/p/1414dc49d3a9

最新文章

  1. 《软件设计师》——UML
  2. 前台json 的一些 处理 (转)
  3. Python_Day10_进程、线程、协程
  4. Leetcode--Swap Nodes in Pairs
  5. MEF入门之不求甚解,但力求简单能讲明白(三)
  6. 第一章,Linux常用命令
  7. ThreadPool线程池 小结
  8. 一个继承TList的例子
  9. puppet 安装
  10. 添加 Windows 8.1 无虚拟机启动项 解决极品飞车的不支持虚拟机报错
  11. 【CDN】国外访问国内服务器网站-响应慢-CDN
  12. Android源代码下载方法具体解释
  13. UI进阶 多线程
  14. [转]用C#实现的条形码和二维码编码解码器
  15. ThinkPHP 3.1 404页面的设置
  16. C++ *max_element函数找最大元素 *min_element函数找最小元素 STL算法(转)
  17. Git常用操作汇总(转)
  18. 微信JS-SDK开发 入门指南
  19. CentOS7 搭建Git服务器(转)
  20. ThinkPHP中:使用递归写node_merge()函数

热门文章

  1. Linux升级Ruby
  2. 子类覆写的变量被private隐藏,强制转换方式通过子类访问父类的被覆写变量:
  3. geoserver的rest服务介绍,搭建java程序
  4. a标签的四个伪类
  5. 2018.09.28 牛客网contest/197/B面积并(二分+简单计算几何)
  6. 【Unity】2.1 初识Unity编辑器
  7. derective示例
  8. HDU 2561 第二小整数 (排序)
  9. WCF客户端第一请求server特别慢,解决办法
  10. shell 脚本,将/etc/目录下所有的软链接文件输出