#!/bin/bash

function showfunc() {
    # 支持的功能项
    opt00="|00. Status Code"
    opt01="|01. Respond Time"
    opt02="|02. First Dur"
    opt03="|03. Error Code"
    opt04="|04. Remote IP"
    opt05="|05. Client IP"
    opt06="|06. Method"
    opt07="|07. Protocol"
    opt08="|08. TOP URL"
    opt09="|09. Upstream Addr"
    opt10="|10. Upstream RT"
    opt11="|11. Origin IP"
    opt12="|12. Combo"
    opt13="|13. Referer"
    opt14="|14. UA"
    opt15="|15. Log"
    opt16="|16. QPS"
    opt17="|17. -"
    opt18="|18. -"
    opt19="|19. -"
    opt20="|20 -"
    opt21="|21 -"
    opt22="|22 -"
    opt23="|23 -"
    opt24="|24 -"
    opt25="|25 -"
    opt26="|26 -"
    opt27="|27 -"
    opt28="|28. First Dur"
    opt29="|29. Combo"
    opt30="|30. Client(NG) IP"
    opt31="|31. Origin IP"
    opt32="|32. Source SC"
    opt33="|33. Status Code"
    opt34="|34. Origin URL"
    opt35="|35. QPS"
    opt36="|36. Log"
    opt37="|37. Source CT"
    opt38="|38. Source RT"
    opt39="|39. -"
    opt40="|40. -"
    opt41="|41. -"
    optA="ACCESS --> "
    optO="ORIGIN --> "
    fmt="${c_bib}%-10s${c_e}%-17s%-18s%-19s%-17s%-15s%-17s%-19s\n"
    printf $fmt "$optA" "$opt00" "$opt01" "$opt02" "$opt03" "$opt04" "$opt05" "$opt06"
    printf $fmt "$optA" "$opt07" "$opt08" "$opt09" "$opt10" "$opt11" "$opt12" "$opt13"
    printf $fmt "$optA" "$opt14" "$opt15" "$opt16" "$opt17" "$opt18" "$opt19" "$opt20"
    echo '------------------------------------------------------------------------------------------------------------------------------------'
    printf $fmt "$optO" "$opt28" "$opt29" "$opt30" "$opt31" "$opt32" "$opt33" "$opt34"
    printf $fmt "$optO" "$opt35" "$opt36" "$opt37" "$opt38" "$opt39" "$opt40" "$opt41"
}


function usage() {
    echo -e "${c_bg}本工具实现指定域名&节点的${c_bc}一小时粒度${c_bg}日志搜索相关功能：${c_e}\n"
    showfunc && echo
    echo -e "${c_by}调用方法 -- logs domain node/IP [0|1]${c_e}"
    echo -e "${c_by}  param 1 - 要查询的域名${c_e}"
    echo -e "${c_by}  param 2 - 必须是边缘/父/中心的节点中英文名称或者IP${c_e}"
    echo -e "${c_by}  param 3 - 可选，存在域名在平台显示为重叠实际却在通用资源池的情况，日志不会带accid，或者反之，可以使用1或0强制指定带或不带accid${c_e}"
    # echo -e "${c_by}易混淆解释：${c_e}"
    # echo -e "${c_by}  Upstream Addr -- 后端代理服务器IP和端口${c_e}"
    # echo -e "${c_by}  Source SC ------ 源站返回的状态码${c_e}"
    # echo -e "${c_by}  Source CT ------ 与源站建立连接的时间${c_e}"
    # echo -e "${c_by}  Source RT ------ 源站的响应时间${c_e}"
    # echo -e "${c_by}  Remote IP ------ 过滤节点VIP访问次数，查看负载是否均衡${c_e}"
    # echo -e "${c_by}  Origin IP ------ 对于ACCESS日志，是回上层IP；对于ORIGIN日志，是回上层或回源IP${c_e}"
    # echo -e "${c_by}  Log ----------- 从每个RIP随机获取一条日志，可指定状态码${c_e}"
    # echo -e "${c_by}  QPS ------------ 获取每个RIP节点指定时间内的访问次数，而非真正QPS，可自行手动计算${c_e}"
    echo
    echo -e "${c_br}对于输出百分比的部分，除了状态码类以及时间类的功能，其他选项都是过滤了TOP10，所以可能会出现比例之和小于1的情况；另外，当前仅支持常规CDN以及L1-7格式的日志搜寻，暂不支持直播/安全/quic等，使用过程中遇到任何问题，可以联系fanmf11@chinatelecom.cn反馈${c_e}"
    exit 222
}

function logfile() {
    if [[ -d $trash ]]; then
        echo -e "${c_br}对于同一个用户，同一时间只能运行一个实例，请重新运行...${c_e}"
        exit 245
    else
        mkdir -p $trash
        cd $trash && cd ..
        docs=`ls`
        for doc in $docs; do
            [[ -f $doc ]] && rm -rf $doc
        done
        folders=`ls -t`
        while [[ `echo $folders | awk '{print NF}'` -gt 29 ]]; do
            folder=`ls -t | tail -1`
            rm -rf $folder
            folders=`ls -t`
        done
        cd $trash && touch logs
    fi
}

