Detailed explanation of Shell script controlling docker container startup sequence

  • 2021-10-13 09:12:38
  • OfStack

1. Problems encountered

In the process of distributed project deployment, it is often required that applications (including databases) can be automatically restored after the server is restarted. Although using docker update --restart=always containerid The container can be automatically started with docker, but it cannot be guaranteed to start after the database is started. If the database is not started, it will lead to application startup failure; Another solution on the Internet is to control the startup sequence through docker-compose container arrangement, which is less studied by this blogger.

2. Solutions

Using Shell script control, the idea is roughly as follows

After the database is started successfully, the ports of the configuration center and the service registry center are probed to verify whether the database is started successfully. When the database and the configuration center are started, other micro-service applications are started again.

3. Port probing

The command used for port probing is

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

host: ip for the target host

port: Port on which the service listens

This command returns 200 if the service is started, and null if it is not started.

4. Shell script

The code is pasted directly, and the configuration center used is nacos


#!/bin/bash
#chkconfig: 2345 80 90
#description:autoStartMaintenanceService.sh
#
# Premise :
#1.docker Must be able to boot and start 
#2.docker Able to start operation and maintenance services normally 
#3. This script must run on the machine where the microservice is located 
#
## Configuration that needs to be modified ----- Begin 
## The machine where the database is located IP
DATABASE_HOST=192.169.1.52
## Port on which the database listens 
DATABASE_PORT=3306
## The machine where the microservice is located IP
LOCAL_HOST=192.169.1.46
## Microservice access port 
Maintenance_Port=8180
##NACOS Of the machine where it is located ip
NACOS_HOST=192.169.1.82
##NACOS Listening port of 
NACOS_PORT=8848
## Microservice container name (NAMES Column )
Maintenance_Container_Name="umc-maintenance"
## The log path generated by this script 
Log_Path=/home/test/log
## Configuration that needs to be modified ----- End 
##
## Cyclic delay time (s) Seconds 
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 the log path does not exist, create 
 if [ ! -d "$Log_Path" ]; then
  mkdir -p $Log_Path
 fi

 while true; do
  ## Determine whether the database is started 
  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
}
## Judge Nacos Whether to start 
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
}

## Start micro-service 
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 input and output redirection

When writing this script, it also makes bloggers more familiar with Shell input and output redirection

1 Typically, each Unix/Linux command runs with three files open:

Standard input file (stdin): The file descriptor for stdin is 0, and the Unix program reads data from stdin by default. Standard output file (stdout): The file descriptor of stdout is 1, and the Unix program outputs data to stdout by default. Standard error file (stderr): stderr has a file descriptor of 2, and the Unix program writes error messages to the stderr stream.

Command description
command > file redirects output to file and overrides file
command < file redirects input to file
command > > file redirects the output to file as an append
command 2 > file outputs errors to file and overwrites file
command 2 > > file redirects errors as appends to file
< < tag takes the contents between the opening tag tag and the closing tag tag as input

If you want to merge stdout and stderr and redirect them to file (that is, output both correct and error information to file), you can write this:


command > file 2>&1
 Or 
command >> file 2>&1

/dev/null File

/dev/null is a special file, and the contents written to it will be discarded; If you try to read from the file, you can't read anything. However, the/dev/null file is very useful, and redirecting the output of the command to it will have the effect of prohibiting the output

command > /dev/null 2>&1 stdout and stderr can be masked

Reference

Rookie Tutorial-Shell


Related articles: