#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

#########################
# 广东堡塔安全技术有限公司
# 堡塔云WAF项目组
# 升级脚本
#########################

PWD_d=`pwd`

install_path=/www
setup_path=$install_path/cloud_waf
waf_path=$setup_path/console

if [ ! -d "$setup_path" ]; then
    echo "没有安装堡塔云WAF,请执行下面的命令安装堡塔云WAF!"
    echo "curl -skSO https://download.bt.cn/cloudwaf/scripts/install_cloudwaf.sh && bash install_cloudwaf.sh"
    exit 1
fi

if [ $(whoami) != "root" ];then
    echo -e "检测到非root用户升级，请尝试以下解决方案：\n   1.请切换到root用户升级 \n   2.尝试执行以下升级命令：\n     sudo bash $0 $@"
    exit 1
fi

NGINX_NAME="cloudwaf_nginx"
MYSQL_NAME="cloudwaf_mysql"
Containers="$NGINX_NAME $MYSQL_NAME"

nginx_command="docker exec $NGINX_NAME nginx -t"
mysql_command="docker exec $MYSQL_NAME mysql -V"

CPU_architecture=$(uname -m)
if [ "${CPU_architecture}" == "s390x" ];then
    echo -e "\033[31m 抱歉, 堡塔云WAF不支持s390x架构进行安装，请使用x86_64服务器架构 \033[0m"
    exit 1
elif [ "${CPU_architecture}" == "aarch64" ];then
    CPU_architecture="-aarch64"
elif [ "${CPU_architecture}" == "x86_64" ];then
    # x86_64 默认为空
    CPU_architecture=""
else
    echo " ${CPU_architecture} 此架构暂不支持."
    uname -a
    exit 1
fi

Mirror_nginx_file="btwaf-openresty-latest${CPU_architecture}.tar.gz"
Mirror_file="btwaf_mysql_openresty-latest${CPU_architecture}.tar.gz"
Cloudwaf_file="cloudwaf-latest${CPU_architecture}.tar.gz"

# 临时处理aawaf变成中文的问题
get_en=$(cat $waf_path/config/sysconfig.json |grep '"language": "EN",')
if [[ -z "${get_en}" ]]; then
    Cloudwaf_file="cloudwaf-latest${CPU_architecture}.tar.gz"
else
    curl -k https://node.aapanel.com/cloudwaf_en/scripts/update_cloudwaf_en.sh |bash
    exit
fi


WAF_Port=$(cat $waf_path/data/.server-port)

getty_status=$(systemctl is-active getty@tty1.service)
getty_status22=$(systemctl is-enabled getty@tty1.service)

if [ "$getty_status22" = "masked" ]; then
    systemctl unmask getty@tty1.service
fi

if [ "$getty_status" = "inactive" ]; then
    systemctl start getty@tty1.service
fi

is64bit=$(getconf LONG_BIT)
if [ "${is64bit}" != '64' ];then
    echo -e "\033[31m 抱歉, 堡塔云WAF不支持32位系统, 请使用64位系统! \033[0m"
    exit 1
fi

Check_Waf_Type(){

    if [ -s $waf_path/data/.cluster-state ]; then
        #echo "堡塔云WAF集群"
        number=$(cat $waf_path/data/.cluster-state)
        if [[ "$number" == "1" ]]; then
            echo "堡塔云WAF集群：主控"
            Master="yes"

        elif [ "$number" == "2" ]; then
            echo "堡塔云WAF集群：被控"
            Slave="yes"

        fi
    
    elif [ -f $waf_path/CloudWaf ] && [ ! -f $waf_path/data/.cluster-state ]; then
        echo "堡塔云WAF单机版"
        Standalone="yes"
    fi

}

PORT(){
    if Command_Exists ss ; then
        command_port="ss"

    elif Command_Exists netstat ; then
        command_port="netstat"
    else
        echo -e "命令不存在，无法检查端口是否使用"
        command_port=""
    fi

    if [[ ! -z $command_port ]]; then

        if [ -d "$setup_path" ]; then
            # 排除了openresty docker-proxy
            check_command=$($command_port -ltnp | grep -E ':(80|443|33060)\s' |grep -v openresty|grep -v docker-proxy)
        else
            check_command=$($command_port -ltnp | grep -E ':(80|443|33060)\s')
        fi

        if [[ ! -z "$check_command" ]]; then
            echo "$check_command"
            echo -e "\033[31m 堡塔云WAF需要使用 80 443 33060 端口,系统内已有服务使用,否则无法正常使用,请修改相关程序端口. \033[0m"
            exit 1
        fi
    fi
}

Check_Port(){
    if ! Command_Exists docker; then
        PORT
    else
        check=$(docker ps |grep -wE "$NGINX_NAME|$MYSQL_NAME")
        if [[ -z "$check" ]]; then
            PORT
        fi
    fi
}

GetSysInfo(){
	if [ -s "/etc/redhat-release" ];then
		SYS_VERSION=$(cat /etc/redhat-release)
	elif [ -s "/etc/issue" ]; then
		SYS_VERSION=$(cat /etc/issue)
	fi
	SYS_INFO=$(uname -a)
	SYS_BIT=$(getconf LONG_BIT)
	MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}')
	CPU_INFO=$(getconf _NPROCESSORS_ONLN)

	echo -e ${SYS_VERSION}
	echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO}
	echo -e ${SYS_INFO}
	echo -e "请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"

}

Red_Error(){
	echo '=================================================';
	printf '\033[1;31;40m%b\033[0m\n' "$@";
	GetSysInfo
    /etc/init.d/btw admin_restart
	exit 1;
}

Check_Disk_Space(){
    df_Th=$(df -Th)
    #echo "$df_Th"
    root_df_Th=$( echo "$df_Th"|grep -w /|awk '{print $6}')
    root_df_Th2=$( echo "$df_Th"|grep -w /|awk '{print $5}')
    a=$(echo $root_df_Th|awk -F "%" '{print $1}')
    echo -e "当前/目录已使用: ${root_df_Th} 可用：${root_df_Th2}"
    if [ $a -ge 98 ];then
        echo -e "当前/目录磁盘剩余空间小于2% 可用：${root_df_Th2},可能是因此导致堡塔云WAF无法正常使用."
    fi
    www_df_Th=$(echo "$df_Th"|grep -w /www|awk '{print $6}')
    www_df_Th2=$(echo "$df_Th"|grep -w /www|awk '{print $5}')
    b=$(echo $www_df_Th|awk -F "%" '{print $1}')
    if [[ ! -z $www_df_Th ]]; then
        echo -e "当前/www目录已使用: ${www_df_Th} 可用：${www_df_Th2}"
        if [ $b -ge 98 ];then
            echo -e "当前/www目录磁盘剩余空间小于2% 可用：${www_df_Th2},可能是因此导致堡塔云WAF无法正常使用."
        fi
    fi

    #查看 Inodes
    df_I=$(df -i)
    #echo "$df_I"
    root_df_I=$( echo "$df_I"|grep -w /|awk '{print $5}')
    c=$(echo $root_df_I|awk -F "%" '{print $1}')
    echo -e "当前/目录的Inodes已使用: ${root_df_I}"
    if [ $c -ge 98 ];then
        echo -e "当前/目录磁盘Inodes剩余空间小于2%,可能是因此导致堡塔云WAF无法正常使用."
        echo -e "查询Inodes占用的命令: for i in /*; do echo \$i; find \$i | wc -l; done"
        echo -e "请根据查询结果到对应目录进行处理,注意清理该目录前请备份好数据后再操作."
    fi
    www_df_I=$( echo "$df_I"|grep -w /www|awk '{print $5}')
    b=$(echo $www_df_I|awk -F "%" '{print $1}')
    if [[ ! -z $www_df_I ]]; then
        echo -e "当前/www的Inodes目录已使用: ${www_df_I}"
        if [ $b -ge 98 ];then
            echo -e "当前/www目录磁盘Inodes剩余空间小于2%,可能是因此导致堡塔云WAF无法正常使用."
            echo -e "查询Inodes占用的命令: for i in /www/*; do echo \$i; find \$i | wc -l; done"
            echo -e "请根据查询结果到对应目录进行处理,注意清理该目录前请备份好数据后再操作."
        fi
    fi
}

