1.遇到的问题

在分布式项目部署的过程中,经常要求服务器重启之后,应用(包括数据库)能够自动恢复使用.虽然使用docker update --restart=always containerid能够让容器自动随docker启动,但是并不能保证是在数据库启动之后启动,如果数据库未启动,那么将导致应用启动失败;网上还有一种解决方法是通过docker-compose容器编排来控制启动顺序,这个博主研究的比较少.

2.解决思路

使用Shell脚本来控制,思路大致如下

  1. 探测数据库端口来检验数据库是否启动成功.
  2. 数据库启动成功后,探测配置中心及服务注册中心的端口来检验其是否启动成功.
  3. 当数据库及配置中心都启动之后,再启动其他微服务应用.

3.端口探测

端口探测使用的命令是

nc -w 1 host port </dev/null && echo "200"

host:目标主机的ip

port:服务监听的端口

如果服务启动了 这条命令会返回 200,未启动则返回空.

4.Shell脚本

直接贴代码了,使用的配置中心是nacos

#!/bin/bash
#chkconfig: 2345 80 90
#description:autoStartMaintenanceService.sh
#
#前提:
#1.docker必须能开机自启
#2.docker能够正常启动运维服务
#3.此脚本须运行微服务所在的机器上
#
##需要修改的配置-----开始
##数据库所在的机器IP
DATABASE_HOST=192.169.1.52
##数据库监听的端口
DATABASE_PORT=3306
##微服务所在机器IP
LOCAL_HOST=192.169.1.46
##微服务访问端口
Maintenance_Port=8180
##NACOS所在机器的ip
NACOS_HOST=192.169.1.82
##NACOS的监听端口
NACOS_PORT=8848
##微服务容器名称(NAMES列)
Maintenance_Container_Name="umc-maintenance"
##该脚本生成的日志路径
Log_Path=/home/test/log
##需要修改的配置-----结束
##
##循环延时时间(s)秒
LOOP_TIME=5
at_time=""
at_date="" getAtTime() {
at_time="$(date +%Y-%m-%d-%H:%M:%S) --- "
at_date=$(date +%Y-%m-%d)
} autoStartWebService() {
##如果日志路径不存在则创建
if [ ! -d "$Log_Path" ]; then
mkdir -p $Log_Path
fi while true; do
##判断数据库是否启动
req_message=$(nc -w 1 ${DATABASE_HOST} ${DATABASE_PORT} </dev/null && echo "200")
if [ -n "$req_message" ]; then
getAtTime
echo "$at_time Database is running" >>${Log_Path}/"$at_date"_autoStartMaintenanceService.log
waitNacosStarting
else
getAtTime
echo "$at_time Database is not running and please wait for Database starting" >>${Log_Path}/"$at_date"_autoStartMaintenanceService.log
sleep $LOOP_TIME
fi
done
}
##判断Nacos是否启动
waitNacosStarting() {
req_message=$(nc -w 1 ${NACOS_HOST} ${NACOS_PORT} </dev/null && echo "200")
if test $((req_message)) -eq 200; then
getAtTime
echo "$at_time Nacos is running" >>${Log_Path}/"$at_date"_autoStartMaintenanceService.log
startMaintenanceService
sleep $LOOP_TIME
else
getAtTime
echo "$at_time Nacos is not running and please wait for nacos starting" >>${Log_Path}/"$at_date"_autoStartMaintenanceService.log
sleep $LOOP_TIME
fi
} ##启动微服务
startMaintenanceService() {
req_message=$(nc -w 1 ${LOCAL_HOST} ${Maintenance_Port} </dev/null && echo "200")
if test $((req_message)) -eq 200; then
getAtTime
echo "$at_time Maintenance service is running" >>${Log_Path}/"$at_date"_autoStartMaintenanceService.log
else
container_id=$(docker ps -a | grep $Maintenance_Container_Name | grep -v grep | awk '{print $1}')
getAtTime
echo "$at_time Maintenance service container id is ${container_id}" >>${Log_Path}/"$at_date"_autoStartMaintenanceService.log
docker start ${container_id}
fi } autoStartWebService

5.Shell输入输出重定向

写这个脚本的时候,也让博主对Shell输入输出重定向更加熟悉

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
命令 说明
command > file 将输出重定向到 file且会覆盖file
command < file 将输入重定向到 file
command >> file 将输出以追加的方式重定向到file
command 2> file 将错误输出到file且会覆盖file
command 2>> file 将错误以追加的方式重定向到file
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入

如果希望将 stdout 和 stderr 合并后重定向到 file(即将正确信息和错误信息都输出到file),可以这样写:

command > file 2>&1
或者
command >> file 2>&1

