#!/bin/bash

cat <<EOF  > /dev/null
# 用法
curl -s http://script.wh.hc-yun.com:3380/install/categraf-linux.sh | bash -s -- --ins client --labels platform=linux,region=idc-sh,project=芒果备用环境
curl -s http://script.wh.hc-yun.com:3380/install/categraf-linux.sh | bash -s -- --config systemctl --labels platform=linux,region=idc-sh,project=芒果备用环境
curl -s http://script.wh.hc-yun.com:3380/install/categraf-linux.sh | bash -s -- --config wfw --labels platform=linux,region=idc-sh,project=芒果备用环境
systemctl status categraf.service
EOF

ERROR() {
    printf "$(tput setaf 1)[$(date '+%Y-%m-%d %H:%M:%S')] [ERRO] ✖ %s $(tput sgr0)\n" " $@"
}

INFO() {
    printf "$(tput setaf 2)[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] ➜ %s $(tput sgr0)\n" " $@"
}

WARNING() {
    printf "$(tput setaf 3)[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] ➜ %s $(tput sgr0)\n" " $@"
}

SUCCESS() {
    printf "$(tput setaf 4)[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] ✔ %s $(tput sgr0)\n" " $@"
}

HELP() {
    printf "$(tput setaf 5) %s $(tput sgr0)\n" "$@"
}

CHECK() {
    printf "$(tput setaf 5)[$(date '+%Y-%m-%d %H:%M:%S')] [CHECK] ✔ %s $(tput sgr0)\n" " $@"
}

# 显示使用帮助
usage () {
    [ -n "$1" ] && eval "$@"
    HELP "Usage: ${0} [OPTION...]"
    HELP "          -H, --help          输出帮助信息."
    HELP "          -i, --ins           指定安装类型 服务端/被监控端，默认: [ server | client | ibex ]."      
    HELP "          -d, --insdir        指定软件安装路径: [ categraf: /usr/local, nightingale: /usr/local,  docker-nightingale: /home ]."
    HELP "          -s, --server        指定监控服务端IP地址，默认: [ 192.168.2.79 ]"
    HELP "          -l, --labels        指定被监控端label用于区分不同类型及区域服务器，默认 [ platform=linux,region=wuhan ]"
    HELP "          -c, --config        配置被监控端可选项 微服务/systemctl : [ wfw | systemctl ]"
    HELP ""
    HELP "Exanple:"
    HELP "       $0 --ins server --insdir /usr/local"
    HELP "       $0 --ins client --insdir /usr/local --server http://172.168.10.33:19000 --labels platform=linux,region=idc-sh,project=芒果备用"
    HELP "       $0 --config wfw --labels platform=linux,region=idc-sh,project=芒果备用"
    HELP "       $0 --config systemctl --labels platform=linux,region=idc-sh,project=芒果备用"
    HELP ""
    HELP "Remote Install:" 
    HELP "       curl -s http://script.wh.hc-yun.com:3380/install/categraf-linux.sh | bash -s -- --ins client --insdir /usr/local --server http://172.168.100.33:19000 --labels platform=linux,region=idc-sh,project=芒果备用"
    HELP "       curl -s http://script.wh.hc-yun.com:3380/install/categraf-linux.sh | bash -s -- --config wfw --labels platform=linux,region=idc-sh,project=芒果备用"
    HELP "       curl -s http://script.wh.hc-yun.com:3380/install/categraf-linux.sh | bash -s -- --config systemctl --labels platform=linux,region=idc-sh,project=芒果备用"
    exit 0
}

# 获取服务器默认上网网卡(监控通信)
host_if=$(ip route get 1.1.1.1 | awk '{print $5}')

# 获取服务器默认上网 IP(监控通信)
host_ip=$(ip route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1); exit}')

# 服务唯一标识(服务指标标签)
HOST=$(hostname -f)
IPADDR=$(awk "/${HOST}/{print \$1; exit}" /etc/hosts)
IPADDR=${IPADDR:-$host_ip}
IPADDR=${IPADDR/#127.0.0.1/$host_ip}


# 匹配默认上网IP网络，获取对应监控端地址
case ${host_ip%.*} in
    (10.34.44)     server="http://10.34.44.30:17000"     ;;
    (10.34.45)     server="http://10.34.45.30:17000"     ;;
    (172.168.100)  server="http://172.168.100.30:17000"  ;;
    (172.168.200)  server="http://172.168.200.30:17000"  ;;
    (*)            server="https://n9e.9j6.cn"           ;;
esac

# 参数默认值设定
insdir='/usr/local'
labels='platform=linux,region=wuhan'

# 获取系统信息(init.d/systemctl)
if [ -f /etc/redhat-release ]; then
    VERSION_ID="$(sed -r 's/.* ([0-9]+)\..*/\1/' /etc/redhat-release)"
fi

# 配置 jstst 软链接，采集 jvm
JstatBin=$(which jstat)
[ -f "$JstatBin" ] && ln -sf $JstatBin /usr/bin/

# 读取命令行参数
OPTS=$(getopt -o Hi:d:s:e:l:c: -al help,ins:,insdir:,server:,labels:,config: -n 'parse-options' -- "$@"); [ $? != 0 ] && exit 1
eval set -- "$OPTS"
while [ -n "$1" ]; do
    case "$1" in
        -H | --help                ) usage;                  break   ;; # 显示帮助信息，无需解析更多参数直接退出
        -i | --ins                 ) ins=$2;                 shift 2 ;; # 安装的类型(监控端/被监控端)
        -d | --insdir              ) insdir=$2;              shift 2 ;; # 安装路径
        -s | --server              ) server=$2;              shift 2 ;; # 监控端IP
        -l | --labels              ) labels=$2;              shift 2 ;; # 被监控端标签
        -c | --config              ) config=$2;              shift 2 ;; # 配置客户端
        -- ) shift; break ;;
        * ) break ;;
    esac
done

# 定义 system_map，键为服务名称，值为进程名称
declare -A system_map=(
    ["zookeeper"]="org.apache.zookeeper.server.quorum.QuorumPeerMain"
    ["kafka"]="kafka.Kafka"
    ["hdp-zkfc"]="org.apache.hadoop.hdfs.tools.DFSZKFailoverController"
    ["hdp-journalnode"]="org.apache.hadoop.hdfs.qjournal.server.JournalNode"
    ["hdp-namenode"]="org.apache.hadoop.hdfs.server.namenode.NameNode"
    ["hdp-resourcemanager"]="org.apache.hadoop.yarn.server.resourcemanager.ResourceManager"
    ["hdp-secondarynamenode"]="org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode"
    ["hdp-datanode"]="org.apache.hadoop.hdfs.server.datanode.DataNode"
    ["hdp-nodemanager"]="org.apache.hadoop.yarn.server.nodemanager.NodeManager"
    ["hbase-master"]="org.apache.hadoop.hbase.master.HMaster"
    ["hbase-regionserver"]="org.apache.hadoop.hbase.regionserver.HRegionServer"
    ["opentsdb"]="net.opentsdb.tools.TSDMain"
    ["storm-ui"]="org.apache.storm.ui.core"
    ["storm-nimbus"]="org.apache.storm.daemon.nimbus"
    ["storm-supervisor"]="org.apache.storm.daemon.supervisor.Supervisor"
    ["flink-zookeeper"]="org.apache.flink.runtime.zookeeper.FlinkZooKeeperQuorumPeer"
    ["flink-jobmanager"]="org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint"
    ["flink-taskmanager"]="org.apache.flink.runtime.taskexecutor.TaskManagerRunner"
    ["seatunnel"]="org.apache.seatunnel.core.starter.seatunnel.SeaTunnelServer"
    ["seatunnel-web"]="org.apache.seatunnel.app.SeatunnelApplication"
    ["doris-fe"]="org.apache.doris.PaloFe"
    ["doris-be"]="lib/doris_be"
    ["dolphinscheduler-api"]="org.apache.dolphinscheduler.api.ApiApplicationServer"
    ["dolphinscheduler-alert"]="org.apache.dolphinscheduler.alert.AlertServer"
    ["dolphinscheduler-master"]="org.apache.dolphinscheduler.server.master.MasterServer"
    ["dolphinscheduler-worker"]="org.apache.dolphinscheduler.server.worker.WorkerServer"
    ["hazelcast"]="com.hazelcast.core.server.StartServer"
    ["tomcat-fanruan"]="org.apache.catalina.startup.Bootstrap"
    ["solr"]="start.jar"
    ["nacos"]="nacos.nacos"
    ["keepalived"]="keepalived"
    ["mongod"]="mongod"
    ["mysqld"]="mysqld"
    ["taosd"]="taosd"
    ["taosadapter"]="taosadapter"
    ["fdfs_trackerd"]="fdfs_trackerd"
    ["fdfs_storaged"]="fdfs_storaged"
    ["minio"]="minio"
    ["ht"]="server.js"
    ["redis"]="redis-server"
    ["emqx"]="bin/run_erl"
    ["emqtt"]="emqttd"
    ["nginx"]="nginx"
)