Get_Pack_Manager(){
	if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then
		PM="yum"
	elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then
		PM="apt-get"		
	fi
}

Command_Exists() {
    command -v "$@" >/dev/null 2>&1
}

Check_Sys_Write(){
    echo "正在检测系统关键目录是否可写"
    if [ ! -d "/etc/init.d" ];then
        mkdir -p /etc/init.d
	fi

    if [ ! -d "$install_path" ];then
        mkdir -p $install_path
	fi
	
    Get_Pack_Manager
    if [ "$PM" == "yum" ]; then
        read_dir="$install_path /usr/lib/systemd/system/ /etc/init.d/ /usr/bin/ /var/spool/cron/"
    else
        read_dir="$install_path /usr/lib/systemd/system/ /etc/init.d/ /usr/bin/ /var/spool/cron/crontabs/"
    fi
    
    echo "Ture" > /tmp/btw_install_test_111.pl || touch /tmp/btw_install_test_111.pl
    for dir in ${read_dir[@]}
    do
        if [[ -d "$dir" ]]; then
            if [[ ! -f "/tmp/btw_install_test_111.pl" ]]; then
                echo "建立测试 /tmp/btw_install_test_111.pl 文件失败"
                state=0
            else
                \cp /tmp/btw_install_test_111.pl $dir/btw_install_test_111.pl
            fi
            state=$(echo $?)
            if [[ "$state" != "0" ]];then
                echo -e "\033[31m错误：检测到系统关键目录不可写! $read_dir \033[0m"
                echo "1、如果安装了[宝塔系统加固]，请先临时关闭"
                echo "2、如果安装了云锁，请临时关闭[系统加固、文件防护]功能"
                echo "3、如果安装了安全狗，请临时关闭[系统防护]功能"
                echo "4、如果使用了其它安全软件，请先卸载 "
                echo -e "5、如果使用了禁止写入命令，请执行命令取消禁止写入：\n   chattr -iaR $read_dir "

                if [ $(whoami) != "root" ];then
                    echo -e "6、检测到非root用户安装，请尝试以下解决方案：\n   1.请切换到root用户安装 \n   2.尝试执行以下安装命令：\n     sudo bash $0 $@"
                fi

                echo ""
                echo -e "\033[31m解决以上问题后，请尝试重新执行！ \033[0m"
                echo -e "如果无法解决请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
                exit 1
            else
                rm -f $dir/btw_install_test_111.pl
            fi
        fi
    done

    if [[ -f "/tmp/btw_install_test_111.pl" ]]; then
        rm -f /tmp/btw_install_test_111.pl
    fi
}

Check_Sys_Packs(){
    echo "正在检查系统中是否存在必备的依赖包"
    Packs="wget curl tar gzip"
    if [ -f /usr/bin/which ];then
        for pack in ${Packs[@]}
        do
            check_pack=$(which $pack)
            #echo $check_pack
            if [[ "$check_pack" == "" ]]; then
                    echo -e "\033[31mERROR: $pack 命令不存在，尝试以下解决方法：\033[0m"
                    if [ "$PM" == "yum" ]; then
                        echo 1、使用命令重新安装依赖包：yum reinstall -y ${Packs}
                    else
                        echo 1、使用命令重新安装依赖包：apt-get reinstall -y ${Packs}
                    fi
                    echo -e "2、检查系统源是否可用？尝试更换可用的源参考教程：\n   https://www.bt.cn/bbs/thread-58005-1-1.html "
                    echo ""
                    echo -e "\033[31m解决以上问题后，请尝试重新执行！ \033[0m"
                    echo -e "如果无法解决请截图以上报错信息发帖至论坛www.bt.cn/bbs求助"
                    exit 1
            fi

        done
    fi
}