function onCtrlC () {
  # while capture Ctrl+C, kill all background processes silently and exit
  exec 3>&2          # 3 is now a copy of 2
  exec 2> /dev/null  # 2 now points to /dev/null
  sleep 1            # sleep to wait for process to die
  exec 2>&3          # restore stderr to saved
  exec 3>&-          # close saved version
  echo
  echo -e "${c_bir}Ctrl+C is captured, exiting...\n${c_e}"
  exit 101
}

function initial() {
    # --------------------------------------------------------------------------------
    # 入参正确性检测
    let numOP=$#                                    # number of parameter
    OP="prefix "$@                                  # do a prefix cause '-' char may damage echo command
    domain=`echo $OP | awk '{print $2}'`            # get first param domain
    label=`echo $OP | awk '{print $3}'`             # get second param nodename or ip
    accsw=`echo $OP | awk '{print $4}'`             # get thied param, forcely acc var, 1 -- acc=reqid, 0 -- acc='-'
    [[ $numOP -ne 2 && $numOP -ne 3 ]] && usage || logfile
    # --------------------------------------------------------------------------------
    # 检查域名是否在平台注册
    res=`cat $data/domain.list | grep -w "$domain"`
    [[ $res == '' ]] && { echo -e "${c_br}该域名未在天翼平台配置，一个小时内新增的域名无法查询，退出...${c_e}"; exit 247; }

    # --------------------------------------------------------------------------------
    # 获取正确的label
    ips $label > ips.log 2>&1
    # 如果不是天翼IP，否则重新回到工作目录$trash
    [[ $? -ne 0 ]] && { cd $trash; cat ips.log; exit 114; } || cd $trash

    # --------------------------------------------------------------------------------
    # 检查是否是重叠域名，并获取正确的解析组
    infos --map $domain $TS
    [[ $? -eq 205 || $? -eq 231 ]] && exit 205

    cd $trash
    if [[ `cat map.log | wc -l` -eq 1 ]]; then
        map=`cat map.log`
    else
        maps=`cat map.log | sort | uniq`
        count=1 && > remap.log
        for map in $maps; do
            echo $count": "$map | tee -a remap.log
            let count=count+1
        done
        echo -ne "${c_bg}存在分区域解析，需确定解析组名称(默认是1)：${c_e}\n"
        read -t 60 imap
        [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...${c_e}\n"; exit 102; }
        # do a check to see if isp is correct or not
        [[ $imap == '' ]] && let imap=1
        map=`cat remap.log | awk -F ':' -v imap=$imap '$1==imap {print $2}'`
        [[ $map == '' ]] && { echo -e "${c_br}请输入正确的序号，退出...${c_e}"; exit 165; }
    fi
        
    getlastcover $map > map.log
    cat map.log | grep -q 'can not find sys_id'
    [[ $? -eq 0 ]] && { echo -e "${c_br}该解析组未在平台配置，退出..."; exit 163; }

    accid=`cat info.log | awk -F ':' '$1==3 {print $2}'`
    overlap=`cat $data/domain.list | grep $accid | grep $domain |  awk -F ',' '{print $17}'`
    [[ $overlap == '"是"' ]] && overlap=1 || overlap=0
    # 因为有些域名系统显示是重叠域名，实际日志并没有带accid，因为用的通用资源池
    if [[ $accsw != "" && $accsw -eq 0 ]]; then
        ida='-'
    elif [[ $accsw != "" && $accsw -eq 1 ]]; then
        ida=$accid
    elif [[ $overlap -eq 0 ]]; then
        ida='-'
    elif [[ $overlap -eq 1 ]]; then
        ida=$accid
    fi

    # --------------------------------------------------------------------------------
    # 检查是否是英文标签的格式，是的话，保持label原值，否则做进一步操作
    echo $label | grep -Eq "(ct|cu|cm|bgp|ctbgp|cmbgp|cubgp|as|eu|sa|na|cbn|cern)_[a-z]{2,3}_[a-z]{2,20}[0-9]{1,2}_(c|e|n)[0-9]{0,2}"
    if [[ $? -eq 0 ]]; then
        label=$label
    else
        # 获取所有相关英文标签
        labels=`cat ips.log | grep -Eo "(ct|cu|cm|bgp|ctbgp|cmbgp|cubgp|as|eu|sa|na|cbn|cern)_[a-z]{2,3}_[a-z]{2,20}[0-9]{1,2}_(c|e|n)[0-9]{0,2}" | sort | uniq`
        [[ $labels == "" ]] && { echo -e "${c_bir}请输入正确的边缘/父层/中心节点的IP或者中英文节点名称，退出...${c_e}"; exit 232; }
        # 如果有多个匹配，则让用户确认是哪个
        if [[ `echo $labels | awk '{print NF}'` -gt 1 ]]; then
            for item in $labels; do
                cat map.log | grep -wq $item
                [[ $? -eq 0 ]] && echo -e "${c_biy}  - $item${c_e}" || echo "  - $item"
            done
            echo -e "${c_bp}输入的 ${c_by}$label${c_bp} 边缘节点中有两个组，请确认具体是哪个：${c_e}"
            read -t 60 label_input
            # 判断60s内无输入，则自动退出
            [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...\n${c_e}"; exit 116; }
            # 判断输入信息是否是正确的
            echo $labels | grep -wq $label_input
            [[ $? -ne 0 ]] && { echo -e "${c_br}需要从如上选择正确的边缘节点信息，请重新运行，退出...\n${c_e}"; exit 117; }
            label=$label_input
        # 否则，获取label
        else
            label=$labels
        fi
    fi
    cat map.log | grep -wq $label
    if [[ $? -ne 0 ]]; then
        echo -e "${c_by}${label}${c_bc}不在$domain的解析组内，判断是否是父层节点(y/N)：${c_e}"
        read -t 60 isc
        # 判断60s内无输入，则自动退出
        [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...\n${c_e}"; exit 116; }
        # 判断输入信息是否是正确的
        [[ $isc == 'n' || $isc == 'N' || $isc == 'no' || $isc == 'No' || $isc == 'NO' ]] && exit 234
    fi

    # --------------------------------------------------------------------------------
    # 获取rip_list
    ips $label > ips.log 2>&1 && cd $trash
    rip_list=`cat ips.log | sed -n '/RIP/, /VIP/p' | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" | sort | uniq`

    # 60s时间接收输入：要查询的时间
    echo -e "${c_bg}请输入要查询的reqID生成时间，格式为yyyymmddHH(默认当前 - $(date +%Y%m%d%H)): ${c_e} "
    read -t 60 time_range
    [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...\n${c_e}"; exit 105; }
    time_check
    type_inp
}

#=======================================================================================
# 功能：获取查询指标
# 入参：None
# 出参：itype
function type_inp() {
    # 60s时间接收输入：要查询的类型
    showfunc
    echo -e "${c_bg}请输入要查询的指标(默认00)： ${c_e}"
    read -t 60 itype
    [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...\n${c_e}"; exit 122; }
    [[ $itype == '' ]] && itype='00'


    # 60s时间接收输入：要查询的类型
    echo -e "1. 静态/下载/点播/全站(default - v03/ov06)"
    echo -e "2. 直播(ACC1/2/3)"
    echo -e "3. 安全"
    echo -e "4. quic"
    echo -e "5. L1/L2/L3/L4/L5/L6/L7(e.g. 查询L3，则输入5.3)"
    echo -e "${c_bg}请输入要查询的业务类型(默认1，目前仅支持1/5)： ${c_e}"
    read -t 60 ptype
    [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...\n${c_e}"; exit 122; }
    [[ $ptype == '' ]] && ptype='1'
    # 根据业务类型，指定前缀
    [[ $ptype == '1' ]] && prefix=''
    [[ $ptype == '5.1' ]] && prefix='L1_'
    [[ $ptype == '5.2' ]] && prefix='L2_'
    [[ $ptype == '5.3' ]] && prefix='L3_'
    [[ $ptype == '5.4' ]] && prefix='L4_'
    [[ $ptype == '5.5' ]] && prefix='L5_'
    [[ $ptype == '5.6' ]] && prefix='L6_'
    [[ $ptype == '5.7' ]] && prefix='L7_'
}

#=======================================================================================
# 功能：检查输入的时间范围是否符合格式要求：14天内，不能是未来时间，10位数字
# 入参：time_range
# 出参：current, year, month, day, hour, time_range
function time_check() {
    # 如果入参 time_range 的值是空，或者说函数没有入参
    if [[ $time_range == '' ]]; then
        time_range=`date +%Y%m%d%H`
        year=${time_range:0:4}
        month=${time_range:4:2}
        day=${time_range:6:2}
        hour=${time_range:8:2}
        current='yes'
        return 0
    fi

    # 检查入参是否正确：长度，表示的时间范围等
    [[ ! $time_range =~ ^[0-9]{10}$ ]] && { echo -e "${c_br}请输入正确的时间格式，退出...\n${c_e}"; exit 106; }
    # 验证入参是10天以内的时间范围
    now=`date +%s`
    # 准备工作，后续要用
    year=${time_range:0:4}
    month=${time_range:4:2}
    day=${time_range:6:2}
    hour=${time_range:8:2}
    # 将入参转换为秒
    previous=`date -d "$year-$month-$day $hour:00:00" +"%s"`
    # 计算当前时间 - 入参时间
    let range_s=now-previous
    let range_d=range_s/86400
    # 如果是14天以外的入参时间，则不可查
    [[ $range_d -gt 10 ]] && { echo -e "${c_br}只能查找最近10天以内的日志记录，退出...\n${c_e}"; exit 107; }
    # 判断 time_range 是否是当前时间，并用 current 来标识，默认是当前，即 current = yes
    [[ $time_range == `date +%Y%m%d%H` ]] && current='yes' || current='no'
}

function is_sc_specified() {
    # 是否指定状态码
    echo -e "${c_bb}直接回车默认过滤所有状态码，是否需要指定(000~999)：${c_e}"
    read -t 60 sc
    # 判断60s内无输入，则自动退出
    [[ $? -ne 0 ]] && { echo -e "${c_br}60s内无任何输入，退出...\n${c_e}"; exit 116; }
    # 判断输入信息是否是正确的，当输入的状态码是空，则不做过滤，全部输出

    if [[ $sc != "" ]]; then
        echo $sc | grep -Eq "[0-9]{1,3}"
        [[ $? -ne 0 ]] && { echo -e "${c_br}需要指定正确的状态码值，退出...\n${c_e}"; exit 117; }
    fi
}

function cdn_access_common() {
    field=$1
    is_sc_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索core_access.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进access_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log | grep $domain;
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logcommon.awk | sort -nk2 | \
                sort -nk2 | tail > access_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain;
            zcat $cdn_access_log/$year$month$day/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logcommon.awk | sort -nk2 | \
                sort -nk2 | tail > access_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat access_$rip && echo
    done
}

function cdn_access_time() {
    field=$1
    is_sc_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索core_access.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进access_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log | grep $domain;
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logtime.awk | \
                sort -nk3 > access_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain;
            zcat $cdn_access_log/$year$month$day/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logtime.awk | \
                sort -nk3 > access_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat access_$rip && echo
    done
}

function cdn_access_sc() {
    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索core_access.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进access_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log | grep $domain;
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v acc="$ida" -v pos=4 -f $toolbox/logsc.awk | \
                sort -nk1 | column -t > access_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain;
            zcat $cdn_access_log/$year$month$day/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v acc="$ida" -v pos=4 -f $toolbox/logsc.awk | \
                sort -nk1 | column -t > access_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait
    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat access_$rip && echo
    done
}

function cdn_access_qps() {
    is_sc_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索core_access.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进access_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log | grep $domain;
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v code="$sc" -v acc="$ida" -f $toolbox/logqps.awk | \
                sort -nk1 | column -t > access_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain;
            zcat $cdn_access_log/$year$month$day/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v code="$sc" -v acc="$ida" -f $toolbox/logqps.awk | \
                sort -nk1 | column -t > access_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat access_$rip && echo
    done
}

function is_access_condtion_specified() {
    # 是否指定过滤条件
    echo -e "${c_bb}根据如上对应组件的过滤功能，可查询符合特定组合条件的日志占比，格式如下${c_e}"
    echo -e "${c_big}00: 404"
    echo -e "02: 0-1"
    echo -e "03: 2"
    echo -e "04: 59.56.177.149"
    echo -e "06: Post"
    echo -e "08: https://www.ctyun.cn"
    echo -e "14: Chrome/54.0 (Windows NT 10.0)${c_e}"
    echo -e "${c_bic}Ctrl + D${c_e}"
    echo -e "${c_by}每行对应一个条件，Ctrl + D结束输入：${c_e}"
    cat > combo.log
    echo "" >> combo.log
    echo -e "${c_bb}\n正在处理中...${c_e}"

    f00=""; f01=""; f02=""; f03=""; f04=""; f05=""; f06=""; f07=""; f08=""; f09=""; f10=""; f11=""; f13="";
    f14=""; f01s=""; f02s=""; f10s=""; f01e=""; f02e=""; f10e=""
    while read line; do
        [[ $line == "" ]] && continue
        index=`echo $line | awk -F ':' '{print $1}'`
        filter=${line:3}
        [[ "$index" == '00' ]] && { f00=$filter; continue; }
        [[ "$index" == '01' ]] && { f01=$filter; continue; }
        [[ "$index" == '02' ]] && { f02=$filter; continue; }
        [[ "$index" == '03' ]] && { f03=$filter; continue; }
        [[ "$index" == '04' ]] && { f04=$filter; continue; }
        [[ "$index" == '05' ]] && { f05=$filter; continue; }
        [[ "$index" == '06' ]] && { f06=$filter; continue; }
        [[ "$index" == '07' ]] && { f07=$filter; continue; }
        [[ "$index" == '08' ]] && { f08=$filter; continue; }
        [[ "$index" == '09' ]] && { f09=$filter; continue; }
        [[ "$index" == '10' ]] && { f10=$filter; continue; }
        [[ "$index" == '11' ]] && { f11=$filter; continue; }
        [[ "$index" == '13' ]] && { f13=$filter; continue; }
        [[ "$index" == '14' ]] && { f14=$filter; continue; }
        echo -e "${c_bir}[Ignored]${c_e} -- $line"
    done < combo.log

    # 处理时间类参数，只允许区间参数
    [[ $f01 != "" ]] && { f01s=`echo $f01 | awk -F '-' '{print $1}'`; f01e=`echo $f01 | awk -F '-' '{print $2}'`; }
    [[ $f02 != "" ]] && { f02s=`echo $f02 | awk -F '-' '{print $1}'`; f02e=`echo $f02 | awk -F '-' '{print $2}'`; }
    [[ $f10 != "" ]] && { f10s=`echo $f10 | awk -F '-' '{print $1}'`; f10e=`echo $f10 | awk -F '-' '{print $2}'`; }
    echo
}

function cdn_access_combo() {
    is_access_condtion_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索core_access.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进access_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log | grep $domain;
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v acc="$ida" -v f00="$f00" -v f01="$f01" -v f02="$f02" -v f03="$f03" \
                -v f04="$f04" -v f05="$f05" -v f06="$f06" -v f07="$f07" -v f08="$f08" -v f09="$f09" -v f10="$f10" -v f11="$f11" \
                -v f13="$f13" -v f14="$f14" -v f01s="$f01s" -v f01e="$f01e" -v f02s="$f02s" -v f02e="$f02e" -v f10s="$f10s" \
                -v f10e="$f10e" -v atype="combo" -f $toolbox/logcombo.awk | \
                sort -nk1 | column -t > access_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain;
            zcat $cdn_access_log/$year$month$day/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v acc="$ida" -v f00="$f00" -v f01="$f01" -v f02="$f02" -v f03="$f03" \
                -v f04="$f04" -v f05="$f05" -v f06="$f06" -v f07="$f07" -v f08="$f08" -v f09="$f09" -v f10="$f10" -v f11="$f11" \
                -v f13="$f13" -v f14="$f14" -v f01s="$f01s" -v f01e="$f01e" -v f02s="$f02s" -v f02e="$f02e" -v f10s="$f10s" \
                -v f10e="$f10e" -v atype="combo" -f $toolbox/logcombo.awk | \
                sort -nk1 | column -t > access_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat access_$rip && echo
    done
}

function cdn_access_logs() {
    is_access_condtion_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索core_access.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进access_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log | grep $domain;
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v acc="$ida" -v f00="$f00" -v f01="$f01" -v f02="$f02" -v f03="$f03" \
                -v f04="$f04" -v f05="$f05" -v f06="$f06" -v f07="$f07" -v f08="$f08" -v f09="$f09" -v f10="$f10" -v f11="$f11" \
                -v f13="$f13" -v f14="$f14" -v f01s="$f01s" -v f01e="$f01e" -v f02s="$f02s" -v f02e="$f02e" -v f10s="$f10s" \
                -v f10e="$f10e" -v atype="logs" -f $toolbox/logcombo.awk | \
                grep -Ev "$hour:(59|00):[0-5][0-9] \+0800" | head -n $((number % 1000)) | tail -n 1 > access_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_access_log/${prefix}core_access.log_*${time_range}* | grep $domain;
            zcat $cdn_access_log/$year$month$day/${prefix}core_access.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=1 -v acc="$ida" -v f00="$f00" -v f01="$f01" -v f02="$f02" -v f03="$f03" \
                -v f04="$f04" -v f05="$f05" -v f06="$f06" -v f07="$f07" -v f08="$f08" -v f09="$f09" -v f10="$f10" -v f11="$f11" \
                -v f13="$f13" -v f14="$f14" -v f01s="$f01s" -v f01e="$f01e" -v f02s="$f02s" -v f02e="$f02e" -v f10s="$f10s" \
                -v f10e="$f10e" -v atype="logs" -f $toolbox/logcombo.awk | \
                grep -Ev "$hour:(59|00):[0-5][0-9] \+0800" | head -n $((number % 1000)) | tail -n 1 > access_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat access_$rip && echo
    done
}

function cdn_origin_common() {
    field=$1
    is_sc_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索origin.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进origin_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log | grep $domain;
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logcommon.awk | \
                sort -nk2 | tail > origin_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain;
            zcat $cdn_origin_log/$year$month$day/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logcommon.awk | \
                sort -nk2 | tail > origin_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat origin_$rip && echo
    done
}


function cdn_origin_time() {
    field=$1
    is_sc_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh进每一个rip，搜索origin.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进origin_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log | grep $domain;
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logtime.awk | \
                sort -nk3 > origin_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain;
            zcat $cdn_origin_log/$year$month$day/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v code="$sc" -v acc="$ida" -v pos="$field" -f $toolbox/logtime.awk | \
                sort -nk3 > origin_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat origin_$rip && echo
    done
}

function cdn_origin_sc() {
    [[ $1 == 'sc' ]] && field=11
    [[ $1 == 'ssc' ]] && field=10
    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索origin.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进origin_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log | grep $domain;
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v acc="$ida" -v pos="$field" -f $toolbox/logsc.awk | \
                sort -nk1 | column -t > origin_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain;
            zcat $cdn_origin_log/$year$month$day/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v acc="$ida" -v pos="$field" -f $toolbox/logsc.awk | \
                sort -nk1 | column -t > origin_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait
    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat origin_$rip && echo
    done
}

function cdn_origin_qps() {
    is_sc_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索origin.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进origin_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log | grep $domain;
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v code="$sc" -v acc="$ida" -f $toolbox/logqps.awk | \
                sort -nk1 | column -t > origin_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain;
            zcat $cdn_origin_log/$year$month$day/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v code="$sc" -v acc="$ida" -f $toolbox/logqps.awk | \
                sort -nk1 | column -t > origin_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat origin_$rip && echo
    done
}

function is_origin_condtion_specified() {
    # 是否指定过滤条件
    echo -e "${c_bb}根据如上对应组件的过滤功能，可查询符合特定组合条件的日志占比，格式如下${c_e}"
    echo -e "${c_big}28: 0-1"
    echo -e "31: 59.56.177.149"
    echo -e "33: 404"
    echo -e "34: https://www.ctyun.cn"
    echo -e "${c_bic}Ctrl + D${c_e}"
    echo -e "${c_by}每行对应一个条件，Ctrl + D结束输入：${c_e}"
    cat > combo.log
    echo "" >> combo.log
    echo -e "${c_bb}\n正在处理中...${c_e}"

    f28=""; f30=""; f31=""; f32=""; f33=""; f34=""; f37=""; f38=""; f28s=""; f28e=""; f37s=""; f37e=""; f38s=""; f38e=""
    while read line; do
        [[ $line == "" ]] && continue
        index=`echo $line | awk -F ':' '{print $1}'`
        filter=${line:3}
        [[ "$index" == '28' ]] && { f28=$filter; continue; }
        [[ "$index" == '30' ]] && { f30=$filter; continue; }
        [[ "$index" == '31' ]] && { f31=$filter; continue; }
        [[ "$index" == '32' ]] && { f32=$filter; continue; }
        [[ "$index" == '33' ]] && { f33=$filter; continue; }
        [[ "$index" == '34' ]] && { f34=$filter; continue; }
        [[ "$index" == '37' ]] && { f37=$filter; continue; }
        [[ "$index" == '38' ]] && { f38=$filter; continue; }
        echo -e "${c_bir}[Ignored]${c_e} -- $line"
    done < combo.log

    # 处理时间类参数，只允许区间参数
    [[ $f28 != "" ]] && { f28s=`echo $f28 | awk -F '-' '{print $1}'`; f28e=`echo $f28 | awk -F '-' '{print $2}'`; }
    [[ $f37 != "" ]] && { f37s=`echo $f37 | awk -F '-' '{print $1}'`; f37e=`echo $f37 | awk -F '-' '{print $2}'`; }
    [[ $f38 != "" ]] && { f38s=`echo $f38 | awk -F '-' '{print $1}'`; f38e=`echo $f38 | awk -F '-' '{print $2}'`; }
    echo
}

function cdn_origin_combo() {
    is_origin_condtion_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索origin.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进origin_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log | grep $domain;
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v acc="$ida" -v f28="$f28" -v f30="$f30" -v f31="$f31" -v f32="$f32" \
                -v f33="$f33" -v f34="$f34" -v f37="$f37" -v f38="$f38" -v f28s="$f28s" -v f28e="$f28e" -v f37s="$f37s" \
                -v f37e="$f37e" -v f38s="$f38s" -v f38e="$f38e" -v atype="combo" -f $toolbox/logcombo.awk | \
                sort -nk1 | column -t > origin_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain;
            zcat $cdn_origin_log/$year$month$day/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v acc="$ida" -v f28="$f28" -v f30="$f30" -v f31="$f31" -v f32="$f32" \
                -v f33="$f33" -v f34="$f34" -v f37="$f37" -v f38="$f38" -v f28s="$f28s" -v f28e="$f28e" -v f37s="$f37s" \
                -v f37e="$f37e" -v f38s="$f38s" -v f38e="$f38e" -v atype="combo" -f $toolbox/logcombo.awk | \
                sort -nk1 | column -t > origin_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat origin_$rip && echo
    done
}

function cdn_origin_logs() {
    is_origin_condtion_specified

    # 如果time_range是当前时间
    exec 3>&2 && exec 2> /dev/null
    if [[ $current == 'yes' ]]; then
        # ssh 进每一个rip，搜索origin.log，设定ssh连接超时时长为CT
        # 把搜索的结果放进origin_$rip文件，所有的ssh命令都后台执行
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log | grep $domain;
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v acc="$ida" -v f28="$f28" -v f30="$f30" -v f31="$f31" -v f32="$f32" \
                -v f33="$f33" -v f34="$f34" -v f37="$f37" -v f38="$f38" -v f28s="$f28s" -v f28e="$f28e" -v f37s="$f37s" \
                -v f37e="$f37e" -v f38s="$f38s" -v f38e="$f38e" -v atype="logs" -f $toolbox/logcombo.awk | \
                grep -Ev "$hour:(59|00):[0-5][0-9] \+0800" | head -n $((number % 1000)) | tail -n 1 > origin_${rip} &
        done
    # 如果time_range不是当前时间
    else
        # 简单粗暴地，分别过滤回滚文件和未归档两部分日志文件
        for rip in $rip_list; do
            ssh -o ConnectTimeout=$CT $rip "
            cat $cdn_origin_log/origin.log_*${time_range}* | grep $domain;
            zcat $cdn_origin_log/$year$month$day/origin.log_*${time_range}* | grep $domain" | grep $domain | \
                awk -F '"' -v comp=0 -v acc="$ida" -v f28="$f28" -v f30="$f30" -v f31="$f31" -v f32="$f32" \
                -v f33="$f33" -v f34="$f34" -v f37="$f37" -v f38="$f38" -v f28s="$f28s" -v f28e="$f28e" -v f37s="$f37s" \
                -v f37e="$f37e" -v f38s="$f38s" -v f38e="$f38e" -v atype="logs" -f $toolbox/logcombo.awk | \
                grep -Ev "$hour:(59|00):[0-5][0-9] \+0800" | head -n $((number % 1000)) | tail -n 1 > origin_${rip} &
        done
    fi
    exec 2>&3 && exec 3>&- && wait

    for rip in $rip_list; do
        echo -e "=============== ${c_biy}$label: ${c_bic}$rip${c_e} ==============="
        cat origin_$rip && echo
    done
}


# ============================================================================================================
# Part 00: Status Code
function statusCodeA() {
    if [[ $ptype == '1' ]]; then
        statusCodeA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        statusCodeA1
    else
        :
    fi
}

function statusCodeA1() {
    cdn_access_sc
}

# ============================================================================================================
# Part 01: Respond Time
function respondTimeA() {
    if [[ $ptype == '1' ]]; then
        respondTimeA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        respondTimeA1
    else
        :
    fi
}

function respondTimeA1() {
    cdn_access_time "6"
}

# ============================================================================================================
# Part 02: First Dur
function firstDurA() {
    if [[ $ptype == '1' ]]; then
        firstDurA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        firstDurA1
    else
        :
    fi
}

function firstDurA1() {
    cdn_access_time "9"
}

# ============================================================================================================
# Part 03: Error Code
function errorCodeA() {
    if [[ $ptype == '1' ]]; then
        errorCodeA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        errorCodeA1
    else
        :
    fi
}

function errorCodeA1() {
    cdn_access_common "10"
}

# ============================================================================================================
# Part 04: Remote IP
function remoteIPA() {
    if [[ $ptype == '1' ]]; then
        remoteIPA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        remoteIPA1
    else
        :
    fi
}

function remoteIPA1() {
    cdn_access_common "11"
}

# ============================================================================================================
# Part 05: Client IP
function clientIPA() {
    if [[ $ptype == '1' ]]; then
        clientIPA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        clientIPA1
    else
        :
    fi
}

function clientIPA1() {
    cdn_access_common "13"
}

# ============================================================================================================
# Part 06: Method
function methodA() {
    if [[ $ptype == '1' ]]; then
        methodA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        methodA1
    else
        :
    fi
}

function methodA1() {
    cdn_access_common "15"
}

# ============================================================================================================
# Part 07: Protocol
function protocolA() {
    if [[ $ptype == '1' ]]; then
        protocolA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        protocolA1
    else
        :
    fi
}

function protocolA1() {
    cdn_access_common "16"
}

# ============================================================================================================
# Part 08: Top URL
function topUrlA() {
    if [[ $ptype == '1' ]]; then
        topUrlA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        topUrlA1
    else
        :
    fi
}

function topUrlA1() {
    cdn_access_common "18"
}

# ============================================================================================================
# Part 09: Upstream Addr
function upstreamAddrA() {
    if [[ $ptype == '1' ]]; then
        upstreamAddrA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        upstreamAddrA1
    else
        :
    fi
}

function upstreamAddrA1() {
    cdn_access_common "24"
}

# ============================================================================================================
# Part 10: Upstream Respond Time
function upstreamRTimeA() {
    if [[ $ptype == '1' ]]; then
        upstreamRTimeA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        upstreamRTimeA1
    else
        :
    fi
}

function upstreamRTimeA1() {
    cdn_access_time "26"
}

# ============================================================================================================
# Part 11: Origin IP for NG
function originIPA() {
    if [[ $ptype == '1' ]]; then
        originIPA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        originIPA1
    else
        :
    fi
}

function originIPA1() {
    cdn_access_common "28"
}

# ============================================================================================================
# Part 12: Combo -- multi condition searching
function comboA() {
    if [[ $ptype == '1' ]]; then
        comboA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        comboA1
    else
        :
    fi
}

function comboA1() {
    cdn_access_combo
}

# ============================================================================================================
# Part 13: Referer
function refererA() {
    if [[ $ptype == '1' ]]; then
        refererA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        refererA1
    else
        :
    fi
}

function refererA1() {
    cdn_access_common "33"
}

# ============================================================================================================
# Part 14: UA
function uaA() {
    if [[ $ptype == '1' ]]; then
        uaA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        uaA1
    else
        :
    fi
}

function uaA1() {
    cdn_access_common "34"
}

# ============================================================================================================
# Part 15: Log
function logA() {
    if [[ $ptype == '1' ]]; then
        logA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        logA1
    else
        :
    fi
}

function logA1() {
    cdn_access_logs
}

# ============================================================================================================
# Part 16: QPS
function qpsA() {
    if [[ $ptype == '1' ]]; then
        qpsA1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        qpsA1
    else
        :
    fi
}

function qpsA1() {
    cdn_access_qps
}

# ============================================================================================================
# Part 28: Origin First Dur
function firstDurO() {
    if [[ $ptype == '1' ]]; then
        firstDurO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        firstDurO1
    else
        :
    fi
}

function firstDurO1() {
    cdn_origin_time "5"
}

# ============================================================================================================
# Part 29: Combo -- multi condition searching
function comboO() {
    if [[ $ptype == '1' ]]; then
        comboO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        comboO1
    else
        :
    fi
}

function comboO1() {
    cdn_origin_combo
}


# ============================================================================================================
# Part 30: Origin Client(NG) IP
function clientIPO() {
    if [[ $ptype == '1' ]]; then
        clientIPO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        clientIPO1
    else
        :
    fi
}

function clientIPO1() {
    cdn_origin_common "7"
}

# ============================================================================================================
# Part 31: Origin IP
function originIPO() {
    if [[ $ptype == '1' ]]; then
        originIPO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        originIPO1
    else
        :
    fi
}

function originIPO1() {
    cdn_origin_common "8"
}
# ============================================================================================================
# Part 32: Source Status Code
function sourceSCO() {
    if [[ $ptype == '1' ]]; then
        sourceSCO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        sourceSCO1
    else
        :
    fi
}

function sourceSCO1() {
    cdn_origin_sc "ssc"
}

# ============================================================================================================
# Part 33: Origin Status Code
function statusCodeO() {
    if [[ $ptype == '1' ]]; then
        statusCodeO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        statusCodeO1
    else
        :
    fi
}

function statusCodeO1() {
    cdn_origin_sc "sc"
}

# ============================================================================================================
# Part 34: Origin URL
function topUrlO() {
    if [[ $ptype == '1' ]]; then
        topUrlO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        topUrlO1
    else
        :
    fi
}

function topUrlO1() {
    cdn_origin_common "46"
}

# ============================================================================================================
# Part 35: Origin QPS
function qpsO() {
    if [[ $ptype == '1' ]]; then
        qpsO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        qpsO1
    else
        :
    fi
}

function qpsO1() {
    cdn_origin_qps
}


# ============================================================================================================
# Part 36: Origin Random Logs
function logO() {
    if [[ $ptype == '1' ]]; then
        logO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        logO1
    else
        :
    fi
}

function logO1() {
    cdn_origin_logs
}


# ============================================================================================================
# Part 37: Source Connection Time
function sourceCTO() {
    if [[ $ptype == '1' ]]; then
        sourceCTO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        sourceCTO1
    else
        :
    fi
}

function sourceCTO1() {
    cdn_origin_time "4"
}

# ============================================================================================================
# Part 38: Source Respond Time
function SourceRTO() {
    if [[ $ptype == '1' ]]; then
        sourceRTO1
    elif [[ $ptype == '2' ]]; then
        :
    elif [[ $ptype == '3' ]]; then
        :
    elif [[ $ptype == '4' ]]; then
        :
    elif [[ $ptype == '5.1' || $ptype == '5.2' ||  $ptype == '5.3' ||  $ptype == '5.4' ||  $ptype == '5.5' ||  $ptype == '5.6' ||  $ptype == '5.7' ]]; then
        sourceRTO1
    else
        :
    fi
}

function sourceRTO1() {
    cdn_origin_time "6"
}

# --------------------------------------------------------------------------------
# set a trap for Ctrl+C
trap 'onCtrlC' INT

# --------------------------------------------------------------------------------
# 自定义颜色显示
c_br='\e[1;31m'     # bold red
c_bg='\e[1;32m'     # bold green
c_by='\e[1;33m'     # bold yellow
c_bb='\e[1;34m'     # bold blue
c_bp='\e[1;35m'     # bold purple
c_bc='\e[1;36m'     # bold cyan
c_bir='\e[1;3;31m'  # bold italic red
c_big='\e[1;3;32m'  # bold italic green
c_biy='\e[1;3;33m'  # bold italic yellow
c_bib='\e[1;3;34m'  # bold italic blue
c_bip='\e[1;3;35m'  # bold italic purple
c_bic='\e[1;3;36m'  # bold italic cyan
c_e='\e[0m'         # reset


# --------------------------------------------------------------------------------
# 初始化设定
number=`date +%N`
CT=45
stty erase '^H'                                     # allow backspace
data='/usr/local/script/fanmf11/data'               # set data directory path
toolbox='/usr/local/script/fanmf11'                 # set toobbox directory path
TS=`date +%s%N`                                     # document the start time of the script
host=`whoami`                                       # who use this script
trash="/usr/local/script/fanmf11/trash/$host/$TS"   # set trash directory path
livelog='/home/log/cluster_live_log'
liveatslog='/home/log/trafficserver'
cdn_access_log='/home/log/cluster_gateway_log'       # *
cdn_origin_log='/home/log/trafficserver'             # *

# --------------------------------------------------------------------------------
# 初始化，获得必要的变量
initial $@

# --------------------------------------------------------------------------------
# 主程序分支
if [[ $itype == '00' ]]; then
    statusCodeA
elif [[ $itype == '01' ]]; then
    respondTimeA
elif [[ $itype == '02' ]]; then
    firstDurA
elif [[ $itype == '03' ]]; then
    errorCodeA
elif [[ $itype == '04' ]]; then
    remoteIPA
elif [[ $itype == '05' ]]; then
    clientIPA
elif [[ $itype == '06' ]]; then
    methodA
elif [[ $itype == '07' ]]; then
    protocolA
elif [[ $itype == '08' ]]; then
    topUrlA
elif [[ $itype == '09' ]]; then
    upstreamAddrA
elif [[ $itype == '10' ]]; then
    upstreamRTimeA
elif [[ $itype == '11' ]]; then
    originIPA
elif [[ $itype == '12' ]]; then
    comboA
elif [[ $itype == '13' ]]; then
    refererA
elif [[ $itype == '14' ]]; then
    uaA
elif [[ $itype == '15' ]]; then
    logA
elif [[ $itype == '16' ]]; then
    qpsA
elif [[ $itype == '17' ]]; then
    :
elif [[ $itype == '18' ]]; then
    :
elif [[ $itype == '19' ]]; then
    :
elif [[ $itype == '20' ]]; then
    :
elif [[ $itype == '21' ]]; then
    :
elif [[ $itype == '22' ]]; then
    :
elif [[ $itype == '23' ]]; then
    :
elif [[ $itype == '24' ]]; then
    :
elif [[ $itype == '25' ]]; then
    :
elif [[ $itype == '26' ]]; then
    :
elif [[ $itype == '27' ]]; then
    :
elif [[ $itype == '28' ]]; then
    firstDurO
elif [[ $itype == '29' ]]; then
    comboO
elif [[ $itype == '30' ]]; then
    clientIPO
elif [[ $itype == '31' ]]; then
    originIPO
elif [[ $itype == '32' ]]; then
    sourceSCO
elif [[ $itype == '33' ]]; then
    statusCodeO
elif [[ $itype == '34' ]]; then
    topUrlO
elif [[ $itype == '35' ]]; then
    qpsO
elif [[ $itype == '36' ]]; then
    logO
elif [[ $itype == '37' ]]; then
    sourceCTO
elif [[ $itype == '38' ]]; then
    SourceRTO
elif [[ $itype == '39' ]]; then
    :
elif [[ $itype == '40' ]]; then
    :
elif [[ $itype == '41' ]]; then
    :
else
    :
fi