# 定义 port_map，键为进程名称，值为端口号
declare -A port_map=(
    ["org.apache.zookeeper.server.quorum.QuorumPeerMain"]="2181"
    ["kafka.Kafka"]="9092"
    ["org.apache.hadoop.hdfs.tools.DFSZKFailoverController"]="8019"
    ["org.apache.hadoop.hdfs.qjournal.server.JournalNode"]="8480,8485"
    ["org.apache.hadoop.hdfs.server.namenode.NameNode"]="50070"
    ["org.apache.hadoop.yarn.server.resourcemanager.ResourceManager"]="8088"
    ["org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode"]="50090"
    ["org.apache.hadoop.hdfs.server.datanode.DataNode"]="50075"
    ["org.apache.hadoop.yarn.server.nodemanager.NodeManager"]="8042"
    ["org.apache.hadoop.hbase.master.HMaster"]="16010"
    ["org.apache.hadoop.hbase.regionserver.HRegionServer"]="16030"
    ["net.opentsdb.tools.TSDMain"]="14242"
    ["org.apache.storm.ui.core"]="8080"
    ["org.apache.storm.daemon.nimbus"]="6627"
    ["org.apache.storm.daemon.supervisor.Supervisor"]=""
    ["org.apache.flink.runtime.zookeeper.FlinkZooKeeperQuorumPeer"]="2181"
    ["org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint"]="8087"
    ["org.apache.flink.runtime.taskexecutor.TaskManagerRunner"]=""
    ["org.apache.seatunnel.core.starter.seatunnel.SeaTunnelServer"]="5801"
    ["org.apache.seatunnel.app.SeatunnelApplication"]="8801"
    ["org.apache.doris.PaloFe"]="8130,9030"
    ["lib/doris_be"]="8140"
    ["org.apache.dolphinscheduler.api.ApiApplicationServer"]="12345"
    ["org.apache.dolphinscheduler.alert.AlertServer"]="50052"
    ["org.apache.dolphinscheduler.server.master.MasterServer"]="5678"
    ["org.apache.dolphinscheduler.server.worker.WorkerServer"]="1234"
    ["com.hazelcast.core.server.StartServer"]="5701,5702,5703"
    ["org.apache.catalina.startup.Bootstrap"]="7070"
    ["start.jar"]="8983"
    ["nacos.nacos"]="8848,9848"
    ["keepalived"]=""
    ["mongod"]="27017"
    ["mysqld"]="3306"
    ["taosd"]="6030"
    ["taosadapter"]="6041"
    ["fdfs_trackerd"]="22122"
    ["fdfs_storaged"]="23000"
    ["minio"]="9000"
    ["server.js"]="5889"
    ["redis-server"]="6379"
    ["bin/run_erl"]="1883,18083"
    ["emqttd"]="1883,18083"
    ["nginx"]=""
)

