环境(Enviornment)
- Docker: 19.03
- Puma: 5.1.1
- Ruby: 2.6.6
问题(Problem)
因为使用Jenkins
时,跑的Ansible Playbook
的最后一个role
是启动Docker
容器,而启动容器的命令是docker-compose up -d
,这就导致docker-compose
在后台启动,直接返回执行完成,那样Ansible
就执行完了。因为Jenkins
除了Ansible
以外没有别的任务了,所以Jenkins
也显示任务已完成。
而实际上,docker
容器还没启动完成,这样就会有两个问题:
- 无法判断任务是在什么时候执行完的(因为
Jenkins
显示的只是脚本执行完成的时间) - 如果这个时候有新的任务上来的话,
Jenkins
会直接执行新的任务,而不是等待前一个任务的容器启动完成(因为Jenkins
并不知道容器的状态),这样可能就会导致之前的容器还没启动完就被这次的覆盖了,可能会导致出现一些问题。
解决办法
因为我最后一个启动的容器(也是耗时最长的容器)是puma
的容器,所有解决办法就是判断puma
什么时候启动完成了。因为也想在Jenkins
里边看到容器的启动日志,方便出了问题时调查,所以这里就用日志的结果来判断是否启动完成了。
我的想法是这样子的,需要实时看到启动日志的话,用tail -f
就可以了,而判断是否启动完成,就根据当前日志的最后一行判断,因为启动完成后,最后一行显示的是Use Ctrl-C to stop
。将这个想法写成脚本后,就是下面的样子:
# 等待容器启动,防止读到上次的log
sleep 10
docker logs -f deploy_jh_web_1 &
# puma 所在容器的名称是 deploy_jh_web_1
while [[ `docker logs --tail 1 deploy_jh_web_1` != *'Use Ctrl-C to stop'* ]]
do
sleep 1
done
kill %1
然后将该脚本加入作为Jenkins
的最后一个任务,如果该任务执行完毕,说明部署已完成
参考
tail -f
根据内容退出的方法参考How to quit "tail -f" mode without using "Ctrl+c"?