get_node_url(){
	if [ ! -f /bin/curl ];then
		if [ "${PM}" = "yum" ]; then
			yum install curl -y
		elif [ "${PM}" = "apt-get" ]; then
			apt-get install curl -y
		fi
	fi

	if [ -f "/www/node.pl" ];then
		download_Url=$(cat /www/node.pl)
		echo "Download node: $download_Url";
		echo '---------------------------------------------';
		return
	fi
	
	echo '---------------------------------------------';
	echo "Selected download node...";
    nodes=(https://dg2.bt.cn https://download.bt.cn https://ctcc1-node.bt.cn https://cmcc1-node.bt.cn https://ctcc2-node.bt.cn https://hk1-node.bt.cn https://na1-node.bt.cn https://jp1-node.bt.cn);
	tmp_file1=/dev/shm/net_test1.pl
	tmp_file2=/dev/shm/net_test2.pl
	[ -f "${tmp_file1}" ] && rm -f ${tmp_file1}
	[ -f "${tmp_file2}" ] && rm -f ${tmp_file2}
	touch $tmp_file1
	touch $tmp_file2
	for node in ${nodes[@]};
	do
		NODE_CHECK=$(curl -k --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
		RES=$(echo ${NODE_CHECK}|awk '{print $1}')
		NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
		TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
		if [ "${NODE_STATUS}" == "200" ];then
			if [ $TIME_TOTAL -lt 100 ];then
				if [ $RES -ge 1500 ];then
					echo "$RES $node" >> $tmp_file1
				fi
			else
				if [ $RES -ge 1500 ];then
					echo "$TIME_TOTAL $node" >> $tmp_file2
				fi
			fi

			i=$(($i+1))
			if [ $TIME_TOTAL -lt 100 ];then
				if [ $RES -ge 3000 ];then
					break;
				fi
			fi	
		fi
	done

	NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}')
	if [ -z "$NODE_URL" ];then
		NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
		if [ -z "$NODE_URL" ];then
			NODE_URL='https://download.bt.cn';
		fi
	fi
	rm -f $tmp_file1
	rm -f $tmp_file2
	download_Url=$NODE_URL
	echo "Download node: $download_Url";
	echo '---------------------------------------------';
}

Bored_waiting(){
    w_time="$wait_time"
    msg="$wait_msg"
    progress="."
    for ((i=0; i<${w_time}; i++))
    do
        printf "$msg %-10s %d\r" "$progress" "$((i+1))"
        sleep 1

        if [ "$progress" == ".........." ]; then
            progress="."
        else
            progress+="."
        fi
    done
    printf "$msg %-10s %d\r" ".........." "$w_time"
    #echo
}

Docker_Start() {
    if Command_Exists docker || [ -f /lib/systemd/system/docker.service ]; then
        if Command_Exists systemctl; then
            # systemctl mask getty@tty1.service
            systemctl enable docker
            systemctl reset-failed docker.service
            systemctl start docker.service
            if [ "$?" != "0" ];then
                systemctl reset-failed docker.service
                systemctl restart docker.service
                if [ "$?" != "0" ];then
                    docker_status=$(systemctl status docker.service)
                    echo "$docker_status"
                    if [ -f /etc/docker/daemon.json ]; then
                        echo "/etc/docker/daemon.json 文件内容:"
                        cat /etc/docker/daemon.json
                        echo -e "\033[33m建议检查以上 /etc/docker/daemon.json 文件内容是否正确？\033[0m"
                    fi
                    #等待100秒动画
                    echo -e "\033[31m启动 docker服务失败，可能启动太快导致\033[0m"
                    wait_msg="正等待100秒后自动重启docker服务"
                    wait_time="100"
                    Bored_waiting
                    systemctl reset-failed docker.service
                    systemctl restart docker.service
                    if [ "$?" != "0" ];then
                        docker_status=$(systemctl status docker.service)
                        echo "$docker_status"
                        Red_Error "docker启动失败" "请尝试等待2分钟执行重启docker命令：systemctl restart docker.service (无内容返回为正常)" "最后重新执行堡塔云WAF安装命令"
                    fi
                fi
            fi
        else
            chkconfig --add docker
            chkconfig --level 2345 docker on
            service docker start
            if [ "$?" != "0" ];then
                service docker.service status
                cat /etc/docker/daemon.json
                Red_Error "docker启动失败。"
            fi
        fi
    fi
}

Docker_Status_Check(){
    if Command_Exists docker ; then
        if Command_Exists systemctl; then
            docker_status=$(systemctl is-active docker)
            # 判断Docker运行状态
            if [ "$docker_status" = "active" ]; then
                echo "Docker正在运行"
            else
                Docker_Start
            fi
        fi
    else

        Red_Error "docker 命令不存在,请检查是否安装docker."

    fi
}

Images_Check(){
    # 检查镜像中是否有 btwaf-openresty，如果没有返回 0
    check_nginx_images=$(docker images --format '{{.Repository}}' | grep -w -c 'btwaf-openresty')
    # echo $check_nginx_images

    # 检查镜像中是否有 btwaf-mysql，如果没有返回 0
    check_mysql_images=$(docker images --format '{{.Repository}}' | grep -w -c 'btwaf-mysql')
    # echo $check_mysql_images
}

Docker_Compose_Check(){

    if Command_Exists docker-compose; then
        echo "docker-compose 存在"
    else 
        if Command_Exists docker; then
            Docker_compose="docker compose version"
            if $Docker_compose; then
                echo "docker compose 存在"
            fi
        fi

    fi
}

Set_Firewall(){
    if [ "$offline_install" != "offline" ]; then
        sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}')
        if [ "${PM}" = "apt-get" ]; then
            apt-get install -y ufw
            if [ -f "/usr/sbin/ufw" ] || [ -f "/sbin/ufw" ] ; then
                ufw allow 22/tcp > /dev/null 2>&1
                ufw allow 80/tcp > /dev/null 2>&1
                ufw allow 443/tcp > /dev/null 2>&1
                ufw allow ${WAF_Port}/tcp > /dev/null 2>&1
                ufw allow ${sshPort}/tcp > /dev/null 2>&1
                ufw_status=`ufw status`
                echo y|ufw enable
                ufw default deny
                ufw reload
            fi
        else
            if [ -f "/etc/init.d/iptables" ]; then
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${WAF_Port} -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${sshPort} -j ACCEPT
                iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
                iptables -A INPUT -s localhost -d localhost -j ACCEPT
                iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
                iptables -P INPUT DROP
                service iptables save
                sed -i "s#IPTABLES_MODULES=\"\"#IPTABLES_MODULES=\"ip_conntrack_netbios_ns ip_conntrack_ftp ip_nat_ftp\"#" /etc/sysconfig/iptables-config
                iptables_status=$(service iptables status | grep 'not running')
                if [ "${iptables_status}" == '' ]; then
                    service iptables restart
                fi
            else
                AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux")
                [ "${AliyunCheck}" ] && return
                yum install firewalld -y
                [ "${Centos8Check}" ] && yum reinstall python3-six -y
                systemctl enable firewalld
                systemctl start firewalld
                firewall-cmd --set-default-zone=public > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=443/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=${WAF_Port}/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1
                firewall-cmd --reload
            fi
        fi

    else
        sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}')
        if [ "${PM}" = "apt-get" ]; then
            if [ -f "/usr/sbin/ufw" ] || [ -f "/sbin/ufw" ] ; then
                ufw allow 22/tcp > /dev/null 2>&1
                ufw allow 80/tcp > /dev/null 2>&1
                ufw allow 443/tcp > /dev/null 2>&1
                ufw allow ${WAF_Port}/tcp > /dev/null 2>&1
                ufw allow ${sshPort}/tcp > /dev/null 2>&1
                ufw_status=`ufw status`
                echo y|ufw enable
                ufw default deny
                ufw reload
            fi
        else
            if [ -f "/etc/init.d/iptables" ];then
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${WAF_Port} -j ACCEPT
                iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${sshPort} -j ACCEPT
                iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
                iptables -A INPUT -s localhost -d localhost -j ACCEPT
                iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
                iptables -P INPUT DROP
                service iptables save
                sed -i "s#IPTABLES_MODULES=\"\"#IPTABLES_MODULES=\"ip_conntrack_netbios_ns ip_conntrack_ftp ip_nat_ftp\"#" /etc/sysconfig/iptables-config
                iptables_status=$(service iptables status | grep 'not running')
                if [ "${iptables_status}" == '' ];then
                    service iptables restart
                fi
            else
                AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux")
                [ "${AliyunCheck}" ] && return
                [ "${Centos8Check}" ]
                systemctl enable firewalld
                systemctl start firewalld
                firewall-cmd --set-default-zone=public > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=443/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=${WAF_Port}/tcp > /dev/null 2>&1
                firewall-cmd --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1
                firewall-cmd --reload
            fi
        fi

    fi
}