# 定义 jvm_map，键为服务名称，值为是否需要 jvm_opt（1 表示需要，0 表示不需要）
declare -A jvm_map=(
    ["zookeeper"]=1
    ["kafka"]=1
    ["hdp-zkfc"]=1
    ["hdp-journalnode"]=1
    ["hdp-namenode"]=1
    ["hdp-resourcemanager"]=1
    ["hdp-secondarynamenode"]=1
    ["hdp-datanode"]=1
    ["hdp-nodemanager"]=1
    ["hbase-master"]=1
    ["hbase-regionserver"]=1
    ["opentsdb"]=1
    ["storm-ui"]=1
    ["storm-nimbus"]=1
    ["storm-supervisor"]=1
    ["flink-zookeeper"]=1
    ["flink-jobmanager"]=1
    ["flink-taskmanager"]=1
    ["seatunnel"]=1
    ["seatunnel-web"]=1
    ["doris-fe"]=1
    ["dolphinscheduler-api"]=1
    ["dolphinscheduler-alert"]=1
    ["dolphinscheduler-master"]=1
    ["dolphinscheduler-worker"]=1
    ["hazelcast"]=1
    ["tomcat-fanruan"]=1
    ["solr"]=1
    ["nacos"]=1
    ["keepalived"]=0
    ["mongod"]=0
    ["mysqld"]=0
    ["taosd"]=0
    ["taosadapter"]=0
    ["fdfs_trackerd"]=0
    ["fdfs_storaged"]=0
    ["minio"]=0
    ["ht"]=0
    ["redis"]=0
    ["emqx"]=0
    ["emqtt"]=0
    ["nginx"]=0
)

# 写入配置
conf () {
    local name=$1
    local out=$2
    local cover=$3
    if [ "$cover" == 'true' ]; then
        echo -e "$out" > $insdir/conf/input.${name}/${name}.toml
    else
        echo -e "$out" >> $insdir/conf/input.${name}/${name}.toml
    fi
}

