This is an automated email from the ASF dual-hosted git repository. jiafengzheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 1cc735f20b [feature](docker)Refactor Image build script (#16528) 1cc735f20b is described below commit 1cc735f20bfd06f5fa1bc22daeeba08a5c01f4af Author: FreeOnePlus <54164178+freeonep...@users.noreply.github.com> AuthorDate: Fri Feb 10 18:30:54 2023 +0800 [feature](docker)Refactor Image build script (#16528) Co-authored-by: Yijia Su <suyi...@selectdb.com> --- docker/runtime/be/Dockerfile | 4 +- docker/runtime/be/resource/entry_point.sh | 184 ++++++++++++++++++ docker/runtime/be/resource/init_be.sh | 274 ++++++++++++++++++-------- docker/runtime/fe/resource/init_fe.sh | 307 ++++++++++++++++++++---------- 4 files changed, 588 insertions(+), 181 deletions(-) diff --git a/docker/runtime/be/Dockerfile b/docker/runtime/be/Dockerfile index d4b60eec65..95eda2ca1c 100644 --- a/docker/runtime/be/Dockerfile +++ b/docker/runtime/be/Dockerfile @@ -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"] diff --git a/docker/runtime/be/resource/entry_point.sh b/docker/runtime/be/resource/entry_point.sh new file mode 100644 index 0000000000..ab2ec6a3d3 --- /dev/null +++ b/docker/runtime/be/resource/entry_point.sh @@ -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 diff --git a/docker/runtime/be/resource/init_be.sh b/docker/runtime/be/resource/init_be.sh index e4de6b7c7e..bd85416af6 100644 --- a/docker/runtime/be/resource/init_be.sh +++ b/docker/runtime/be/resource/init_be.sh @@ -16,90 +16,198 @@ # specific language governing permissions and limitations # under the License. -FE_SERVERS="" -BE_ADDR="" - -ARGS=$(getopt -o -h: --long fe_servers:,be_addr: -n "$0" -- "$@") - -eval set -- "${ARGS}" - -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 +set -eo pipefail +shopt -s nullglob + +DORIS_HOME="/opt/apache-doris" + +# 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 -done - -#echo FE_SERVERS = $FE_SERVERS -echo "DEBUG >>>>>> FE_SERVERS=[${FE_SERVERS}]" -echo "DEBUG >>>>>> BE_ADDR=[${BE_ADDR}]" - -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}" + # 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 +} + +# 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 - ## be doesn't registe - echo "DEBUG >>>>>> run commnad ${registerMySQL}" - eval "${registerMySQL}" - if [[ "${i}" == 20 ]]; then - echo "DEBUG >>>>>> BE Start Or Register FAILED!" + 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 - sleep 5 + 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 -done +} + +# 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 diff --git a/docker/runtime/fe/resource/init_fe.sh b/docker/runtime/fe/resource/init_fe.sh index 64e97a08dc..bcc546553d 100644 --- a/docker/runtime/fe/resource/init_fe.sh +++ b/docker/runtime/fe/resource/init_fe.sh @@ -16,111 +16,224 @@ # specific language governing permissions and limitations # under the License. -FE_ID=0 -FE_SERVERS="" - -ARGS=$(getopt -o -h: --long fe_id:,fe_servers: -n "$0" -- "$@") - -eval set -- "${ARGS}" - -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 - shift -done - -echo "DEBUG >>>>>> FE_ID = [${FE_ID}]" -echo "DEBUG >>>>>> FE_SERVERS = [${FE_SERVERS}]" - -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}') - 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 +set -eo pipefail +shopt -s nullglob - ## 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] +DORIS_HOME="/opt/apache-doris" - ## PREPARE1: registe follower from mysql client - registerMySQL="mysql -uroot -P9030 -h${feIpArray[1]} -e \"alter system add follower '${feIpArray[FE_ID]}:${feEditLogPortArray[FE_ID]}'\"" +# Obtain necessary and basic information to complete initialization - ## PREPARE2: call start_fe.sh using --help optional - registerShell="/opt/apache-doris/fe/bin/start_fe.sh --helper '${feIpArray[1]}:${feEditLogPortArray[1]}'" +# 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 + # 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}/fe/doris-meta/image" ]; then + DATABASE_ALREADY_EXISTS='true' + fi +} + +# 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 +} + +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 - 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\"】" + 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 +} - ## STEP1: check FE master status +_main() { + docker_setup_env + docker_required_variables_env + get_doris_fe_args - for ((i = 0; i <= 2000; i++)); do + if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + add_priority_networks $PRIORITY_NETWORKS + fi - ## run STEP1 & STEP2, and then break - echo "Run registerShell command, [ registerMySQL = ${registerMySQL} ]" - eval "${registerMySQL}" - sleep 2 + docker_setup_db + check_fe_status + doris_note "Ready to start CURRENT_FE!" - ## 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 [ $CURRENT_FE_IS_MASTER == true ]; then + start_fe.sh + else + start_fe.sh --helper ${MASTER_FE_IP}:${MASTER_FE_EDIT_PORT} + fi - if [[ "${followerJoined}" == 0 ]]; then - echo "Run registerShell command, [ registerShell = ${registerShell} ]" - eval "${registerShell}" - echo "The resutl of run registerShell command, [ res = $? ]" - fi - sleep 5 - done + exec "$@" +} -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}" +if ! _is_sourced; then + _main "$@" fi --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org