Get_Ip_Address(){
    if [ "$offline_install" != "offline" ]; then
        getIpAddress=""
        getIpAddress=$(curl -sSk --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
        if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then
            isHosts=$(cat /etc/hosts|grep 'www.bt.cn')
            if [ -z "${isHosts}" ];then
                echo "" >> /etc/hosts
                echo "116.213.43.206 www.bt.cn" >> /etc/hosts
                getIpAddress=$(curl -sSk --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
                if [ -z "${getIpAddress}" ];then
                    sed -i "/bt.cn/d" /etc/hosts
                fi
            fi
        fi

        ipv4_regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
        ipv6_regex="^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$"
        ipv6Address=$(echo ${getIpAddress}|tr -d "[]")

        if [[ ${getIpAddress} =~ ${ipv4_regex} ]]; then
            echo "${getIpAddress}" >/dev/null 2>&1
        elif [[ ${ipv6Address} =~ ${ipv6_regex} ]]; then
            echo "${ipv6Address}" >/dev/null 2>&1
        else
            getIpAddress="SERVER_IP"
        fi

        if [ "${getIpAddress}" != "SERVER_IP" ];then
            echo "${getIpAddress}" > ${waf_path}/data/iplist.txt
            #echo "${getIpAddress}"
        fi

    else
        # 离线安装不获取外网IP
        getIpAddress="SERVER_IP"
    fi

    LOCAL_IP=$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1)

}

Container_Check(){
    nginx_container_exists=0
    mysql_container_exists=0
    #查找$Containers 列表的容器是否存在
    for container in ${Containers}; do
        if [[ ! -z "$container" ]]; then
            #精确匹配容器名称
            container_name=$(docker ps -a --filter "name=^${container}$" --format "{{.Names}}")
            #nginx
            if [ "$container_name" == "$NGINX_NAME" ];then
				nginx_container_exists=1
			fi
            
            #mysql
			if [ "$container_name" == "$MYSQL_NAME" ];then
				mysql_container_exists=1
			fi

        fi
	done
    # echo nginx_container_exists $nginx_container_exists
    # echo mysql_container_exists $mysql_container_exists

    if [ "$nginx_container_exists" == "0" ]; then
        # echo "curl -skSO https://download.bt.cn/cloudwaf/scripts/install_cloudwaf.sh && bash install_cloudwaf.sh"
        # Red_Error "$NGINX_NAME 容器不存在"

        echo -e "\033[31m $NGINX_NAME 容器不存在 \033[0m"

        if [ -f "$setup_path/nginx/conf/nginx.conf" ]; then
            # 检查镜像是否存在
            Images_Check
            if [[ "$check_nginx_images" == "0" ]]; then
                # 镜像不存在,下载nginx镜像文件并且创建容器
                Fix_Container="fix_nginx"
                Download_Nginx_Files="1"
                Download_Nginx_Container_Files
                Create_Nginx_Container
                sleep 3
            else
                # 镜像存在,只创建容器
                Create_Nginx_Container
                sleep 3
            fi
        else
            Red_Error "$setup_path/nginx/conf/nginx.conf 文件不存在，创建 $NGINX_NAME 失败."
        fi
     
    fi


    if [ "$mysql_container_exists" == "0" ]; then
        # echo "curl -skSO https://download.bt.cn/cloudwaf/scripts/install_cloudwaf.sh && bash install_cloudwaf.sh"
        # Red_Error "$MYSQL_NAME 容器不存在"
        echo -e "\033[31m $MYSQL_NAME 容器不存在 \033[0m"

    fi

}

Container_one_Check(){
    #检查指定容器是否正常运行 调用请添加如：container=$NGINX_NAME

    if [ "$container" == "$NGINX_NAME" ]; then
        container_check_command=$nginx_command
    elif [ "$container" == "$MYSQL_NAME" ]; then
        container_check_command=$mysql_command
    fi

        # $container_check_command 2>&1 >/dev/null
        output=$($container_check_command 2>&1 >/dev/null)
}

Container_All_Status(){
    #检查所有容器是否运行
    for container in ${Containers}; do
        #检查指定容器是否正常运行
        echo "正在检查 $container 是否运行"
        container=$container
        Container_one_Check
        if [ "$?" == "0" ]; then
            echo -e "\033[32m$container is running\033[0m"
        else
            echo -e "${container} 未启动,正在尝试重启..."
            systemctl reset-failed docker.service
            systemctl restart docker.service
            if [ -s "/etc/init.d/btw" ]; then
                /etc/init.d/btw ${container}_restart
            elif [ -f "${setup_path}/btw.init" ]; then
                bash ${setup_path}/btw.init ${container}_restart
                \cp -arpf ${setup_path}/btw.init /etc/init.d/btw
                chmod +x /etc/init.d/btw
            else
                docker restart $container
                if [ $? -ne "0" ]; then
                    docker logs --tail=10 $container
                    Red_Error "ERROR: Failed start $container container!" "ERROR: 启动 $container 容器失败！"
                fi
            fi            
        fi
    done 
}

Container_Check_22(){
    docker_version="docker version"
    if Command_Exists $docker_version && [ ! -d "$setup_path" ]; then
        Container_info_2=""
        for container in ${Containers}; do
            #精确匹配容器名称
            container_name=$(docker ps -a --filter "name=^${container}$" --format "{{.Names}}")
            if [ -n "$container_name" ]; then
                Container_info_2+="容器已存在: $container_name \n"
                container_info+="1. 导出容器并压缩备份命令：\n   docker export $container_name | gzip > backup_$(date +%Y_%m_%d_%H_%M_%S)_$container_name.tar.gz \n"
                container_info+="2. 删除容器命令：\n   docker rm -f $container_name \n"
            fi
        done

        if [ -n "$Container_info_2" ]; then
            echo -e "$Container_info_2"
            echo ""
            echo -e "\033[31m$setup_path 目录不存在,检测到非堡塔云WAF创建的容器\033[0m"
            echo -e "\033[31m堡塔云WAF需要使用到 $Containers 容器,请先解决以上问题,再安装堡塔云WAF.\033[0m"
            exit 1;
        fi
    fi
    
}

Download_Nginx_Container_Files(){

    if [[ "$Download_Nginx_Files" == "1" ]]; then

        if [ "$offline_install" != "offline" ]; then
            echo "下载 $NGINX_NAME 文件中,请稍等..."

            wget --no-check-certificate -O ${Mirror_nginx_file} $download_Url/cloudwaf/package/${Mirror_nginx_file} -t 5 -T 10

            tmp_size=$(du -b "${Mirror_nginx_file}" |awk '{print $1}')
            if [ $tmp_size -lt 30486748 ];then
                ls -l ${Mirror_nginx_file} && rm -f ${Mirror_nginx_file}
                echo "ERROR: Failed to download!" "ERROR: 下载${Mirror_nginx_file}文件失败！"
            else
                Download_completed="1"
            fi
        else
            # 离线文件复制
            if [ "${Mirror_nginx_file}" == "" ]; then
                Red_Error "Mirror_nginx_file  变量为空 "
            fi

            if [[ ! -f "${PWD_d}/${Mirror_nginx_file}" ]]; then

                if [[ "$Fix_Container" != "fix_nginx" ]] || [[ "$check_nginx_images" == "0" ]]; then
                    echo -e "\033[31m "${PWD_d}/${Mirror_nginx_file}" 文件不存在,\n请将 update_cloudwaf.sh "${Cloudwaf_file}" "${Mirror_nginx_file}" 放在相同的目录下\033[0m"
                    echo "${Mirror_nginx_file}下载地址: https://download.bt.cn/cloudwaf/package/${Mirror_nginx_file}"
                    echo "${Cloudwaf_file}下载地址: https://download.bt.cn/cloudwaf/package/${Cloudwaf_file}"
                else
                    echo -e "\033[31m "${PWD_d}/${Mirror_nginx_file}" 文件不存在,\n请将 update_cloudwaf.sh "${Mirror_nginx_file}" 放在相同的目录下\033[0m"
                    echo "${Mirror_nginx_file}下载地址: https://download.bt.cn/cloudwaf/package/${Mirror_nginx_file}"
                fi
                #不支持带有目录,如：bash /tmp/update_cloudwaf.sh offline，否则无法找到文件
                echo -e "\033[31m最后执行此命令进行安升级塔云WAF： bash update_cloudwaf.sh offline \033[0m"
                echo -e "推荐使用更方便的在线升级命令(需要连接互联网)：bash update_cloudwaf.sh "
                exit 1
            fi

            \cp -arpf "${PWD_d}/${Mirror_nginx_file}" $setup_path/
            if [ $? -ne "0" ]; then
                echo -e "\033[31m复制离线文件失败，请检查是否有此文件：${PWD_d}/${Mirror_nginx_file} \033[0m"
                exit 1;
            else
                Download_completed="1"    
            fi

        fi
    fi

}

Create_Nginx_Container(){

    if [[ "$Download_Nginx_Files" == "1" ]]; then
        tar -zxvf ${Mirror_nginx_file}
        if [ $? -ne "0" ]; then
            Red_Error "解压 ${Mirror_nginx_file} 失败"
        fi

        echo -e "正在安装镜像中,请稍等..."
        docker load -i "btwaf-openresty:latest.tar"
        if [ $? -ne "0" ]; then
            Red_Error "ERROR: Failed import image!" "ERROR: 导入nginx镜像文件失败！"
        fi
    fi

    if [[ $nginx_container_exists == "1" ]]; then
        echo "正在删除 $NGINX_NAME 容器"
        docker stop $NGINX_NAME
        docker rm -f $NGINX_NAME
    fi

    echo "正在创建 $NGINX_NAME 容器..."

    System_Info=$(hostnamectl)
    check_container=$(echo "$System_Info" |grep "Chassis"|awk -F":" '{print $2}')

    if [[ "$check_container" =~ "container" ]];then
        LXC_install="yes"
    fi

    if [[ "$LXC_install" == "yes" ]]; then
        echo -e "在LXC容器升级"
        docker run --name $NGINX_NAME --net=host --restart=always \
        -v $setup_path/nginx/logs:/usr/local/openresty/nginx/logs \
        -v $setup_path/nginx/logs:/www/wwwlogs \
        -v $setup_path/wwwroot:/www/wwwroot \
        -v $setup_path/nginx/conf.d:/etc/nginx \
        -v $setup_path/nginx/conf:/usr/local/openresty/nginx/conf \
        -v /etc/localtime:/etc/localtime:ro \
        --ulimit nofile=100000 \
        --ulimit core=0 \
        --hostname "$NGINX_NAME" \
        -d btwaf-openresty:latest
    else
        docker run --name $NGINX_NAME --net=host --restart=always \
        -v $setup_path/nginx/logs:/usr/local/openresty/nginx/logs \
        -v $setup_path/nginx/logs:/www/wwwlogs \
        -v $setup_path/wwwroot:/www/wwwroot \
        -v $setup_path/nginx/conf.d:/etc/nginx \
        -v $setup_path/nginx/conf:/usr/local/openresty/nginx/conf \
        -v /etc/localtime:/etc/localtime:ro \
        --ulimit nofile=1000001 \
        --ulimit core=0 \
        --hostname "$NGINX_NAME" \
        -d btwaf-openresty:latest
    fi

    if [ $? -ne "0" ]; then
        echo "ERROR: 创建 $NGINX_NAME 容器失败.尝试重启docker服务中..."
        systemctl reset-failed docker.service
        systemctl restart docker.service
        docker start $NGINX_NAME 2>&1 >/dev/null
        if [ $? -ne "0" ]; then
            Red_Error "ERROR: Failed create $NGINX_NAME container!" "ERROR: 创建 $NGINX_NAME 容器失败！"
        fi
    fi

    sleep 3
    # docker exec $NGINX_NAME groupadd -g 1000 www
    # docker exec $NGINX_NAME useradd -r -s /sbin/nologin -g www -u 1000 www
    # if [ $? -ne "0" ]; then
    #     echo -e "ERROR: Failed create www user!" "ERROR: 创建 www 用户失败！请稍等正在重试中..."
    #     sleep 5
    #     docker exec $NGINX_NAME groupadd -g 1000 www
    #     docker exec $NGINX_NAME useradd -r -s /sbin/nologin -g www -u 1000 www
    #     if [ $? -ne "0" ]; then
    #         echo "ERROR: Failed create www user!" "ERROR: 创建 www 用户失败！"
    #     fi
    # fi
    
    if [[ "$Download_Nginx_Files" == "1" ]]; then
        rm -f ${Mirror_nginx_file} "btwaf-openresty:latest.tar"
    fi
}

Update_Nginx_Container(){
    nginx_version=$(docker exec cloudwaf_nginx nginx -v 2>&1 )

    # 判断获取的内容是否包含 openresty，如果不包含容器可能运行不正常
    if [[ "$nginx_version" =~ "openresty" ]]; then
        get_openresty="1"

        # 获取版本数字
        get_nginx_version=$( echo "$nginx_version" | awk -F "/" '{print $2}' )
        # echo $get_nginx_version

        # 数字去除 .   1.21.4.2 结果: 12142
        nginx_version_number=$(echo "$get_nginx_version" | sed 's/\.//g')
        # echo "$nginx_version_number"

        # 判断是否小于 12142  需要升级到的版本号
        if [ $nginx_version_number -lt 12500 ] || [ $nginx_version_number = 12711 ]; then
            echo "nginx需要升级 "$nginx_version_number""

            # 下载nginx镜像文件
            Download_Nginx_Files="1"
            Download_Nginx_Container_Files

            if [[ $Download_completed == "1" ]]; then

                # echo "正在备份 $NGINX_NAME 容器,请稍等..."
                # docker stop $NGINX_NAME
                # backup_time=$(date +%Y_%m_%d_%H_%M_%S)
                # docker export $NGINX_NAME | gzip > /tmp/backup_${backup_time}_$NGINX_NAME.tar.gz
                
                # if [ -s /tmp/backup_${backup_time}_$NGINX_NAME.tar.gz ]; then
                #     echo "备份文件：/tmp/backup_${backup_time}_$NGINX_NAME.tar.gz"
                # fi

                echo "正在删除 $NGINX_NAME 容器与镜像,请稍等..."
                docker stop $NGINX_NAME
                docker rm -f $NGINX_NAME
                docker rmi btwaf-openresty:latest

                echo "正在升级 $NGINX_NAME 容器,请稍等..."

                # 创建 nginx 容器
                Create_Nginx_Container

            else
                echo "下载/复制出错了,无法升级容器."
            fi
        else
            echo "nginx 不需要升级: "$nginx_version" "
        fi

    else
        echo -e "\033[33m Error: $NGINX_NAME 运行异常,无法获取版本号. \033[0m"
        echo "$nginx_version"
        echo ""
    fi
}

Core_File_Nginx(){
# 处理nginx core崩溃文件
    
    # 检查镜像是否存在
    Images_Check

    core_file_number=$(docker exec $NGINX_NAME ls |grep -c ^core.)

    # core文件不等于0时，容器存在时，镜像存在时
    if [[ $core_file_number != "0" ]] && [[ "$check_nginx_images" == "1" ]]; then
        
        echo "重建 $NGINX_NAME 容器中"
        Create_Nginx_Container
        sleep 3
    fi
}

Download_Copy_Files(){

    mkdir -p $setup_path
    cd $setup_path

    # 检查是否需要升级nginx
    Update_Nginx_Container

    # 检查core崩溃文件
    Core_File_Nginx

    if [ "$offline_install" != "offline" ]; then
        echo "下载升级文件中,请稍等..."
       
        # echo ${Mirror_file} ${Cloudwaf_file}

        # wget --no-check-certificate -O ${Mirror_file} $download_Url/cloudwaf/package/${Mirror_file} -t 5 -T 10 

        # tmp_size=$(du -b "$Mirror_file" |awk '{print $1}')
        # if [ $tmp_size -lt 128127057 ];then
        #     ls -l $Mirror_file && rm -f $Mirror_file
        #     Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载镜像文件失败，请尝试重新执行！"
        # fi

        wget --no-check-certificate -O ${Cloudwaf_file} $download_Url/cloudwaf/package/${Cloudwaf_file} -t 5 -T 10
        tmp_size=$(du -b "${Cloudwaf_file}" |awk '{print $1}')
        if [ $tmp_size -lt 20692352 ];then
            ls -l ${Cloudwaf_file} && rm -f ${Cloudwaf_file}
            Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载${Cloudwaf_file}文件失败，请尝试重新执行！"
        fi
        

        if [ -f "$setup_path/offline.pl" ]; then
            rm -f $setup_path/offline.pl
        fi

    else
        # 离线文件复制 镜像先不检查不复制
        if [ "${Mirror_file}" == "" ] || [ "${Cloudwaf_file}" == "" ]; then
            Red_Error "Mirror_file 或者 Cloudwaf_file 变量为空 "
        fi
        # \cp -arpf "${PWD_d}/${Mirror_file}" $setup_path/
        # if [ $? -ne "0" ]; then
        #     echo -e "\033[31m复制离线文件失败，请检查是否有此文件：${PWD_d}/${Mirror_file} \033[0m"
        #     exit 1;
        # fi

        \cp -arpf "${PWD_d}/${Cloudwaf_file}" $setup_path/
        if [ $? -ne "0" ]; then
            echo -e "\033[31m复制离线文件失败，请检查是否有此文件：${PWD_d}/${Cloudwaf_file} \033[0m"
            exit 1;
        fi
        

        # 生成离线判断文件
        echo "Ture" > $setup_path/offline.pl

    fi
}

Optimize_waf_conf_file(){
# 根据内存优化waf.conf文件

    BTWAF_DATA_MEM="50m"
    IPINFO_MEM="30m";
    MEM_TOTAL=$(free -m | awk '/^Mem:/{print $2}')
    if [ -z "$MEM_TOTAL" ]; then
        MEM_TOTAL=$(free -m | awk '/^内存：/{print $2}')
    fi

    if [[ "${MEM_TOTAL}" -gt 4096 && "${MEM_TOTAL}" -le 8192 ]];then
        BTWAF_DATA_MEM="50m"
        IPINFO_MEM="50m";
    elif [[ "${MEM_TOTAL}" -gt 8192 && "${MEM_TOTAL}" -le 16384 ]]; then
        BTWAF_DATA_MEM="80m"
        IPINFO_MEM="80m";
    elif [[ "${MEM_TOTAL}" -gt 16384 && "${MEM_TOTAL}" -le 32768 ]]; then
        BTWAF_DATA_MEM="100m"
        IPINFO_MEM="100m";
    elif [[ "${MEM_TOTAL}" -gt 32768 && "${MEM_TOTAL}" -le 65536 ]]; then
        BTWAF_DATA_MEM="110m"
        IPINFO_MEM="110m";
    elif [[ "${MEM_TOTAL}" -gt 65536 && "${MEM_TOTAL}" -le 131072 ]]; then
        BTWAF_DATA_MEM="120m"
        IPINFO_MEM="120m";
    elif [ "${MEM_TOTAL}" -gt 131072 ]; then
        BTWAF_DATA_MEM="130m"
        IPINFO_MEM="130m";
    fi

    if [ ! -f $setup_path/nginx/conf.d/waf.conf_bak ]; then
        cp $setup_path/nginx/conf.d/waf.conf $setup_path/nginx/conf.d/waf.conf_bak
    fi

    sed -i "s/btwaf_data 100m/btwaf_data ${BTWAF_DATA_MEM}/g" $setup_path/nginx/conf.d/waf.conf
    sed -i "s/ipinfo 100m/ipinfo ${IPINFO_MEM}/g" $setup_path/nginx/conf.d/waf.conf

}

Install_Mirror(){

    cd $setup_path

    mkdir -p $setup_path/wwwroot
    mkdir -p $setup_path/vhost
    mkdir -p $setup_path/mysql/{log,data,conf}
    mkdir -p $setup_path/nginx/{conf,logs,conf}
    mkdir -p $setup_path/nginx/conf.d/{vhost,user,pass,other}
    mkdir -p $waf_path/{logs,data,ssl}

    mkdir $setup_path/new_cloudwaf

    if [ ! -d "$setup_path/nginx/conf.d/waf/logs" ]; then
        mkdir -p $setup_path/nginx/conf.d/waf/logs
    fi

    echo -e "解压文件中,请稍等..."
    tar -zxf ${Cloudwaf_file} -C $setup_path/new_cloudwaf
    if [ $? -ne "0" ]; then
        Red_Error "解压 ${Cloudwaf_file} 失败"
    fi

    #升级时处理不需要复制的文件
    # if [ -f "$setup_path/nginx/conf.d/vhost/0.default.conf" ]; then
    #     rm -f $setup_path/new_cloudwaf/nginx/conf.d/vhost/0.default.conf
    # fi

    # nginx.conf文件存在时不覆盖
    if [ -f "$setup_path/nginx/conf/nginx.conf" ]; then
        rm -f $setup_path/new_cloudwaf/nginx/conf/nginx.conf
    fi

    # if [ -f "$setup_path/wwwroot/nginx/index.html" ]; then
    #     rm -f $setup_path/new_cloudwaf/wwwroot/nginx/index.html
    #     rm -f $setup_path/new_cloudwaf/wwwroot/nginx/fullchain.pem
    #     rm -f $setup_path/new_cloudwaf/wwwroot/nginx/privkey.pem
    # fi

    \cp -arpf $setup_path/new_cloudwaf/console/config/waf_site_new.json $setup_path/console/config
    rm -rf $setup_path/new_cloudwaf/console/config
    # 处理新添加的文件
    if [ ! -f "$setup_path/nginx/conf.d/waf/rule/limit.json" ]; then
        cp $setup_path/new_cloudwaf/nginx/conf.d/waf/rule/limit.json $setup_path/nginx/conf.d/waf/rule
    fi
	cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/rule/args.json $setup_path/nginx/conf.d/waf/rule/args.json
    # 处理新添加的文件
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/limit.json" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/limit.json $setup_path/nginx/conf.d/waf/html/limit.json
    fi
        # 处理新添加的文件
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/limit.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/limit.html $setup_path/nginx/conf.d/waf/html/limit.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_cbc.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_cbc.html $setup_path/nginx/conf.d/waf/html/aes_cbc.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_cbc_customize.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_cbc_customize.html $setup_path/nginx/conf.d/waf/html/aes_cbc_customize.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_cfb.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_ctr.html $setup_path/nginx/conf.d/waf/html/aes_ctr.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_ctr_customize.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_ctr_customize.html $setup_path/nginx/conf.d/waf/html/aes_ctr_customize.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_gcm.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_gcm.html $setup_path/nginx/conf.d/waf/html/aes_gcm.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_gcm_customize.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_gcm_customize.html $setup_path/nginx/conf.d/waf/html/aes_gcm_customize.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_ofb.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_ofb.html $setup_path/nginx/conf.d/waf/html/aes_ofb.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_ofb_customize.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/aes_ofb_customize.html $setup_path/nginx/conf.d/waf/html/aes_ofb_customize.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_cfb.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/forge.min.js $setup_path/nginx/conf.d/waf/html/forge.min.js
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_cfb.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/timeout.html $setup_path/nginx/conf.d/waf/html/timeout.html
    fi
    if [ ! -f "$setup_path/nginx/conf.d/waf/html/aes_cfb.html" ]; then
        cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/html/timeout_user.html $setup_path/nginx/conf.d/waf/html/timeout_user.html
    fi

    rm -rf $setup_path/new_cloudwaf/nginx/conf.d/waf/config
    
    rm -rf $setup_path/new_cloudwaf/nginx/conf.d/waf/html

    # 处理新添加的文件
    cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/rule/pay.json $setup_path/nginx/conf.d/waf/rule/pay.json

	cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/rule/password.json $setup_path/nginx/conf.d/waf/rule/password.json
	if [ -f "$setup_path/new_cloudwaf/nginx/conf.d/waf/rule/username_top.json" ]; then
		cp -a -r $setup_path/new_cloudwaf/nginx/conf.d/waf/rule/username_top.json $setup_path/nginx/conf.d/waf/rule/username_top.json
	fi
    rm -rf $setup_path/new_cloudwaf/nginx/conf.d/waf/rule
    rm -rf $setup_path/new_cloudwaf/nginx/conf.d/waf/logs

    # 复制剩下的所有文件到 $setup_path
    \cp -arpf $setup_path/new_cloudwaf/* $setup_path
    if [ $? -ne "0" ]; then
        Red_Error "无法复制文件到 $setup_path"
    fi

    if [ ! -f "$waf_path/CloudWaf" ]; then
        Red_Error "$waf_path/CloudWaf 文件不存在"
    fi

    # 根据内存优化waf.conf文件
    Optimize_waf_conf_file

    #开机启动文件
    \cp -arpf btw.init /etc/init.d/btw
    if [ $? -ne "0" ]; then
        echo "无法复制文件到 /etc/init.d/btw"
    fi

    chmod +x /etc/init.d/btw
    ln -sf /etc/init.d/btw /usr/bin/btw
    if [ $? -ne "0" ]; then
        echo -e "/etc/init.d/btw软链接到/usr/bin/btw 失败,将无法正常使用btw命令."
    fi

    \cp -arpf btw.service /usr/lib/systemd/system/btw.service
    if [ $? -ne "0" ]; then
        echo -e "无法复制文件到 /usr/lib/systemd/system/btw.service,将无法设置开机启动."
    fi

    # echo -e "正在解压文件中,请稍等..."
    # tar -zxf ${Mirror_file}
    # if [ $? -ne "0" ]; then
    #     Red_Error "解压 ${Mirror_file} 失败"
    # fi

    # echo -e "正在安装镜像中,请稍等..."
    # docker load -i "btwaf-openresty:latest.tar"
    # if [ $? -ne "0" ]; then
    #     Red_Error "ERROR: Failed import image!" "ERROR: 导入镜像文件失败！"
    # fi

    # docker load -i "btwaf-mysql:latest.tar"
    # if [ $? -ne "0" ]; then
    #     Red_Error "ERROR: Failed import image!" "ERROR: 导入镜像文件失败！"
    # fi

    # rm -f ${Mirror_file} "btwaf-openresty:latest.tar" "btwaf-mysql:latest.tar"
    
    rm -f ${Cloudwaf_file}
    rm -rf $setup_path/new_cloudwaf
    
}


Start_Monitor(){

    # NGINX
    if [ "$nginx_container_exists" == "1" ]; then
        echo -e "$NGINX_NAME 容器,正在重载..."
        if [ -s "/etc/init.d/btw" ]; then
            /etc/init.d/btw ${NGINX_NAME}_reload
        elif [ -f "${setup_path}/btw.init" ]; then
            bash ${setup_path}/btw.init ${NGINX_NAME}_reload
            \cp -arpf ${setup_path}/btw.init /etc/init.d/btw
            chmod +x /etc/init.d/btw
        else
            docker exec $NGINX_NAME nginx -s reload 2>&1 >/dev/null
        fi
    fi

    sleep 2

    if [ -s "$setup_path/nginx/conf.d/waf/mysql_default.pl" ]; then
        #获取数据库密码
        MYSQL_PASS=$(cat $setup_path/nginx/conf.d/waf/mysql_default.pl)
    elif docker ps -a |grep -w $MYSQL_NAME 2>&1 >/dev/null ; then
        MYSQL_ROOT_PASSWORD=$(docker inspect $MYSQL_NAME |grep MYSQL_ROOT_PASSWORD)
        MYSQL_PASS=$(echo "$MYSQL_ROOT_PASSWORD" | sed -n 's/.*MYSQL_ROOT_PASSWORD=\([^",]*\).*/\1/p')
        # echo "$MYSQL_PASS"
        echo "$MYSQL_PASS" > $setup_path/nginx/conf.d/waf/mysql_default.pl
    else
        echo -e "\033[31m无法获取到 $MYSQL_NAME 密码，重载失败。\033[0m"
        exit 1
    fi

    # MYSQL
    if [ "$mysql_container_exists" == "1" ]; then
        echo -e "$MYSQL_NAME 容器,正在重载..."
        if [ -s "/etc/init.d/btw" ]; then
            /etc/init.d/btw ${MYSQL_NAME}_reload
        elif [ -f "${setup_path}/btw.init" ]; then
            bash ${setup_path}/btw.init ${MYSQL_NAME}_reload
            \cp -arpf ${setup_path}/btw.init /etc/init.d/btw
            chmod +x /etc/init.d/btw
        else
            docker exec $MYSQL_NAME mysqladmin -uroot -p${MYSQL_PASS} reload >/dev/null 2>&1
        fi
    fi

}

Check_Connect_mysql(){

    MAX_RETRIES=10
    retries=0

    while [ $retries -lt $MAX_RETRIES ]; do
        # 使用的错误密码
        output=$(docker exec -i $MYSQL_NAME mysql -u root -p"test" -e " SHOW DATABASES;" 2>&1)
        connect_mysql=$(echo "$output" |grep "connect to local MySQL server")
        
        # connect_mysql 为空时，终止循环
        if [ -z "$connect_mysql" ]; then
            mysql_run="1"
            break
        fi

        retries=$((retries + 1))

        echo "MySQL is not running. mysql未启动完成,10秒后再尝试..."
        echo "$connect_mysql"
        wait_msg="请耐心等待"
        wait_time="10"
        Bored_waiting
        
    done

    if [ $retries -ge $MAX_RETRIES ]; then
        echo -e "\033[31m ERROR: 超过最大重试次数,无法连接到MySQL.\033[0m"
    fi

}

init_CloudWaf(){
    echo -e "正在检查用户是否存在..."
    #检查用户是否存在
    cd $waf_path
    chmod 700 $waf_path/CloudWaf
    user_status=$($waf_path/CloudWaf default_user_created)
    # echo "$user_status"
    if [ "$user_status" = "0" ]; then
        #用户不存在时创建新用户
        default_user=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8 )
        default_password=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8 )
    
        create_user=$($waf_path/CloudWaf create_default_user "${default_user}" "${default_password}")
        get_username=$($waf_path/CloudWaf get_username)
        echo default_user: "$get_username"
        if [[ "$default_user" != "$get_username" ]]; then
            echo default_user: "$default_user"
            echo create_user: "$create_user" 
            echo get_username: "$get_username" 
            Red_Error "ERROR: 创建用户失败！"
        fi

        password_check=$(echo "$create_user" |grep "password:"|awk -F ":" '{print $2}'|awk '{print $1}')
        echo default_password: "$password_check"
        if [ -z "$password_check" ]; then
            echo create_user: "$create_user"
            echo default_password_check: "$password_check"
            Red_Error "ERROR: 创建用户失败，密码为空！"
        fi

        echo -e "\033[31m已经创建新用户与密码：\033[0m"
        echo username: "$get_username"
        echo password: "$password_check"
    fi

    # 检查是否可以连接到mysql
    Check_Connect_mysql

    check_database=$(ls "$setup_path/mysql/data/" |grep -w btwaf)
    if [ -z "$check_database" ]; then
        create_database="0"
    fi

    if [ "$mysql_run" == "1" ]; then
        check_database=$(docker exec -i $MYSQL_NAME mysql -u root -p"$MYSQL_PASS" -e " SHOW DATABASES LIKE 'btwaf';" 2>&1 )
        database=$(echo "$check_database" |grep btwaf)
        if [ -z "$database" ]; then
            create_database="0"
        fi
    fi

    if [ "$create_database" == "0" ] && [ "$mysql_run" == "1" ]; then
    # 数据库不存在时，导入数据
        # echo -e "正在导入数据中"
        # wait_msg="请耐心等待"
        # wait_time="10"
        # Bored_waiting

        MAX_RETRIES=10
        retries=0

        while [ $retries -lt $MAX_RETRIES ]; do
        if docker exec -i $MYSQL_NAME mysql -u root -p"$MYSQL_PASS" -e " SHOW DATABASES;"  >/dev/null 2>&1; then
            # echo "正在导入数据中,请耐心等待..."
            echo -e "\033[31m 数据库不存在,正在导入数据中,请耐心等待...\033[0m"

            output=$(docker exec -i $MYSQL_NAME mysql -u root -p"$MYSQL_PASS" -e "CREATE DATABASE btwaf CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;" 2>&1 )
            if [ $? -ne "0" ]; then
                echo "$output"
                Red_Error "ERROR: Failed create database!" "ERROR: 创建数据库失败！"
            fi

            output=$(docker exec -i $MYSQL_NAME mysql -u root -p"$MYSQL_PASS" btwaf < $setup_path/nginx/conf.d/waf/inc/request_total.sql 2>&1 )
            if [ $? -ne "0" ]; then
                echo "$output"
                Red_Error "ERROR: Failed import database!" "ERROR: 导入数据库失败"
            fi

            output=$(docker exec -i $MYSQL_NAME mysql -u root -p"$MYSQL_PASS" btwaf < $setup_path/nginx/conf.d/waf/inc/btwaf_black.sql 2>&1 )
            if [ $? -ne "0" ]; then
                echo "$output"
                Red_Error "ERROR: Failed import database2!" "ERROR: 导入数据库失败2"
            fi

            #重启nginx
            /etc/init.d/btw ${NGINX_NAME}_restart

            break
        else
            echo "MySQL is not running. mysql未启动完成,10秒后再尝试..."
            wait_msg="请耐心等待"
            wait_time="10"
            Bored_waiting
            retries=$((retries+1))
        fi
        done

        if [ $retries -ge $MAX_RETRIES ]; then
            echo "超过最大重试次数,无法连接到MySQL."
            Red_Error "Error: 导入数据库出错."
        fi

    fi


    #启动管理界面与四层拦截
    /etc/init.d/btw ip_restart
    if [ $? -ne "0" ]; then
        echo -e "ERROR: ipfilter出错,正在输出进程,日志信息"
        tail -n 10 ${waf_path}/logs/ipfilter_error.log
        ps aux|grep -v grep|grep -v panel|grep "ipfilter"

        echo "正在尝试重启ipfilter..."
        sleep 5
        /etc/init.d/btw ip_restart
        if [ $? -ne "0" ]; then
            echo "ERROR: 启动ipfilter出错！"
        fi
    fi

    sleep 5
    /etc/init.d/btw admin_restart
    if [ $? -ne "0" ]; then
        echo -e "ERROR: 启动堡塔云WAF管理界面出错,正在输出进程,日志信息"
        tail -n 10 ${waf_path}/logs/error.log

        current_date=$(date +"%Y%m/%d")
        tail -n 10 ${waf_path}/logs/debug/${current_date}.log
        echo ""
        ps aux|grep -v grep|grep -E "${waf_path}|CloudWaf"
        ss -tulnp|grep ${WAF_Port}

        echo "正在尝试重启堡塔云WAF管理界面..."
        sleep 5
        /etc/init.d/btw admin_restart
        if [ $? -ne "0" ]; then
            Red_Error "ERROR: 启动堡塔云WAF管理界面出错！"
        fi
    fi

}