# 端口监控
addport() {
    local port=$1
    local system=$2
    # hosts 文件内获取如果没有则是host_ip 的值 ${IPADDR}   默认路由获取的 ${host_ip}
    targets=$(for i in ${port//,/ }; do echo ${IPADDR}:${i}; done)

    if ! grep -q "product=\"${system}\"" $insdir/conf/input.net_response/net_response.toml &>/dev/null; then
        conf net_response ""
        conf net_response "[[instances]]"
        conf net_response "targets = ["
        for target in ${targets}; do
            if ! grep -q "${target}" $insdir/conf/input.net_response/net_response.toml &>/dev/null; then
                conf net_response "    \"${target}\","
            fi
        done
        conf net_response "]"
        conf net_response "labels = {region=\"${region}\", project=\"${project}\", product=\"${system}\", port=\"${port}\"}"
    fi
}


ins_categraf() {
    INFO "安装 categraf"
    insdir="${insdir}/categraf"
    if [ -d "$insdir" ]; then
        bakdir="${insdir}-$(date +%s)"
        mv "$insdir" "$bakdir"
        WARNING "已存在 categraf 安装目录，旧目录被移动到 ${bakdir} ."
    fi

    INFO "下载解压 Categraf ."
    mkdir -p "$insdir"
    curl -s http://oss.hc-yun.com/nightingale/categraf-linux-amd64.tar.gz | tar xz --strip-components=1 -C "$insdir"

    INFO "配置 categraf.service ."
    if command -v systemctl &>/dev/null; then
        $insdir/categraf --remove &>/dev/null
        $insdir/categraf --install &>/dev/null
        systemctl daemon-reload
    else
        base64 -d <<< '[payload removed: 1672 characters]' > /etc/init.d/categraf
        chmod +x /etc/init.d/categraf
    fi

    INFO "配置监控端地址为 ${server} ."
    sed -i \
        -e "s|http://127.0.0.1:17000|${server}|" \
        -e "s|^hostname =.*|hostname = \"${HOST}-${IPADDR}\"|" ${insdir}/conf/config.toml

    if [ -n "$host_if" ]; then
        INFO "指定本地网卡 ${host_if}  ."
        sed -i \
            -e 's|^# interfaces|interfaces|' \
            -e "s|eth0|$host_if|" \
        ${insdir}/conf/input.net/net.toml
    fi

    INFO "配置Labels: ${labels} ."
    add_labels=$(for label in ${labels//,/ }; do echo "-e '/^\[global.labels/a\\${label/=/ = \"}\"'"; done)
    eval "sed -i -e '/# sn /d' -e '/# env /d' -e '/# region/d' "$add_labels" ${insdir}/conf/config.toml"

    INFO "启动服务 categraf ."
    if command -v systemctl &>/dev/null; then
        systemctl daemon-reload
        systemctl enable --now categraf.service &>/dev/null
        systemctl restart categraf.service
    else
        chkconfig --add categraf
        service categraf restart
    fi

    # 删除历史安装
    rm -rf ${insdir}-*
}

# /etc/rc.local systemctl
system() {
    # 获取 labels
    for label in ${labels//,/ }; do  eval $label; done

    # 判断参数
    if [ -z "$region" -o -z "$project" ]; then
        usage "WARNING  缺少参数 --labels=region=wuhan,project=芒果测试"
    fi

    # 获取安装路径
    BinPath=$(systemctl show categraf.service --property=ExecStart | grep -oP 'path=\K[^ ;]+')
    insdir="$(dirname $BinPath)"

    # 如果没有安装 categraf
    if [ -z "$insdir" ]; then
        ERROR "没有找到 categraf 操作取消."
        exit 1
    fi

    # 判断 procstat 是否已配置
    if ! grep -q '# mango' $insdir/conf/input.procstat/procstat.toml &>/dev/null; then
        conf procstat "# mango $(date '+%F %T')" "true"
        conf procstat "interval = 15"
    fi

    # 判断 net_response 是否已配置
    if ! grep -q '# mango' $insdir/conf/input.net_response/net_response.toml &>/dev/null; then
        conf net_response "# mango $(date '+%F %T')" "true"
        conf net_response "interval = 15"
    fi

    # 遍历 /etc/rc.local 配置进程监控 ( !/^#/ 过滤注释行，匹配关键字 systemctl)
    systemd=$(awk '!/^#/ && /systemctl/{print $NF}' /etc/rc.local)

    # 根据 system 名称匹配进程关键字
    for system in ${systemd}; do
        # 去除服务后缀 .service
        local system=${system%.*}

        # 从 system_map 中获取进程名称
        pattern=${system_map["$system"]}
        if [ -z "$pattern" ]; then
            WARNING "$system 服务没有匹配到监控策略, 没有被监管."
            continue
        fi

        # 是否需要 jvm 监控
        # if [ "${jvm_map["$system"]}" == '1' ]; then
        #     jvm_opt=',"jvm"'
        # else
        #     unset jvm_opt
        # fi
        # hadoop 配置
        sed -i 's@1022@50075@' $insdir/conf/input.hadoop/hadoop.toml

        # config procstat
        if ! grep -q "product=\"${system}\"" $insdir/conf/input.procstat/procstat.toml &>/dev/null; then
            conf procstat ""
            conf procstat "[[instances]]"
            conf procstat "gather_total = true"
            conf procstat "gather_per_pid = true"
            conf procstat "search_cmdline_substring = \"${pattern}\""
            conf procstat "labels = {region=\"${region}\", project=\"${project}\", product=\"${system}\", type=\"systemctl\"}"
            conf procstat "gather_more_metrics = [\"threads\",\"fd\",\"io\",\"uptime\",\"cpu\",\"mem\",\"limit\"${jvm_opt}]"
        fi

        # 根据进程名从 port_map 中获取进程端口
        port=${port_map["$pattern"]}

        # 动态获取 nginx 监听端口
        #[ "$system" == 'nginx' ] && port=$(ss -ntlp | awk '/nginx/ {split($4,a,":");p=p?p","a[length(a)]:a[length(a)]} END{print p}')
        [ "$system" == 'nginx' ] && port=$(ss -ntlp | awk '/nginx/ {split($4,a,":"); if (a[1] != "127.0.0.1") {p=p?p","a[length(a)]:a[length(a)]}} END{print p}')

        # config net_response
        if [ -n "$port" ]; then
            addport "$port" "$system"
        fi
    done

    # 遍历 system_map，检查每个进程是否存在
    for system in "${!system_map[@]}"; do
        pattern=${system_map["$system"]}
        if ps -ef | grep -v grep | grep -w "$pattern" &>/dev/null; then
            # config procstat
            if ! grep -q "product=\"${system}\"" $insdir/conf/input.procstat/procstat.toml &>/dev/null; then
                conf procstat ""
                conf procstat "[[instances]]"
                conf procstat "gather_total = true"
                conf procstat "gather_per_pid = true"
                conf procstat "search_cmdline_substring = \"${pattern}\""
                conf procstat "labels = {region=\"${region}\", project=\"${project}\", product=\"${system}\", type=\"process\"}"
                conf procstat "gather_more_metrics = [\"threads\",\"fd\",\"io\",\"uptime\",\"cpu\",\"mem\",\"limit\"${jvm_opt}]"
                conf procstat ""
            fi

            # 根据进程名从 port_map 中获取进程端口
            port=${port_map["$pattern"]}

            # 动态获取 nginx 监听端口
            #[ "$system" == 'nginx' ] && port=$(ss -ntlp | awk '/nginx/ {split($4,a,":");p=p?p","a[length(a)]:a[length(a)]} END{print p}')
            [ "$system" == 'nginx' ] && port=$(ss -ntlp | awk '/nginx/ {split($4,a,":"); if (a[1] != "127.0.0.1") {p=p?p","a[length(a)]:a[length(a)]}} END{print p}')
        
            # config net_response
            if [ -n "$port" ]; then
                addport "$port" "$system"
            fi
        fi
    done

    # 检测 docekr
    if command -v docker >/dev/null; then
        if ! grep -q ^labels $insdir/conf/input.docker/docker.toml; then
            endpoint=unix:///var/run/docker.sock
            sed -i "s|endpoint =.*|endpoint = \"$endpoint\"|" $insdir/conf/input.docker/docker.toml
            sed -i "s|# labels =.*|labels = {region=\"${region}\", project=\"${project}\", product=\"docker\"}|" $insdir/conf/input.docker/docker.toml
        fi
    fi

    # 重启服务
    systemctl restart categraf 
}


# 运行的微服务
mgwfw() {
    # 获取 labels
    for label in ${labels//,/ }; do  eval $label; done

    # 判断参数
    if [ -z "$region" -o -z "$project" ]; then
        usage "WARNING  缺少参数 --labels=region=wuhan,project=芒果测试"
    fi

    # 获取安装路径
    BinPath=$(systemctl show categraf.service --property=ExecStart | grep -oP 'path=\K[^ ;]+')
    insdir="$(dirname $BinPath)"

    # 如果没有安装 categraf
    if [ -z "$insdir" ]; then
        ERROR "没有找到 categraf 服务, 操作取消"
        exit 1
    fi

    # 判断环境
    if [ -z "$JAVA_HOME" ]; then
        ERROR "没有找到 JAVA_HOME 变量, 操作取消"
        exit 2
    fi

    # 判断 procstat 是否已配置
    procstat_state=$(grep -rl '# mango' $insdir/conf/input.procstat/procstat.toml)
    if [ -z "$procstat_state" ]; then
        conf procstat "# mango $(date '+%F %T')" "true"
        conf procstat "interval = 15"
        # conf procstat "$(gunzip < <(base64 -d <<<'H4sIAAAAAAAAAz2MwQoDIQxE735FwGtBeuix31KCZncDiQaN7e93LWwPA8PM40WIkJsIZQeuTv2NEuK/whPuj3AOYyq0DfzohGWkrSRuKdtMSnoD5breac5KSVjZw45+UH9585/G+6Ql+rAIoBnVAsYFcIDjftG2cq4X/wVbsDc1nwAAAA=='))"
    fi

    # 获取java进程及命令信息
    ps -eo pid,args | grep -v grep | egrep '[0-9] /.*bin/java|[0-9] java' > /tmp/java_process
    if ! egrep -q 'uaa|gateway|loong|dcapi|dcmqtt|dc-api|dc-mqtt' /tmp/java_process; then
        ERROR "没有获取到微服务信息(uaa|base|loong|dcapi|dcmqtt|dc-api|dc-mqtt), 操作取消"
        exit 1
    fi

    # 对获取的信息处理
    while read line; do
        pid=$(echo $line | awk '{print $1}')
        package=$(jps -l | grep -w ${pid} | awk '{print $2}')
        module=${package%-*}
        pattern=$(sed -E 's/(.*-[0-9]+.[0-9]+).[0-9]+.[0-9]+(.[a-z]{3})?$/\1/' <<<${package})
        if [[ -n "${package}" ]]; then
            if grep -q "product=\"${module}\"" $insdir/conf/input.procstat/procstat.toml; then
                old_pattern=$(grep -m 1 "${module}-[0-9]" $insdir/conf/input.procstat/procstat.toml | awk -F '"' '{print $2}')
                sed -i "s|$old_pattern|$pattern|g" $insdir/conf/input.procstat/procstat.toml
                #echo "配置进程监控 微服务: ${module}  进程名: ${pattern}"
            else
                conf procstat ""
                conf procstat "[[instances]]"
                conf procstat "gather_total = true"
                conf procstat "gather_per_pid = true"
                conf procstat "search_cmdline_substring = \"${pattern}\""
                conf procstat "labels = {region=\"${region}\", project=\"${project}\", product=\"${module}\"}"
                conf procstat "gather_more_metrics = [\"threads\",\"fd\",\"io\",\"uptime\",\"cpu\",\"mem\",\"limit\"]"
                #conf procstat "gather_more_metrics = [\"threads\",\"fd\",\"io\",\"uptime\",\"cpu\",\"mem\",\"limit\",\"jvm\"]"
                conf procstat ""
                #echo "配置进程监控 微服务: ${module}  进程名: ${pattern}"
            fi

            port=$(ss -ntlp | awk -v pid="$pid," '$0 ~ "pid=" pid {split($4,a,":"); p=p?p","a[length(a)]:a[length(a)]} END{print p}')
            #port=$(ss -ntlp | awk -v pid="$pid," '$3 != 100 && $0 ~ "pid=" pid {split($4,a,":"); p=p?p","a[length(a)]:a[length(a)]} END{print p}')
            if [ -n "$port" ]; then
                #echo "配置端口监控 微服务: ${module}  端口: ${port}"
                addport "$port" "$module"
            fi
        fi
    done < /tmp/java_process

    # 重启服务
    if command -v systemctl >/dev/null; then
        systemctl restart categraf
    else
        service categraf restart &>/dev/null
    fi
}

ins_docker() {
    if command -v docker >/dev/null; then
        WARNING "操作取消, 本机已经安装 docker"
    else
        INFO "安装 docker."
        insdir="/usr/local/docker/bin"

        INFO "下载解压 dcoker"
        mkdir -p "$insdir"
        curl -s http://oss.hc-yun.com/docker/docker-20.10.9.tgz | tar xz --strip-components=1 -C "$insdir"
        curl -s http://oss.hc-yun.com/docker/_docker > /usr/share/bash-completion/completions/docker
        ln -sf $insdir/docker /bin/docker

        INFO "配置、启动 docker.service"
        mkdir -p /etc/docker
        base64 -d <<< "[payload removed: 544 characters]" > /etc/docker/daemon.json
        base64 -d <<< "[payload removed: 748 characters]" > /etc/systemd/system/docker.service
        systemctl daemon-reload
        systemctl enable --now docker &>/dev/null
    fi

    if ! command -v docker-compose >/dev/null; then
        INFO "安装配置 docker-compose"
        curl -s http://oss.hc-yun.com/docker/docker-compose -o /usr/local/bin/docker-compose
        curl -s http://oss.hc-yun.com/docker/_docker-compose > /usr/share/bash-completion/completions/docker-compose
        chmod +x /usr/local/bin/docker-compose
    fi
    }

ins_docker_nightingale () {
    INFO "下载解压 docker-nightingale"
    [ "$insdir" == '/usr/local' ] && insdir=/home
    mkdir -p "$insdir"
    curl -s http://oss.hc-yun.com/nightingale/docker-nightingale.tgz -o "$insdir/docker-nightingale.tgz"
    tar xf "$insdir/docker-nightingale.tgz" -C "$insdir"
    cd "$insdir/docker-nightingale"

    INFO "下载镜像"
    docker-compose pull &>/dev/null

    INFO "启动服务"
    docker-compose up -d

    INFO "容器信息"
    docker-compose ps

    host_if=$(ip route get 1.1.1.1 | awk '{print $5}')
    host_ip=$(ip route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1); exit}')
    HELP ""
    HELP ""
    HELP ""
    HELP "         登录地址: http://${host_ip}:18000   账号: root/root.2020"     
}


# 安装服务端/被监控端
if [ -n "$ins" ]; then
    case ${ins} in
        server)
            ins_docker
            ins_docker_nightingale
            ;;
        client)
            ins_categraf
            ;;
        *)
            usage
            ;;
    esac
fi


# 配置 categraf
if [ -n "$config" ]; then
    case ${config} in
        wfw)
            mgwfw
            ;;
        systemctl)
            system
            ;;
        *)
            usage
            ;;
    esac
fi