详解Shell脚本控制docker容器启动顺序

1.遇到的问题

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

2.解决思路

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

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

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容器启动顺序的文章就介绍到这了,更多相关Shell脚本控制docker内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 在宿主机上执行docker容器内部的shell或程序方式

    为了避免反复进入docker容器内部操作,可以将一系列容器内部的指令由宿主机来操作完成. 在宿主机(作者主机为windows7)上执行centos容器(name为centos-1)中/usr目录下的"printer"可执行程序,该程序输出为打印"123". C:\Users\Administrator>docker exec -it centos-1 /bin/bash -c "cd usr && ./printer" 12

  • Docker容器中运行flume及启动不输出运行日志问题

    flume配置文件如下: # Name the components on this agent app1.sources = r1 app1.sinks = k1 app1.channels = c1 # Describe/configure the source app1.sources.r1.type = avro app1.sources.r1.bind = 0.0.0.0 app1.sources.r1.port = 44444 # Describe the sink #a1.sink

  • 如何解决docker容器启动失败

    问题:电脑重启之后,docker里面的mysql容器重启不了,不知道是什么原因 上面的步骤:如果sudo docker start name 能重新启动,也就是输入:docker ps 能看到自己所需要的服务已经开启,那就不需要再进行下面的步骤了,如果刚好像上面那样,那就接着看下文: 解决办法:删除启动不了的容器,然后再重新运行镜像. 注意此时的容器名已经变为mysql了,为关闭状态,再运行镜像时还是运行不了,但此时再启动镜像时就可以启动了 内容补充 1.查看docker占用的挂载点 cat /

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

    概要 网上有许多人在查找关于容器启动后能否进行端口映射的问题.我曾经也问过度娘,很遗憾我没找到.本文就这个问题给出一个解决方法,旨在抛砖引玉.本文的思路是使用iptables的端口转发,这也是docker端口映射内部的实现机制,只不过我是显示地写出来罢了,为的就是让查找这个问题的人对docker的端口映射有一个直观的了解. 结论:容器启动后是可以添加端口映射的,但不建议手工添加,最好使用docker提供的功能. 步骤 创建两个容器并进行了端口映射,结果如图所示: 假如,我start一个容器,其内

  • 使用Shell脚本批量启停Docker服务

    最近日常测试中经常需要手动启动或停止docker,于是决定写一个Shell脚本来代替人工操作,另外该脚本,也可以通过Python脚本实行远程调用,详细如下所示: 目前该脚本是将Container ID写死在脚本中,当然也可以通过传参给脚本来进行控制,大家可以改造一下. 启动docker 启动脚本详细如下所示: #!/bin/bash containerIDs="ad3e4d7fc407 a228730a915f ad3e4d7fc4099" statusLived="live

  • 详解docker中使用systemctl启动服务报错的解决办法

    docker版本: [root@localhost gae_proxy]# docker version Client: Version: 1.10.3 API version: 1.22 Package version: docker-common-1.10.3-46.el7.centos.10.x86_64 Go version: go1.6.3 Git commit: d381c64-unsupported Built: Thu Aug 4 13:21:17 2016 OS/Arch: l

  • Docker容器内应用服务自启动的方法示例

    如果想把Docker容器内的应用服务随着容器开启时自启动.只需要将服务启动的脚本写在Dockerfile里,然后用Dockerfile重构镜像即可实现: 编写应用服务自启动脚本 编写Dockerfile 重构镜像 开启容器 编写服务自启动脚本(dockerd) (tomcat为例) #!/bin/bash # # # # chkconfig: 345 98 30 # description: tomcat program. # processname: tomcat # Source funct

  • 详解Shell脚本控制docker容器启动顺序

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

  • 详解shell脚本中的case条件语句介绍和使用案例

    #前言:这篇我们接着写shell的另外一个条件语句case,上篇讲解了if条件语句.case条件语句我们常用于实现系统服务启动脚本等场景,case条件语句也相当于if条件语句多分支结构,多个选择,case看起来更规范和易读 #case条件语句的语法格式 case "变量" in 值1) 指令1... ;; 值2) 指令2... ;; *) 指令3... esac #说明:当变量的值等于1时,那么就会相应的执行指令1的相关命令输出,值等于2时就执行指令2的命令,以此类推,如果都不符合的话

  • 详解Shell脚本中^M的问题和解决方案

    目录 ^M 是什么? 本质原因 常用工具 在开发过程中,有时候不小心将Windows本地创建的shell脚本(以 .sh 结尾的脚本),传到linux系统中,通过 vi或者view命令查看文件时,发现在末尾发现出现了很多^M字符. ^M 是什么? 这个字符就是换行符.是由于跨平台解析的原因.因为window和Linux下对行尾的换行的定义不同Windows: \r\nLinux/Unix: \nMac: \r 例子 出现的原因:在DOS/Windows里,文本文件的换行符为\r\n,而在nix系

  • 详解shell脚本[] [[]] -n -z 的含义解析

    在写脚本的时候,总是搞不懂[] [[]]的区别,这次写一个总结,把它掌握牢固 []和test 两者是一样的,在命令行里test expr和[ expr ]的效果相同. test的三个基本作用是判断文件.判断字符串.判断整数.支持使用 "与或非" 将表达式连接起来. test中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq, -gt这种形式. 无论是字符串比较还是整数比较都千万不要使用大于号小于号.当然,如果你实在想用也是可以的,对于字

  • 详解Shell脚本中调用另一个Shell脚本的三种方式

    主要以下有几种方式: Command Explanation fork 新开一个子 Shell 执行,子 Shell 可以从父 Shell 继承环境变量,但是子 Shell 中的环境变量不会带回给父 Shell. exec 在同一个 Shell 内执行,但是父脚本中 exec 行之后的内容就不会再执行了 source 在同一个 Shell 中执行,在被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用,相当于合并两个脚本在执行. 第一种:fork 特点:会生成子PID而且可重复被

  • 详解Shell 脚本中 “$” 符号的多种用法

    通常情况下,在工作中用的最多的有如下几项: $0:Shell 的命令本身 1到9:表示 Shell 的第几个参数 $? :显示最后命令的执行情况 $#:传递到脚本的参数个数 $$:脚本运行的当前进程 ID 号 $*:以一个单字符串显示所有向脚本传递的参数 $!:后台运行的最后一个进程的 ID 号 $-:显示 Shell 使用的当前选项 ...... 今天将通过以上几种选项并做进一步的操作案例: 1.引用变量 引用变量时,使用 $ 符号直接来进行引用,以及包括循环变量: [root@localho

  • 一文详解Spring如何控制Bean注入的顺序

    目录 简介 构造方法依赖(推荐) @DependsOn(不推荐) BeanPostProcessor(不推荐) 简介 说明 本文介绍Spring如何控制Bean注入的顺序. 首先需要说明的是:在Bean上加@Order(xxx)是无法控制bean注入的顺序的! 控制bean的加载顺序的方法 1.构造方法依赖 2.@DependsOn 注解 3.BeanPostProcessor 扩展 Bean初始化顺序与类加载顺序基本一致:静态变量/语句块=> 实例变量或初始化语句块=> 构造方法=>

  • 详解挂载运行的docker容器中如何挂载文件系统

    前言 感觉最近很多人都在问docker相关的问题,关于怎么操作一个已经启动的docker容器的文件系统,首先我发现这非常困难,因为 mnt的命名空间. 为了登录进入一个已经启动的docker容器,我们需要这么做: 使用nsenter来在临时挂载点上挂载整个docker容器的文件系统. 创建一个特定目录的绑定挂载来当作卷来使用. 卸载临时挂载. 好吧,开始实践. 启动一个名为charlie的docker实例: $ docker run --name charlie -ti ubuntu bash

  • 详解利用ELK搭建Docker容器化应用日志中心

    概述 应用一旦容器化以后,需要考虑的就是如何采集位于Docker容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 收集.本文即将阐述如何利用ELK日志中心来收集容器化应用程序所产生的日志,并且可以用可视化的方式对日志进行查询与分析,其架构如下图所示: 架构图 镜像准备 镜像准备 ElasticSearch镜像 Logstash镜像 Kibana镜像 Nginx镜像(作为容器化应用来生产日志) 开启Linux系统Rsyslog服务 修改Rsyslog服务配置文件: v

  • 详解shell脚本的编写规范

    编写shell脚本的一些规范 解释器 shell脚本一般选择bash作为解释器,脚本开头应为 #!/bin/bash 或 #!/bin/sh 添加脚本版本和注释功能 在脚本的开头加注释,说明脚本作者.编写时间.脚本功能,最好可以加上脚本的版本号.shell中脚本注释用#,注释语句和#号之间有一个空格 #!/bin/bash # 脚本版本 # 脚本作者 # 脚本时间 # 脚本功能 添加脚本调试 通过set命令添加脚本调试,如果报错,脚本直接退出,不继续执行,对于管道错误也可以直接退出 #!/bin

随机推荐