Service_Add(){
    if [ $Command_Exists systemctl ]; then
        systemctl daemon-reload
        systemctl enable btw
    else
        if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then
            chkconfig --add btw
            chkconfig --level 2345 btw on            
        elif [ "${PM}" == "apt-get" ]; then
            update-rc.d btw defaults
        fi
    fi
}

Offline_Install_Check(){
    cd ${PWD_d}

    if [[ "$Offline" == "offline" ]]; then
        echo -e "您正在使用离线模式 $Offline"
        echo -e " "
        offline_install="offline"
        
        # if [[ ! -f "$Mirror_file" ]] ; then
        #     echo -e "\033[31m "$Mirror_file" 文件不存在,请将升级脚本、${Mirror_file}、${Cloudwaf_file}放在相同的目录下\033[0m"
        #     #不支持带有目录,如：bash /tmp/update_cloudwaf.sh offline，否则无法找到文件
        #     echo -e "\033[31m最后执行此命令进行安升级塔云WAF： bash update_cloudwaf.sh offline \033[0m"
        #     echo -e "推荐使用更方便的在线升级命令(需要连接互联网)：bash update_cloudwaf.sh "
        #     exit 1
        # fi

        if [[ ! -f "${Cloudwaf_file}" ]] && [[ "$Fix_Container" != "fix_nginx" ]]; then
            echo -e "\033[31m "${Cloudwaf_file}" 文件不存在,\n请将 update_cloudwaf.sh、"${Cloudwaf_file}" 放在相同的目录下\033[0m"
            #不支持带有目录,如：bash /tmp/update_cloudwaf.sh offline，否则无法找到文件
            echo "${Cloudwaf_file}下载地址: https://download.bt.cn/cloudwaf/package/${Cloudwaf_file}"
            echo -e "\033[31m最后执行此命令进行安升级塔云WAF： bash update_cloudwaf.sh offline \033[0m"
            echo -e "推荐使用更方便的在线升级命令(需要连接互联网)：bash update_cloudwaf.sh "
            exit 1
        fi
        
    fi
}

