[feature](docker)Refactor Image build script (#16528)
Co-authored-by: Yijia Su <suyijia@selectdb.com>
This commit is contained in:
@ -35,6 +35,8 @@ RUN apt-get update && \
|
||||
mv apache-doris-be-x.x.x-bin-x86_64 /opt/apache-doris/be
|
||||
|
||||
ADD resource/init_be.sh /opt/apache-doris/be/bin
|
||||
ADD resource/entry_point.sh /usr/local/bin
|
||||
RUN chmod 755 /usr/local/bin/entry_point.sh
|
||||
RUN chmod 755 /opt/apache-doris/be/bin/init_be.sh
|
||||
|
||||
ENTRYPOINT ["/opt/apache-doris/be/bin/init_be.sh"]
|
||||
ENTRYPOINT ["bash","entry_point.sh"]
|
||||
|
||||
184
docker/runtime/be/resource/entry_point.sh
Normal file
184
docker/runtime/be/resource/entry_point.sh
Normal file
@ -0,0 +1,184 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
set -eo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
# Obtain necessary and basic information to complete initialization
|
||||
|
||||
# logging functions
|
||||
# usage: doris_[note|warn|error] $log_meg
|
||||
# ie: doris_warn "task may be risky!"
|
||||
# out: 2023-01-08T19:08:16+08:00 [Warn] [Entrypoint]: task may be risky!
|
||||
doris_log() {
|
||||
local type="$1"
|
||||
shift
|
||||
# accept argument string or stdin
|
||||
local text="$*"
|
||||
if [ "$#" -eq 0 ]; then text="$(cat)"; fi
|
||||
local dt="$(date -Iseconds)"
|
||||
printf '%s [%s] [Entrypoint]: %s\n' "$dt" "$type" "$text"
|
||||
}
|
||||
doris_note() {
|
||||
doris_log Note "$@"
|
||||
}
|
||||
doris_warn() {
|
||||
doris_log Warn "$@" >&2
|
||||
}
|
||||
doris_error() {
|
||||
doris_log ERROR "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check to see if this file is being run or sourced from another script
|
||||
_is_sourced() {
|
||||
[ "${#FUNCNAME[@]}" -ge 2 ] &&
|
||||
[ "${FUNCNAME[0]}" = '_is_sourced' ] &&
|
||||
[ "${FUNCNAME[1]}" = 'source' ]
|
||||
}
|
||||
|
||||
docker_setup_env() {
|
||||
declare -g DATABASE_ALREADY_EXISTS
|
||||
if [ -d "${DORIS_HOME}/be/storage/data" ]; then
|
||||
DATABASE_ALREADY_EXISTS='true'
|
||||
fi
|
||||
}
|
||||
|
||||
get_doris_args() {
|
||||
local feServerArray=($(echo "${FE_SERVERS}" | awk '{gsub (/,/," "); print $0}'))
|
||||
for i in "${feServerArray[@]}"; do
|
||||
val=${i}
|
||||
val=${val// /}
|
||||
tmpFeId=$(echo "${val}" | awk -F ':' '{ sub(/fe/, ""); sub(/ /, ""); print$1}')
|
||||
tmpFeIp=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
feIpArray[$tmpFeId]=${tmpFeIp}
|
||||
done
|
||||
|
||||
declare -g MASTER_FE_IP BE_HOST_IP BE_HEARTBEAT_PORT
|
||||
MASTER_FE_IP=${feIpArray[1]}
|
||||
doris_note "masterFe = ${MASTER_FE_IP}"
|
||||
BE_HOST_IP=$(echo "${BE_ADDR}" | awk -F ':' '{ sub(/ /, ""); print$1}')
|
||||
BE_HEARTBEAT_PORT=$(echo "${BE_ADDR}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
doris_note "be_addr = ${BE_HOST_IP}:${BE_HEARTBEAT_PORT}"
|
||||
}
|
||||
|
||||
# Execute sql script, passed via stdin
|
||||
# usage: docker_process_sql [mysql-cli-args]
|
||||
# ie: docker_process_sql --database=mydb <<<'INSERT ...'
|
||||
# ie: docker_process_sql --database=mydb <my-file.sql
|
||||
docker_process_sql() {
|
||||
set +e
|
||||
mysql -uroot -P9030 -h${MASTER_FE_IP} --comments "$@" 2>/dev/null
|
||||
}
|
||||
|
||||
check_be_status() {
|
||||
set +e
|
||||
local is_fe_start=false
|
||||
for i in {1..300}; do
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_warn "start check be status~"
|
||||
fi
|
||||
docker_process_sql <<<"show backends;" | grep "[[:space:]]${BE_HOST_IP}[[:space:]]" | grep "[[:space:]]${BE_HEARTBEAT_PORT}[[:space:]]" | grep "[[:space:]]true[[:space:]]"
|
||||
be_join_status=$?
|
||||
if [[ "${be_join_status}" == 0 ]]; then
|
||||
doris_note "Verify that BE is registered to FE successfully"
|
||||
is_fe_start=true
|
||||
break
|
||||
else
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_note "register is failed, wait next~"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if ! [[ $is_fe_start ]]; then
|
||||
doris_error "Failed to register BE to FE!Tried 30 times!Maybe FE Start Failed!"
|
||||
fi
|
||||
}
|
||||
|
||||
# usage: docker_process_init_files [file [file [...]]]
|
||||
# ie: docker_process_init_files /always-initdb.d/*
|
||||
# process initializer files, based on file extensions
|
||||
docker_process_init_files() {
|
||||
local f
|
||||
for f; do
|
||||
case "$f" in
|
||||
*.sh)
|
||||
if [ -x "$f" ]; then
|
||||
doris_note "$0: running $f"
|
||||
"$f"
|
||||
else
|
||||
doris_note "$0: sourcing $f"
|
||||
. "$f"
|
||||
fi
|
||||
;;
|
||||
*.sql)
|
||||
doris_note "$0: running $f"
|
||||
docker_process_sql <"$f"
|
||||
echo
|
||||
;;
|
||||
*.sql.bz2)
|
||||
doris_note "$0: running $f"
|
||||
bunzip2 -c "$f" | docker_process_sql
|
||||
echo
|
||||
;;
|
||||
*.sql.gz)
|
||||
doris_note "$0: running $f"
|
||||
gunzip -c "$f" | docker_process_sql
|
||||
echo
|
||||
;;
|
||||
*.sql.xz)
|
||||
doris_note "$0: running $f"
|
||||
xzcat "$f" | docker_process_sql
|
||||
echo
|
||||
;;
|
||||
*.sql.zst)
|
||||
doris_note "$0: running $f"
|
||||
zstd -dc "$f" | docker_process_sql
|
||||
echo
|
||||
;;
|
||||
*) doris_warn "$0: ignoring $f" ;;
|
||||
esac
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
_main() {
|
||||
docker_setup_env
|
||||
# get init args
|
||||
get_doris_args
|
||||
# Start Doris BE
|
||||
{
|
||||
set +e
|
||||
bash init_be.sh 2>/dev/null
|
||||
} &
|
||||
# check BE started status
|
||||
check_be_status
|
||||
if [ -z ${DATABASE_ALREADY_EXISTS} ]; then
|
||||
# run script
|
||||
docker_process_init_files /docker-entrypoint-initdb.d/*
|
||||
fi
|
||||
|
||||
# keep BE started status
|
||||
wait
|
||||
exec "$@"
|
||||
}
|
||||
|
||||
if ! _is_sourced; then
|
||||
_main "$@"
|
||||
fi
|
||||
@ -16,90 +16,198 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
FE_SERVERS=""
|
||||
BE_ADDR=""
|
||||
set -eo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
ARGS=$(getopt -o -h: --long fe_servers:,be_addr: -n "$0" -- "$@")
|
||||
DORIS_HOME="/opt/apache-doris"
|
||||
|
||||
eval set -- "${ARGS}"
|
||||
# Obtain necessary and basic information to complete initialization
|
||||
|
||||
while [[ -n "$1" ]]; do
|
||||
case "$1" in
|
||||
--fe_servers)
|
||||
FE_SERVERS=$2
|
||||
shift
|
||||
;;
|
||||
--be_addr)
|
||||
BE_ADDR=$2
|
||||
shift
|
||||
;;
|
||||
--) ;;
|
||||
|
||||
*)
|
||||
echo "Error option $1"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
# logging functions
|
||||
# usage: doris_[note|warn|error] $log_meg
|
||||
# ie: doris_warn "task may be risky!"
|
||||
# out: 2023-01-08T19:08:16+08:00 [Warn] [Entrypoint]: task may be risky!
|
||||
doris_log() {
|
||||
local type="$1"
|
||||
shift
|
||||
done
|
||||
# accept argument string or stdin
|
||||
local text="$*"
|
||||
if [ "$#" -eq 0 ]; then text="$(cat)"; fi
|
||||
local dt="$(date -Iseconds)"
|
||||
printf '%s [%s] [Entrypoint]: %s\n' "$dt" "$type" "$text"
|
||||
}
|
||||
doris_note() {
|
||||
doris_log Note "$@"
|
||||
}
|
||||
doris_warn() {
|
||||
doris_log Warn "$@" >&2
|
||||
}
|
||||
doris_error() {
|
||||
doris_log ERROR "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
#echo FE_SERVERS = $FE_SERVERS
|
||||
echo "DEBUG >>>>>> FE_SERVERS=[${FE_SERVERS}]"
|
||||
echo "DEBUG >>>>>> BE_ADDR=[${BE_ADDR}]"
|
||||
# check to see if this file is being run or sourced from another script
|
||||
_is_sourced() {
|
||||
[ "${#FUNCNAME[@]}" -ge 2 ] &&
|
||||
[ "${FUNCNAME[0]}" = '_is_sourced' ] &&
|
||||
[ "${FUNCNAME[1]}" = 'source' ]
|
||||
}
|
||||
|
||||
feIpArray=()
|
||||
feEditLogPortArray=()
|
||||
|
||||
IFS=","
|
||||
# shellcheck disable=SC2206
|
||||
feServerArray=(${FE_SERVERS})
|
||||
|
||||
for i in "${!feServerArray[@]}"; do
|
||||
val=${feServerArray[i]}
|
||||
val=${val// /}
|
||||
tmpFeId=$(echo "${val}" | awk -F ':' '{ sub(/fe/, ""); sub(/ /, ""); print$1}')
|
||||
tmpFeIp=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
tmpFeEditLogPort=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$3}')
|
||||
feIpArray[tmpFeId]=${tmpFeIp}
|
||||
feEditLogPortArray[tmpFeId]=${tmpFeEditLogPort}
|
||||
done
|
||||
|
||||
be_ip=$(echo "${BE_ADDR}" | awk -F ':' '{ sub(/ /, ""); print$1}')
|
||||
be_heartbeat_port=$(echo "${BE_ADDR}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
|
||||
echo "DEBUG >>>>>> feIpArray = ${feIpArray[*]}"
|
||||
echo "DEBUG >>>>>> feEditLogPortArray = ${feEditLogPortArray[*]}"
|
||||
echo "DEBUG >>>>>> masterFe = ${feIpArray[1]}:${feEditLogPortArray[1]}"
|
||||
echo "DEBUG >>>>>> be_addr = ${be_ip}:${be_heartbeat_port}"
|
||||
|
||||
priority_networks=$(echo "${be_ip}" | awk -F '.' '{print$1"."$2"."$3".0/24"}')
|
||||
echo "DEBUG >>>>>> Append the configuration [priority_networks = ${priority_networks}] to /opt/apache-doris/be/conf/fe.conf"
|
||||
echo "priority_networks = ${priority_networks}" >>/opt/apache-doris/be/conf/be.conf
|
||||
|
||||
registerMySQL="mysql -uroot -P9030 -h${feIpArray[1]} -e \"alter system add backend '${be_ip}:${be_heartbeat_port}'\""
|
||||
echo "DEBUG >>>>>> registerMySQL = ${registerMySQL}"
|
||||
|
||||
registerShell="/opt/apache-doris/be/bin/start_be.sh &"
|
||||
echo "DEBUG >>>>>> registerShell = ${registerShell}"
|
||||
|
||||
for ((i = 0; i <= 20; i++)); do
|
||||
|
||||
## check be register status
|
||||
echo "mysql -uroot -P9030 -h${feIpArray[1]} -e \"show backends\" | grep \" ${be_ip} \" | grep \" ${be_heartbeat_port} \""
|
||||
mysql -uroot -P9030 -h"${feIpArray[1]}" -e "show backends" | grep "[[:space:]]${be_ip}[[:space:]]" | grep "[[:space:]]${be_heartbeat_port}[[:space:]]"
|
||||
be_join_status=$?
|
||||
echo "DEBUG >>>>>> The " "${i}" "time to register BE node, be_join_status=${be_join_status}"
|
||||
if [[ "${be_join_status}" == 0 ]]; then
|
||||
## be registe successfully
|
||||
echo "DEBUG >>>>>> run command ${registerShell}"
|
||||
eval "${registerShell}"
|
||||
else
|
||||
## be doesn't registe
|
||||
echo "DEBUG >>>>>> run commnad ${registerMySQL}"
|
||||
eval "${registerMySQL}"
|
||||
if [[ "${i}" == 20 ]]; then
|
||||
echo "DEBUG >>>>>> BE Start Or Register FAILED!"
|
||||
fi
|
||||
sleep 5
|
||||
docker_setup_env() {
|
||||
declare -g DATABASE_ALREADY_EXISTS
|
||||
if [ -d "${DORIS_HOME}/be/storage/data" ]; then
|
||||
DATABASE_ALREADY_EXISTS='true'
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Check the variables required for startup
|
||||
docker_required_variables_env() {
|
||||
if [[ $FE_SERVERS =~ ^.+:[1-2]{0,1}[0-9]{0,1}[0-9]{1}(\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}){3}:[1-6]{0,1}[0-9]{1,4}(,.+:[1-2]{0,1}[0-9]{0,1}[0-9]{1}(\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}){3}:[1-6]{0,1}[0-9]{1,4})*$ ]]; then
|
||||
doris_warn "FE_SERVERS" $FE_SERVERS
|
||||
else
|
||||
doris_error "FE_SERVERS rule error!example: \$FE_NAME:\$FE_HOST_IP:\$FE_EDIT_LOG_PORT[,\$FE_NAME:\$FE_HOST_IP:\$FE_EDIT_LOG_PORT]..."
|
||||
fi
|
||||
if [[ $BE_ADDR =~ ^[1-2]{0,1}[0-9]{0,1}[0-9]{1}(\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}){3}:[1-6]{0,1}[0-9]{1,4}$ ]]; then
|
||||
doris_warn "BE_ADDR" $BE_ADDR
|
||||
else
|
||||
doris_error "BE_ADDR rule error!example: \$BE_HOST_IP:\$HEARTBEAT_SERVICE_PORT"
|
||||
fi
|
||||
}
|
||||
|
||||
get_doris_be_args() {
|
||||
local feServerArray=($(echo "${FE_SERVERS}" | awk '{gsub (/,/," "); print $0}'))
|
||||
for i in "${feServerArray[@]}"; do
|
||||
val=${i}
|
||||
val=${val// /}
|
||||
tmpFeId=$(echo "${val}" | awk -F ':' '{ sub(/fe/, ""); sub(/ /, ""); print$1}')
|
||||
tmpFeIp=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
tmpFeEditLogPort=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$3}')
|
||||
check_arg "tmpFeIp" $tmpFeIp
|
||||
feIpArray[$tmpFeId]=${tmpFeIp}
|
||||
check_arg "tmpFeEditLogPort" $tmpFeEditLogPort
|
||||
feEditLogPortArray[$tmpFeId]=${tmpFeEditLogPort}
|
||||
done
|
||||
|
||||
declare -g MASTER_FE_IP BE_HOST_IP BE_HEARTBEAT_PORT PRIORITY_NETWORKS
|
||||
MASTER_FE_IP=${feIpArray[1]}
|
||||
check_arg "MASTER_FE_IP" $MASTER_FE_IP
|
||||
BE_HOST_IP=$(echo "${BE_ADDR}" | awk -F ':' '{ sub(/ /, ""); print$1}')
|
||||
check_arg "BE_HOST_IP" $BE_HOST_IP
|
||||
BE_HEARTBEAT_PORT=$(echo "${BE_ADDR}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
check_arg "BE_HEARTBEAT_PORT" $BE_HEARTBEAT_PORT
|
||||
|
||||
PRIORITY_NETWORKS=$(echo "${BE_HOST_IP}" | awk -F '.' '{print$1"."$2"."$3".0/24"}')
|
||||
check_arg "priority_networks" $PRIORITY_NETWORKS
|
||||
|
||||
doris_note "feIpArray = ${feIpArray[*]}"
|
||||
doris_note "feEditLogPortArray = ${feEditLogPortArray[*]}"
|
||||
doris_note "masterFe = ${feIpArray[1]}:${feEditLogPortArray[1]}"
|
||||
doris_note "be_addr = ${BE_HOST_IP}:${BE_HEARTBEAT_PORT}"
|
||||
doris_note "priority_networks = ${PRIORITY_NETWORKS}"
|
||||
# wait fe start
|
||||
check_be_status true
|
||||
}
|
||||
|
||||
add_priority_networks() {
|
||||
doris_note "add priority_networks ${1} to ${DORIS_HOME}/be/conf/be.conf"
|
||||
echo "priority_networks = ${1}" >>${DORIS_HOME}/be/conf/be.conf
|
||||
}
|
||||
|
||||
# Execute sql script, passed via stdin
|
||||
# usage: docker_process_sql sql_script
|
||||
docker_process_sql() {
|
||||
set +e
|
||||
mysql -uroot -P9030 -h${MASTER_FE_IP} --comments "$@" >2 &
|
||||
1>/dev/null
|
||||
}
|
||||
|
||||
register_be_to_fe() {
|
||||
set +e
|
||||
# check fe status
|
||||
local is_fe_start=false
|
||||
for i in {1..300}; do
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_note "Register BE to FE is failed. retry."
|
||||
fi
|
||||
docker_process_sql <<<"alter system add backend '${BE_HOST_IP}:${BE_HEARTBEAT_PORT}'"
|
||||
register_be_status=$?
|
||||
if [[ $register_be_status == 0 ]]; then
|
||||
doris_note "BE successfully registered to FE!"
|
||||
is_fe_start=true
|
||||
break
|
||||
else
|
||||
check_be_status
|
||||
if [ -n "$BE_ALREADY_EXISTS" ]; then
|
||||
doris_warn "Same backend already exists! No need to register again!"
|
||||
break
|
||||
fi
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_warn "register_be_status: ${register_be_status}"
|
||||
doris_warn "BE failed registered to FE!"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if ! [[ $is_fe_start ]]; then
|
||||
doris_error "Failed to register BE to FE!Tried 30 times!Maybe FE Start Failed!"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check whether the passed parameters are empty to avoid subsequent task execution failures. At the same time,
|
||||
# enumeration checks can be added, such as checking whether a certain parameter appears repeatedly, etc.
|
||||
check_arg() {
|
||||
if [ -z $2 ]; then
|
||||
doris_error "$1 is null!"
|
||||
fi
|
||||
}
|
||||
|
||||
# 这里可用 docker_process_sql() 函数封装,为了方便调试,暂未封装
|
||||
check_be_status() {
|
||||
set +e
|
||||
for i in {1..300}; do
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
if [[ $1 == true ]]; then
|
||||
doris_note "MASTER FE is not started. retry."
|
||||
else
|
||||
doris_note "BE is not register. retry."
|
||||
fi
|
||||
fi
|
||||
if [[ $1 == true ]]; then
|
||||
docker_process_sql <<<"show frontends" | grep "[[:space:]]${MASTER_FE_IP}[[:space:]]"
|
||||
else
|
||||
docker_process_sql <<<"show backends" | grep "[[:space:]]${BE_HOST_IP}[[:space:]]" | grep "[[:space:]]${BE_HEARTBEAT_PORT}[[:space:]]"
|
||||
fi
|
||||
be_join_status=$?
|
||||
if [[ "${be_join_status}" == 0 ]]; then
|
||||
if [[ $1 == true ]]; then
|
||||
doris_note "MASTER FE is started!"
|
||||
else
|
||||
doris_note "Init Check - Verify that BE is registered to FE successfully"
|
||||
BE_ALREADY_EXISTS=true
|
||||
fi
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
_main() {
|
||||
docker_setup_env
|
||||
docker_required_variables_env
|
||||
get_doris_be_args
|
||||
|
||||
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
|
||||
add_priority_networks $PRIORITY_NETWORKS
|
||||
fi
|
||||
|
||||
register_be_to_fe
|
||||
check_be_status
|
||||
doris_note "Ready to start BE!"
|
||||
start_be.sh
|
||||
exec "$@"
|
||||
}
|
||||
|
||||
if ! _is_sourced; then
|
||||
_main "$@"
|
||||
fi
|
||||
|
||||
@ -16,111 +16,224 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
FE_ID=0
|
||||
FE_SERVERS=""
|
||||
set -eo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
ARGS=$(getopt -o -h: --long fe_id:,fe_servers: -n "$0" -- "$@")
|
||||
DORIS_HOME="/opt/apache-doris"
|
||||
|
||||
eval set -- "${ARGS}"
|
||||
# Obtain necessary and basic information to complete initialization
|
||||
|
||||
while [[ -n "$1" ]]; do
|
||||
case "$1" in
|
||||
--fe_id)
|
||||
FE_ID=$2
|
||||
shift
|
||||
;;
|
||||
--fe_servers)
|
||||
FE_SERVERS=$2
|
||||
shift
|
||||
;;
|
||||
--) ;;
|
||||
|
||||
*)
|
||||
echo "Error option $1"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
# logging functions
|
||||
# usage: doris_[note|warn|error] $log_meg
|
||||
# ie: doris_warn "task may fe risky!"
|
||||
# out: 2023-01-08T19:08:16+08:00 [Warn] [Entrypoint]: task may fe risky!
|
||||
doris_log() {
|
||||
local type="$1"
|
||||
shift
|
||||
done
|
||||
# accept argument string or stdin
|
||||
local text="$*"
|
||||
if [ "$#" -eq 0 ]; then text="$(cat)"; fi
|
||||
local dt="$(date -Iseconds)"
|
||||
printf '%s [%s] [Entrypoint]: %s\n' "$dt" "$type" "$text"
|
||||
}
|
||||
doris_note() {
|
||||
doris_log Note "$@"
|
||||
}
|
||||
doris_warn() {
|
||||
doris_log Warn "$@" >&2
|
||||
}
|
||||
doris_error() {
|
||||
doris_log ERROR "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "DEBUG >>>>>> FE_ID = [${FE_ID}]"
|
||||
echo "DEBUG >>>>>> FE_SERVERS = [${FE_SERVERS}]"
|
||||
# check to see if this file is being run or sourced from another script
|
||||
_is_sourced() {
|
||||
[ "${#FUNCNAME[@]}" -ge 2 ] &&
|
||||
[ "${FUNCNAME[0]}" = '_is_sourced' ] &&
|
||||
[ "${FUNCNAME[1]}" = 'source' ]
|
||||
}
|
||||
|
||||
feIpArray=()
|
||||
feEditLogPortArray=()
|
||||
docker_setup_env() {
|
||||
declare -g DATABASE_ALREADY_EXISTS
|
||||
if [ -d "${DORIS_HOME}/fe/doris-meta/image" ]; then
|
||||
DATABASE_ALREADY_EXISTS='true'
|
||||
fi
|
||||
}
|
||||
|
||||
IFS=","
|
||||
# shellcheck disable=SC2206
|
||||
feServerArray=(${FE_SERVERS})
|
||||
# Check the variables required for startup
|
||||
docker_required_variables_env() {
|
||||
if [[ $FE_SERVERS =~ ^.+:[1-2]{0,1}[0-9]{0,1}[0-9]{1}(\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}){3}:[1-6]{0,1}[0-9]{1,4}(,.+:[1-2]{0,1}[0-9]{0,1}[0-9]{1}(\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}){3}:[1-6]{0,1}[0-9]{1,4})*$ ]]; then
|
||||
doris_warn "FE_SERVERS" $FE_SERVERS
|
||||
else
|
||||
doris_error "FE_SERVERS rule error!example: \$FE_NAME:\$FE_HOST_IP:\$FE_EDIT_LOG_PORT[,\$FE_NAME:\$FE_HOST_IP:\$FE_EDIT_LOG_PORT]..."
|
||||
fi
|
||||
if [[ $FE_ID =~ ^[1-9]{1}$ ]]; then
|
||||
doris_warn "FE_ID" $FE_ID
|
||||
else
|
||||
doris_error "FE_ID rule error!If FE is the role of Master, please set FE_ID=1, and ensure that all IDs correspond to the IP of the current node."
|
||||
fi
|
||||
}
|
||||
|
||||
for i in "${!feServerArray[@]}"; do
|
||||
|
||||
val=${feServerArray[i]}
|
||||
val=${val// /}
|
||||
tmpFeId=$(echo "${val}" | awk -F ':' '{ sub(/fe/, ""); sub(/ /, ""); print$1}')
|
||||
tmpFeIp=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
tmpFeEditLogPort=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$3}')
|
||||
echo "DEBUG >>>>>> tmpFeId = [${tmpFeId}]"
|
||||
echo "DEBUG >>>>>> tmpFeIp = [${tmpFeIp}]"
|
||||
echo "DEBUG >>>>>> tmpFeEditLogPort = [${tmpFeEditLogPort}]"
|
||||
|
||||
feIpArray[tmpFeId]=${tmpFeIp}
|
||||
feEditLogPortArray[tmpFeId]=${tmpFeEditLogPort}
|
||||
|
||||
done
|
||||
|
||||
echo "DEBUG >>>>>> feIpArray = ${feIpArray[*]}"
|
||||
echo "DEBUG >>>>>> feEditLogPortArray = ${feEditLogPortArray[*]}"
|
||||
echo "DEBUG >>>>>> masterFe = ${feIpArray[1]}:${feEditLogPortArray[1]}"
|
||||
echo "DEBUG >>>>>> currentFe = ${feIpArray[FE_ID]}:${feEditLogPortArray[FE_ID]}"
|
||||
|
||||
priority_networks=$(echo "${feIpArray[FE_ID]}" | awk -F '.' '{print$1"."$2"."$3".0/24"}')
|
||||
echo "DEBUG >>>>>> Append the configuration [priority_networks = ${priority_networks}] to /opt/doris-fe/conf/fe.conf"
|
||||
echo "priority_networks = ${priority_networks}" >>/opt/apache-doris/fe/conf/fe.conf
|
||||
|
||||
if [[ "${FE_ID}" != 1 ]]; then
|
||||
|
||||
## if current node is not master
|
||||
## PREPARE1: registe follower from mysql client
|
||||
## PREPARE2: call start_fe.sh using --help optional
|
||||
## STEP1: check master fe service works
|
||||
## STEP2: if feMasterStat == true; register PREPARE1 & PREPARE2 [retry 3 times, sleep 10s]
|
||||
|
||||
## PREPARE1: registe follower from mysql client
|
||||
registerMySQL="mysql -uroot -P9030 -h${feIpArray[1]} -e \"alter system add follower '${feIpArray[FE_ID]}:${feEditLogPortArray[FE_ID]}'\""
|
||||
|
||||
## PREPARE2: call start_fe.sh using --help optional
|
||||
registerShell="/opt/apache-doris/fe/bin/start_fe.sh --helper '${feIpArray[1]}:${feEditLogPortArray[1]}'"
|
||||
|
||||
echo "DEBUG >>>>>> FE is follower, fe_id = ${FE_ID}"
|
||||
echo "DEBUG >>>>>> registerMySQL = 【${registerMySQL}】"
|
||||
echo "DEBUG >>>>>> registerShell = 【${registerShell}】"
|
||||
echo "DEBUG >>>>>> feMasterStat = 【mysql -uroot -P9030 -h ${feIpArray[1]} -e \"show frontends\" | grep \"${feIpArray[1]}_9010\" | grep -E \"true[[:space:]]*true\"】"
|
||||
|
||||
## STEP1: check FE master status
|
||||
|
||||
for ((i = 0; i <= 2000; i++)); do
|
||||
|
||||
## run STEP1 & STEP2, and then break
|
||||
echo "Run registerShell command, [ registerMySQL = ${registerMySQL} ]"
|
||||
eval "${registerMySQL}"
|
||||
sleep 2
|
||||
|
||||
## followerJoined: Joined = 0, doesn't join = 1
|
||||
mysql -uroot -P9030 -h"${feIpArray[1]}" -e "show frontends" | grep "${feIpArray[FE_ID]}_9010" | grep -E "false[[:space:]]*false"
|
||||
followerJoined=$?
|
||||
|
||||
if [[ "${followerJoined}" == 0 ]]; then
|
||||
echo "Run registerShell command, [ registerShell = ${registerShell} ]"
|
||||
eval "${registerShell}"
|
||||
echo "The resutl of run registerShell command, [ res = $? ]"
|
||||
fi
|
||||
sleep 5
|
||||
get_doris_fe_args() {
|
||||
local feServerArray=($(echo "${FE_SERVERS}" | awk '{gsub (/,/," "); print $0}'))
|
||||
for i in "${feServerArray[@]}"; do
|
||||
val=${i}
|
||||
val=${val// /}
|
||||
tmpFeName=$(echo "${val}" | awk -F ':' '{ sub(/fe/, ""); sub(/ /, ""); print$1}')
|
||||
tmpFeIp=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$2}')
|
||||
tmpFeEditLogPort=$(echo "${val}" | awk -F ':' '{ sub(/ /, ""); print$3}')
|
||||
check_arg "TMP_FE_NAME" $tmpFeName
|
||||
feIpArray[$tmpFeName]=${tmpFeIp}
|
||||
check_arg "TMP_FE_EDIT_LOG_PORT" $tmpFeEditLogPort
|
||||
feEditLogPortArray[$tmpFeName]=${tmpFeEditLogPort}
|
||||
done
|
||||
|
||||
else
|
||||
registerShell="/opt/apache-doris/fe/bin/start_fe.sh"
|
||||
eval "${registerShell}"
|
||||
echo "DEBUG >>>>>> FE is master, fe_id = ${FE_ID}"
|
||||
echo "DEBUG >>>>>> registerShell = ${registerShell}"
|
||||
declare -g MASTER_FE_IP CURRENT_FE_IP MASTER_FE_EDIT_PORT CURRENT_FE_EDIT_PORT PRIORITY_NETWORKS CURRENT_FE_IS_MASTER
|
||||
MASTER_FE_IP=${feIpArray[1]}
|
||||
check_arg "MASTER_FE_IP" $MASTER_FE_IP
|
||||
MASTER_FE_EDIT_PORT=${feEditLogPortArray[1]}
|
||||
check_arg "MASTER_FE_EDIT_PORT" $MASTER_FE_EDIT_PORT
|
||||
CURRENT_FE_IP=${feIpArray[FE_ID]}
|
||||
check_arg "CURRENT_FE_IP" $CURRENT_FE_IP
|
||||
CURRENT_FE_EDIT_PORT=${feEditLogPortArray[FE_ID]}
|
||||
check_arg "CURRENT_FE_EDIT_PORT" $CURRENT_FE_EDIT_PORT
|
||||
|
||||
if [ ${MASTER_FE_IP} == ${CURRENT_FE_IP} ]; then
|
||||
CURRENT_FE_IS_MASTER=true
|
||||
else
|
||||
CURRENT_FE_IS_MASTER=false
|
||||
fi
|
||||
|
||||
PRIORITY_NETWORKS=$(echo "${CURRENT_FE_IP}" | awk -F '.' '{print$1"."$2"."$3".0/24"}')
|
||||
check_arg "PRIORITY_NETWORKS" $PRIORITY_NETWORKS
|
||||
|
||||
doris_note "FE_IP_ARRAY = ${feIpArray[*]}"
|
||||
doris_note "FE_EDIT_LOG_PORT_ARRAY = ${feEditLogPortArray[*]}"
|
||||
doris_note "MASTER_FE = ${feIpArray[1]}:${feEditLogPortArray[1]}"
|
||||
doris_note "CURRENT_FE = ${CURRENT_FE_IP}:${CURRENT_FE_EDIT_PORT}"
|
||||
doris_note "PRIORITY_NETWORKS = ${PRIORITY_NETWORKS}"
|
||||
# wait fe start
|
||||
check_fe_status true
|
||||
}
|
||||
|
||||
add_priority_networks() {
|
||||
doris_note "add priority_networks ${1} to ${DORIS_HOME}/fe/conf/fe.conf"
|
||||
echo "priority_networks = ${1}" >>${DORIS_HOME}/fe/conf/fe.conf
|
||||
}
|
||||
|
||||
# Execute sql script, passed via stdin
|
||||
# usage: docker_process_sql sql_script
|
||||
docker_process_sql() {
|
||||
set +e
|
||||
mysql -uroot -P9030 -h${MASTER_FE_IP} --comments "$@" 2>/dev/null
|
||||
}
|
||||
|
||||
docker_setup_db() {
|
||||
set +e
|
||||
# check fe status
|
||||
local is_fe_start=false
|
||||
if [ ${CURRENT_FE_IS_MASTER} == true ]; then
|
||||
doris_note "Current FE is Master FE! No need to register again!"
|
||||
return
|
||||
fi
|
||||
for i in {1..300}; do
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_note "ADD FOLLOWER failed, retry."
|
||||
fi
|
||||
docker_process_sql <<<"alter system add FOLLOWER '${CURRENT_FE_IP}:${CURRENT_FE_EDIT_PORT}'"
|
||||
register_fe_status=$?
|
||||
if [[ $register_fe_status == 0 ]]; then
|
||||
doris_note "FE successfully registered!"
|
||||
is_fe_start=true
|
||||
break
|
||||
else
|
||||
check_fe_status
|
||||
if [ -n "$CURRENT_FE_ALREADY_EXISTS" ]; then
|
||||
doris_warn "Same frontend already exists! No need to register again!"
|
||||
break
|
||||
fi
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_warn "register_fe_status: ${register_fe_status}"
|
||||
doris_warn "FE failed registered!"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if ! [[ $is_fe_start ]]; then
|
||||
doris_error "Failed to register CURRENT_FE to FE!Tried 30 times!Maybe FE Start Failed!"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check whether the passed parameters are empty to avoid subsequent task execution failures. At the same time,
|
||||
# enumeration checks can fe added, such as checking whether a certain parameter appears repeatedly, etc.
|
||||
check_arg() {
|
||||
if [ -z $2 ]; then
|
||||
doris_error "$1 is null!"
|
||||
fi
|
||||
}
|
||||
|
||||
# 这里可用 docker_process_sql() 函数封装,为了方便调试,暂未封装
|
||||
check_fe_status() {
|
||||
set +e
|
||||
declare -g CURRENT_FE_ALREADY_EXISTS
|
||||
if [ ${CURRENT_FE_IS_MASTER} == true ]; then
|
||||
doris_note "Current FE is Master FE! No need check fe status!"
|
||||
return
|
||||
fi
|
||||
for i in {1..300}; do
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
doris_note "try session Master FE."
|
||||
fi
|
||||
if [[ $1 == true ]]; then
|
||||
docker_process_sql <<<"show frontends" | grep "[[:space:]]${MASTER_FE_IP}[[:space:]]" | grep "[[:space:]]${MASTER_FE_EDIT_PORT}[[:space:]]"
|
||||
else
|
||||
docker_process_sql <<<"show frontends" | grep "[[:space:]]${CURRENT_FE_IP}[[:space:]]" | grep "[[:space:]]${CURRENT_FE_EDIT_PORT}[[:space:]]"
|
||||
fi
|
||||
fe_join_status=$?
|
||||
if [[ "${fe_join_status}" == 0 ]]; then
|
||||
if [[ $1 == true ]]; then
|
||||
doris_note "Master FE is started!"
|
||||
else
|
||||
doris_note "Verify that CURRENT_FE is registered to FE successfully"
|
||||
fi
|
||||
CURRENT_FE_ALREADY_EXISTS=true
|
||||
break
|
||||
else
|
||||
if [[ $(($i % 20)) == 1 ]]; then
|
||||
if [[ $1 == true ]]; then
|
||||
doris_note "Master FE is not started, retry."
|
||||
else
|
||||
doris_warn "Verify that CURRENT_FE is registered to FE failed, retry."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
_main() {
|
||||
docker_setup_env
|
||||
docker_required_variables_env
|
||||
get_doris_fe_args
|
||||
|
||||
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
|
||||
add_priority_networks $PRIORITY_NETWORKS
|
||||
fi
|
||||
|
||||
docker_setup_db
|
||||
check_fe_status
|
||||
doris_note "Ready to start CURRENT_FE!"
|
||||
|
||||
if [ $CURRENT_FE_IS_MASTER == true ]; then
|
||||
start_fe.sh
|
||||
else
|
||||
start_fe.sh --helper ${MASTER_FE_IP}:${MASTER_FE_EDIT_PORT}
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
}
|
||||
|
||||
if ! _is_sourced; then
|
||||
_main "$@"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user