/dev/null文件

/dev/null是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到禁止输出的效果

command > /dev/null 2>&1 可以屏蔽stdout和stderr

参考

菜鸟教程-Shell

Shell脚本控制docker容器启动顺序的更多相关文章

  1. shell 脚本控制命令的执行顺序

    &&,||,(),{},& 五个符号的运用shell脚本执行命令的时候,有时候会依赖于前一个命令是否执行成功.而&&和||就是用来判断前一个命令执行效果的. 也 ...

  2. Docker容器启动时初始化Mysql数据库

    1. 前言 Docker在开发中使用的越来越多了,最近搞了一个Spring Boot应用,为了方便部署将Mysql也放在Docker中运行.那么怎么初始化 SQL脚本以及数据呢? 我这里有两个传统方案 ...

  3. docker容器启动设置固定IP

    docker安装以后的网络类型 [root@insure updev]# docker network ls NETWORK ID NAME DRIVER SCOPE 14da40175b01 bri ...

  4. Docker容器启动Mysql,Docker实现Mysql主从,读写分离

    Docker容器启动Mysql,Docker实现Mysql主从,读写分离 一.Docker文件编排 二.配置主从复制 2.1 配置master 2.2 配置slave 三.验证主从复制 3.1 mas ...

  5. web容器启动顺序

    web容器启动顺序: 第一:context-param 第二:Listerer 第三:Filter 第四:servlet

  6. docker容器启动几分钟之后自动退出

    2018-11-06 问题: docker容器启动几分钟之后自动退出 log日志报错 WARNING: overlay2: the backing xfs filesystem is formatte ...

  7. 解决docker容器启动时候无法映射端口的问题

    当我们停止防火墙后,docker容器启动映射端口可能无法映射端口,这个时候需要重建docker0网桥. 详细的错误是这样的: docker: Error response from daemon: d ...

  8. docker容器启动后添加端口映射

    DOCKER 给运行中的容器添加映射端口 方法1 1.获得容器IP 将container_name 换成实际环境中的容器名 docker inspect `container_name` | grep ...

  9. Centos7 docker容器启动后添加端口映射

    docker容器启动后添加端口映射的两种方法: 一.通过修改防火墙策略添加端口映射 docker容器已创建好,但是想在容器内配置tomcat监控,需要新的端口去访问,但是映射时没有映射多余端口,此时, ...

随机推荐

  1. 2019牛客暑期多校训练营(第九场) D Knapsack Cryptosystem

    题目 题意: 给你n(最大36)个数,让你从这n个数里面找出来一些数,使这些数的和等于s(题目输入),用到的数输出1,没有用到的数输出0 例如:3  4 2 3 4 输出:0 0 1 题解: 认真想一 ...

  2. Nginx基础 - Nginx+Lua实现灰度发布与WAF

    1.Nginx加载Lua环境默认情况下Nginx不支持Lua模块, 需要安装LuaJIT解释器, 并且需要重新编译Nginx, 建议使用openrestry 1)环境准备 [root@localhos ...

  3. Nginx location相关配置说明

    Nginx location相关配置说明       基于不同的IP.不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块ngx_http_core_module实现. 新建PC web站点 [ ...

  4. 设计模式(二十三)——策略模式(Arrays源码分析)

    1 编写鸭子项目,具体要求如下: 1) 有各种鸭子(比如 野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如 叫.飞行等) 2) 显示鸭子的信息 2 传统方案解决鸭子问题的分析和代码实现 1) 传统的设计方 ...

  5. HDU 3949 XOR (线性基第k小)题解

    题意: 给出\(n\)个数,求出子集异或第\(k\)小的值,不存在输出-1. 思路: 先用线性基存所有的子集,然后对线性基每一位进行消元,保证只有\(d[i]\)的\(i\)位存在1,那么这样变成了一 ...

  6. mssql数据库提权(xp_cmdshell)

    1.关于 "xp_cmdshell" "存储过程":其实质就是一个"集合",那么是什么样的结合呢,就是存储在SqlServer中预先定义好的 ...

  7. css scroll text without wrap & webkit-scrollbar

    css scroll text without wrap hidden webkit-scrollbar .tabs-title-box::-webkit-scrollbar, .tabs-conte ...

  8. API & YApi

    API & YApi 接口管理服务 YApi http://yapi.demo.qunar.com/ https://ued.qunar.com/ build bug https://gith ...

  9. React vs Vue in 2020

    React vs Vue in 2020 技术选型 React // UserProfile.jsx function UserProfile({id, showAvatar, onFollowCli ...

  10. POSIX cron & schedule

    POSIX cron & schedule https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#ta ...