Offline="${1}"
if [[ "${1}" == "fix_nginx" ]]; then
    Fix_Container="${1}"
else
    Fix_Container="${2}"
fi

#检查是否存在WAF类型
Check_Waf_Type
if [[ "$Slave" == "yes" ]]; then  
    # 有堡塔云WAF集群：被控
    echo -e "\033[33m不支持在被控上执行堡塔云WAF单机版升级命令。\033[0m"
    exit 1;
fi

if [[ "$Master" == "yes" ]]; then  
    # 有堡塔云WAF集群：主控
    echo -e "\033[33m不支持在主控上执行堡塔云WAF单机版升级命令。\033[0m"
    exit 1;
fi

Update_Waf(){

    Check_Port
    Get_Pack_Manager
    Docker_Status_Check

    if [ "$offline_install" != "offline" ]; then
        get_node_url
    fi

    Container_Check

    # Check_Sys_Write
    Check_Disk_Space
    Check_Sys_Packs



    Download_Copy_Files
    Install_Mirror
    Start_Monitor
    
    sleep 3

    Container_All_Status
    init_CloudWaf
    Service_Add

    # Set_Firewall
    # Get_Ip_Address

    version=$(cat $waf_path/.ver)
    echo ""
    echo "堡塔云WAF已升级到 "$version" 版本"

}

Fix_Containers(){
    if [[ "$Fix_Container" == "fix_nginx" ]]; then
        
        echo -e " 正在修复容器中... "
        Fix_Container="fix_nginx"

        Check_Port
        Get_Pack_Manager
        Docker_Status_Check
        Images_Check
        if [ "$offline_install" != "offline" ]; then
            get_node_url
        fi

        Container_Check

        Check_Disk_Space
        Check_Sys_Packs

        # Create_Nginx_Container

        # Start_Monitor
        
        sleep 3

        Container_All_Status
    fi    

}

# 离线检查
Offline_Install_Check "$@"



if [[ "$Fix_Container" == "fix_nginx" ]]; then
    # 容器修复，目前仅nginx
    Fix_Containers "$@"
else
    # 升级WAF,默认
    Update_Waf
fi
