#!/bin/bash
source /home/omm/.profile
declare SSSD_CHECK="[domain/default]|ldap_uri,ldap_tls_reqcert,ldap_tls_cacert,id_provider,ldap_default_bind_dn,ldap_default_authtok,ldap_default_authtok_type;[sssd]|services,config_file_version,domains"
declare REDHAT_LDAP_CHECK="|URI,TLS_REQCERT,TLS_CACERT"
declare SUSE_LDAP_CHECK="|URI,BINDDN,bindpw,TLS_REQCERT,TLS_CACERTDIR,bind_policy,base"
#0不需要 1需要修复 
declare NEED_REPAIR=0
##########################################################
#    Description: get script path and return to caller
#    Parameter:   None
#    Return:      script path
#                 
##########################################################
getCurrentPath()
{
    cd "$(dirname "$0")"
    readlink -e "$(pwd)"
    cd - > /dev/null 2>&1    
}

################################################################
#   日志转换函数
################################################################
echoLog()
{
    local line="${1}"
    local logOwner="${2}"
    local logType="${3}"
    local logMsg="${4}"

  outputDetailLogtool "${line}" "${g_log_file}" "${logOwner}" "${logType}" "${logMsg}" "${g_script_name}"
}

##########################################################
#    Description: stop nscd service  
#    Parameter:   None
#    Return:      None                
##########################################################
stopNscdService()
{
    if [ "${g_os_type}" == "${SUSE_OS_TYPE}" -o "${g_os_type}" == "${SUSE15_OS_TYPE}" ];then
        return 0        
    fi

    local pid=""
    local nscd_run_cmd="/usr/sbin/nscd"
    
    pid=`ps -ww -eo pid,cmd | grep -w "$nscd_run_cmd" |grep -v grep`
    if [ -n "$pid" ]; then  
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "nscd start,need to stop."              
          sudo ${SUDO_PATH_NODEAGENT}  ldap_stopNscd
    fi    
}

##########################################################
#    Description: the main function
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed
##########################################################
main()
{

    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "Begin check."
    #init global var 
    initGlobalVar    
    
    #check if new conf could be generated
    local ldap_server_list="$(getLdapServerIPList ",")"
    if [ -z "${ldap_server_list}" ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}}"  "ldap_server_list is empty:${ldap_server_list}, can not generate correct conf."
        return $RET_OK
    fi
    
    #stop nscd service
    stopNscdService

    TMP_DIR=${BIGDATA_HOME}/tmp/ldapclient  
    if [ ! -d ${TMP_DIR} ];then
        mkdir -p ${TMP_DIR}
    fi
    
    #check ldap config file
    checkAndRepairConfigFile
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" "check config file failed."
        rm -rf "${TMP_DIR}/"*
        return $RET_ERR
    fi    
    rm -rf "${TMP_DIR}/"*
    
    #check sssd service status
    if [ ${sssd_service_status} -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" "sssd service status fault."
        return $RET_ERR
    fi
    
    #check nscd service status
    if [ ${service_status} -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" "nscd service status fault."
        return $RET_ERR
    fi
    
    checkAndRepairCertFile
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" "check cert file failed."
        return $RET_ERR
    fi
    
    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "End check." 
    
    return $RET_OK
     
}


init_env()
{
    installpath="${g_current_path}"
    
    source $installpath/../../../*_*_SlapdClient/etc/ENV_VARS
    
    g_log_file="${LDAP_CLIENT_LOG_PATH}/ldapclient_hmon.log"
}

##########################################################
#    Description: init global variable
#    Parameter:   None
#    Return:      None              
##########################################################
initGlobalVar()
{    
    
    
    checkNscdService
    service_status=$?
    
    checkSssdService
    sssd_service_status=$?

}

##########################################################
#    Description: check and repair config file
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed                 
##########################################################
checkAndRepairConfigFile()
{
    local ret=$RET_OK
    
    checkAndRepairSssdConfFile
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" "check or repair sssd config file failed."
        ret=$RET_ERR
    fi   
    
    checkAndRepairLdapConfigFile
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "check or repair ldap config file failed."
        ret=$RET_ERR
    fi 
    return $ret
}

##########################################################
#    Description: check and repair sssd conf file 
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed                 
##########################################################
function checkAndRepairSssdConfFile()
{ 
    if [ "${g_os_type}" == "${SUSE_OS_TYPE}" -o  "${g_os_type}" == "${SUSE15_OS_TYPE}" ];then
        return 0        
    fi
    
    local src_file="/etc/sssd/sssd.conf"
    local tmp_file="$TMP_DIR/sssd.conf"
    local src_tmp_file="${tmp_file}.tmp"
    local file_mode_str="\-rw\-\-\-\-\-\-\-"
    local file_mode_num="600"
    local file_user="root"
    local file_group="root"
    
    #generate config file to compare    
    genSssdConfigFile "${tmp_file}" "${installpath}"
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "generate sssd config file failed."
        return $RET_ERR
    fi  
    
    checkFileModeAndOwner "${src_file}" "${file_mode_str}" "${file_user}" "${file_group}"
    if [ $? -ne 0 ]; then
        sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_second "${file_mode_num}" "${src_file}"
        if [ $? -ne 0 ];then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" " chmod  ${file_mode_num}   ${src_file} failed. "
        fi 
        sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_third  "${file_user}":"${file_group}"  "${src_file}" 
        if [ $? -ne 0 ];then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "/bin/chown  ${file_user}:${file_group}   ${src_file} failed. "
        fi
    fi
    
    #check file config
    
    checkFileNeedRepair "${src_file}" "${tmp_file}"  "${file_mode_str}" "${file_user}" "${file_group}"
    if [ $? -eq $RET_OK ];then
        return $RET_OK
    fi
   
    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "sssd config has changed, need to reconfig."
    
    #不刷新
    if [ ! -f ${src_tmp_file} ] ; then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "${src_tmp_file} is not exist,can not repair sssd config."
        return 1
    fi
    
    repairConfigFile "${src_file}" "${src_tmp_file}" "${file_mode_num}" "${file_user}" "${file_group}" 
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERROR}" "Failed to repair sssd config."
        rm -f $src_tmp_file
        return $RET_ERR
    fi    
    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "Successful repair ${src_file}."
    
    rm -f $src_tmp_file
    
    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "sssd config has changed, need to stop sssd."
    sudo ${SUDO_PATH_NODEAGENT} ldap_restartSssd        
    
    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "sssd config has changed, need to clear cache."
    sudo ${SUDO_PATH_NODEAGENT} nscd_clear_cache   
    
    return $RET_OK      
}



##########################################################
#    Description: copy source config file 
#    Parameter:   $1 src config file
#                 $2 dst config file  
#    Return:      RET_OK: success
#                 RET_ERR: failed                 
##########################################################
copySrcConfFile()
{
    local src_conf_file="${1}"
    local dst_conf_file="${2}"
    
    cat /dev/null > "${dst_conf_file}" 
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"   "echo dst_conf_file failed."
        return $RET_ERR
    fi 
    
    chmod 600 "${dst_conf_file}"
    
    sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_copySrcConfFile "${src_conf_file}" "${dst_conf_file}"
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"   "copy config file ${src_conf_file} to ${dst_conf_file} failed."
        return $RET_ERR
    fi  
    
    return $RET_OK   
}

##########################################################
#    Description: check file mode and owner 
#    Parameter:   $1 file path
#                 $2 file mode 
#                 $3 file user
#                 $4 file group    
#    Return:      RET_OK: no need to repair file
#                 RET_ERR: need to repair file                 
##########################################################
checkFileModeAndOwner()
{
    local file_path="${1}"    
    local correct_mode_str="${2}"
    local correct_user="${3}"
    local correct_group="${4}"    
    
    sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_lsSrcConfFile  "${file_path}"
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"   "check file ${src_file} mode failed, file not exist."
        return $RET_ERR
    fi
    
    local file_attr_list=($(sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_lsSrcConfFile  "${file_path}" | awk -F' ' '{for(i=1; i<=NF; i++){print $i;};}'))
    local file_mode_str="${file_attr_list[0]}"
    local file_user="${file_attr_list[2]}"
    local file_group="${file_attr_list[3]}" 
    local mode=$(echo "${file_mode_str}" |grep "${correct_mode_str}")   
    
    if [ -z "${mode}" ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "file ${src_file} mode ${file_mode_str}, not ${correct_mode_str}."
        return $RET_ERR
    fi
    
    if [ "${correct_user}" != "${file_user}" ] || [ "${correct_group}" != "${file_group}" ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "file ${src_file} owner ${file_user}:${file_group}, not ${correct_user}:${correct_group}."
        return $RET_ERR
    fi
        
    return $RET_OK    
    
}

function compareFiles(){
    
    local src_tmp_file="${1}"
    local tmp_file="${2}"
    local checks="${3}"
    
    local check_list=( $(echo "${checks}" | sed 's/,/ /g') ) 
    
    local split="=" 
    local service="sssd"
    echo "$src_tmp_file" | grep "sssd.conf" >>/dev/null 2>&1
    if [ $? -ne 0 ] ; then
        split="[[:space:]][[:space:]]*"
        service="ldap"
    fi
    
    for check_key in "${check_list[@]}"
        do
            grep -iw "^$check_key" "${tmp_file}" >>/dev/null 2>&1
            if [ $? -ne 0 ] ; then
                continue
            fi
            
            local module=$(getMoudle $service $check_key)
            
            local replace_line=$(grep -iw "^${check_key}" ${tmp_file})
        
            #ldap监控项比较
            if [ -z "${module}" ] ;then
                
                local line_nums=$(grep -i "^${check_key}${split}" "${src_tmp_file}" | wc -l)
                
                if [ ${line_nums} -eq 0 ] ; then  
                    
                    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "Begin append ${replace_line} to $src_tmp_file ."
                    echo "${replace_line}" >> $src_tmp_file
                    
                    if [ $? -ne 0 ] ;then
                        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to append check_line to $src_tmp_file ."
                        return 1
                    fi
                    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  " End append ${replace_line} to $src_tmp_file ."
                     
                    NEED_REPAIR=1
                
                else
                    #键和值之间的分隔符可能在值之间也有,如ldap_uri uri1 urui2 uri3 uri4 键和值之间分割符是空格,值之间也是空格,取值需要从头先删除键,再删除分隔符然后再删除空格,余下的就是值
                    local replace_value=$(grep -iw "^${check_key}" "${tmp_file}" | sed "s/^${check_key}[[:space:]]*//g" | sed "s/^${split}//g" | sed "s/^[[:space:]]*//g" )
                    local src_value  
                    local lines_no=($(grep -n "^${check_key}${split}" "${src_tmp_file}" | awk -F ':' '{print $1}'))
                    for line_no in "${lines_no[@]}"
                    do
                        src_value=$(grep -n "^${check_key}${split}" "${src_tmp_file}" | grep -i "^${line_no}:${check_key}${split}" | sed "s/^${line_no}:${check_key}[[:space:]]*//g" | sed "s/^${split}//g" | sed "s/^[[:space:]]*//g" ) 
                        if [[  "${src_value}" != "${replace_value}" ]]  ; then
                            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "Begin modify ${check_key} in ${src_tmp_file}."
                            sed "${line_no}c ${replace_line}" -i ${src_tmp_file}
                            if [ $? -ne 0 ] ;then
                                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to modify ${check_key} in ${src_tmp_file}."
                                return 1
                            fi  
                            echoLog  "${LINENO}" "${LAUNCHROLE}" "${INFO}"  "End modify ${check_key} in ${src_tmp_file}."
                            NEED_REPAIR=1
                        fi
                    done
                fi
            else
            #sssd监控项比较               
                cat $src_tmp_file | grep -w "^\\${module}" >> /dev/null 2>&1
                if [ $? -eq 0 ] ; then
                    local module_length=$(getModuleLength ${module} ${src_tmp_file} )
                    local line_nums=$(cat "${src_tmp_file}" | grep -w "^\\${module}"  -A ${module_length} | grep -iw "^${check_key}[[:space:]]\{0,\}${split}[[:space:]]\{0,\}" | wc -l)
                    if [ $line_nums -eq 0 ] ;then
                        local module_line_no=$(cat ${src_tmp_file} | grep -nw "^\\${module}" | awk -F ':' '{print $1}')
                        sed "${module_line_no}a ${replace_line}" -i  $src_tmp_file
                        if [ $? -ne 0 ] ;then
                            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to modify $src_tmp_file."
                            return 1
                        fi     
                        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "End append ${replace_line} to $src_tmp_file ${module}."
                        NEED_REPAIR=1
                    else
                        #键和值之间的分隔符可能在值之间也有,如ldap_search_base = dc=hadoop,dc=com 键和值之间分割符是=,值之间也有=,取值需要从头先删除键,再删除分隔符然后再删除空格,余下的就是值
                        local replace_value=$(cat "${tmp_file}" | grep -iw "^${check_key}" | sed "s/^${check_key}[[:space:]]*//g" | sed "s/^${split}//g" | sed "s/^[[:space:]]*//g" )
                        local src_value
                        local lines_no=($(cat "${src_tmp_file}" | grep -wn "^\\${module}" -A ${module_length} | grep -iw "^[1-9][0-9]*-${check_key}" | awk -F '-' '{print $1}'))
                        
                        for line_no in "${lines_no[@]}"
                        do
                            src_value=$(cat "${src_tmp_file}" | grep -wn "^\\${module}" -A ${module_length} | grep -iw "^${line_no}-${check_key}[[:space:]]\{0,\}${split}[[:space:]]\{0,\}" | sed "s/^${line_no}-${check_key}[[:space:]]*//g" | sed "s/^${split}//g" | sed "s/^[[:space:]]*//g" )
                            
                            if [[ "${src_value}" != "${replace_value}" ]]  ; then
                                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "Begin modify ${check_key} in ${src_tmp_file}."
                                sed "${line_no}c ${replace_line}" -i ${src_tmp_file}
                                if [ $? -ne 0 ] ;then
                                    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to modify ${check_key} in ${src_tmp_file}."   
                                    return 1
                                fi  
                                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "End modify ${check_key} in ${src_tmp_file}."
                                
                                #使用sss_obfuscate模糊化bind dn密码，每次都不一样，所以不重启，如果密码有变化，交给sssd_alarm_func流程重启
                                if [ "${check_key}" != "ldap_default_authtok" ];then
                                    NEED_REPAIR=1
                                fi
                            fi
                        done
                    fi
                else
                    #模块不存在,恢复整个模块
                    local module_length=$(getModuleLength ${module} ${tmp_file} )
                    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "$module is not exist in $src_tmp_file."
                    local tmp_module_part_file="${tmp_file}.module.part"
          
                    grep "^\\${module}" -A "${module_length}" ${tmp_file} > ${tmp_module_part_file}
                        
                    if [ ! -s ${tmp_module_part_file} ] ;then
                        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to get $module."
                        rm -f $tmp_module_part_file
                        return 1
                    fi
                        
                    cat ${tmp_module_part_file} >> $src_tmp_file
                    if [ $? -ne 0 ] ; then
                        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to append ${module} to $src_tmp_file."
                        rm -f $tmp_module_part_file
                        return 1
                    fi
                    rm -f $tmp_module_part_file
                    NEED_REPAIR=1     
                fi
            fi
        done
    return 0
}


function getMoudle(){
   local service="${1}"
   local key="${2}"
   local module=""
   if [ $service = "sssd" ] ; then
       module=$(echo "${SSSD_CHECK}" | awk -F ';' '{for(i=1;i<=NF;i++){print $i}}' | grep -w "${key}" | awk -F '|' '{print $1}') 
       if [ -z "${module}" -a -f ${LDAPCLIENT_CHECK_CONFIG} ] ;then
           module=$(grep "^sssd" $LDAPCLIENT_CHECK_CONFIG | grep -w "${key}" | awk -F '|' '{print $2}')
       fi
   fi
   
   echo $module
}

function getModuleLength(){
    local check_module=$1
    local check_file="$2"
    local length=0
    local location=0
    local -a modules=($(cat $check_file | grep '^\['))
    local -i nums=${#modules[@]}
    local -i last_index=$[nums-1]
    for ((i=0;i<nums;i++))
    do
        local module=${modules[$i]}
        if [ $check_module = $module ];then
           location=$(cat $check_file | grep -wn "^\\${check_module}" | awk -F ':' '{print $1}')
           if [ $i -lt $last_index ];then
              local next_module=${modules[$i+1]}
              local next_module_location=$(cat $check_file | grep -wn "^\\${next_module}" | awk -F ':' '{print $1}' )
              length=$[next_module_location-location-1]
           else
              local end_location=$(cat -n $check_file | tail -n1 | awk -F ' ' '{print $1}')
              length=$[end_location-location]
           fi
        fi
    done
   echo $length
}

##########################################################
#    Description: check file cert file
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed                
##########################################################
checkAndRepairCertFile()
{
    local src_file="${NODE_AGENT_HOME}/security/cert/subcert/certFile/ca.crt"
    local tmp_file="${installpath}/local/cert/cacert.pem"
    local src_tmp_file="${tmp_file}.tmp"

    #no src file exist need repair
    /bin/ls -l "${src_file}"    > /dev/null
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "check cert file ${src_file} failed, file not exist."
        return $RET_ERR
    fi

    #copy file to compare
    cp "${src_file}" "${src_tmp_file}"
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "copy cert file ${src_file} to ${src_tmp_file} failed."
        return $RET_ERR
    fi

    #compare src file and tmp file
    diff  "${tmp_file}" "${src_tmp_file}"
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "file tmp_file and src_tmp_file different"
        cp  "${src_tmp_file}" "${tmp_file}"
        if [ $? -ne $RET_OK ];then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "copy cert file ${src_tmp_file} to ${tmp_file} failed."
            return $RET_ERR
        fi
        return $RET_OK
    else
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "check cert file success."
        rm  -f "${src_tmp_file}"
        return $RET_OK
    fi   

}


function checkFileNeedRepair(){
    local src_file="${1}"
    local tmp_file="${2}"
    local src_tmp_file="${tmp_file}.tmp"
    local correct_mode_str="${3}"
    local correct_user="${4}"
    local correct_group="${5}"
    NEED_REPAIR=0 
    #no src file exist need repair
    sudo ${SUDO_PATH_NODEAGENT} configFile_exist_and_NotNull  "${src_file}" 
    if [ $? -ne 0 ];then
        cp -f $tmp_file $src_tmp_file
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "check file ${src_file} config failed, file not exist."
        return $RET_ERR
    fi
      
    #copy file to compare
    copySrcConfFile "${src_file}" "${src_tmp_file}"
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "copy config file ${src_file} to ${src_tmp_file} failed."
        return 1;
    fi 
    
    diff $src_tmp_file $tmp_file >>/dev/null 2>&1
    if [ $? -eq 0 ] ;then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "$src_tmp_file and  $tmp_file are the same,so needn't to repair"
        return 0
    fi
    
    
    
    echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "$src_tmp_file is different from $tmp_file."
       
    local checks
    echo "${tmp_file}" | grep "sssd.conf" >>/dev/null 2>&1
    
    if [ $? -eq 0 ] ;then
    
        checks=($(echo "${SSSD_CHECK}" | awk -F ';' '{for(i=1;i<=NF;i++){print $i}}' | awk -F '|' '{print $2}'))
        if [ -f ${LDAPCLIENT_CHECK_CONFIG} ] ; then
            sssd_checks=( $(cat "${LDAPCLIENT_CHECK_CONFIG}" | grep "^sssd" | awk -F '|' '{print $3}') )
            checks="${checks[@]},${sssd_checks[@]}"
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "${LDAPCLIENT_CHECK_CONFIG} is exist."
        fi  
        
        #删除sssd配置文件项key和value之间没有=的场景
        local line_nums=$(cat ${src_tmp_file} | grep -v '^$' |  grep -v '\[' | grep -v '=' | wc -l)
        for((i=0;i<${line_nums};i++))
        do
            NEED_REPAIR=1
            local del_line=$(cat ${src_tmp_file} | grep -v '^$' |  grep -v '\[' | grep -v '=' | tail -n1)
            local line_no=$(cat ${src_tmp_file} | grep -n "${del_line}" | awk -F ':' '{print $1}')
            sed "${line_no} d" -i ${src_tmp_file}
        done
    else
        
        if [ "${g_os_type}" == "${SUSE_OS_TYPE}" -o "${g_os_type}" == "${SUSE15_OS_TYPE}" ] ;then
            checks=$(echo "${SUSE_LDAP_CHECK}" | awk -F '|' '{print $2}')
        else 
            checks=$(echo "${REDHAT_LDAP_CHECK}" | awk -F '|' '{print $2}')
        fi
        
        if [ -f ${LDAPCLIENT_CHECK_CONFIG} ] ; then
            ldap_checks=$(cat $LDAPCLIENT_CHECK_CONFIG | grep "^ldap" | awk -F '|' '{print $3}')
            checks="${checks},${ldap_checks}"
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  " ${LDAPCLIENT_CHECK_CONFIG} is exist."
        fi
         
    fi
    
    local check_list=$(echo "${checks}" | sed 's/[[:space:]][[:space:]]*/,/g')
      
    local ret=0
    compareFiles "${src_tmp_file}" "${tmp_file}" "${check_list}"
       
    if [ $? -ne 0 ] ;then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "Failed to compareFiles ${src_tmp_file} ${tmp_file}"   
        rm -f $src_tmp_file
        return $RET_ERR
    else
        if [ $NEED_REPAIR -eq 1 ] ; then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "successfully compare Files,${src_file} is change."
            return $RET_ERR
        else
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "successfully compare Files,${src_file} is not change."
        fi
    fi

    rm -f $src_tmp_file
    
    checkFileModeAndOwner "${src_file}" "${correct_mode_str}" "${correct_user}" "${correct_group}"
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "checkFileModeAndOwner ${src_file} ${correct_mode_str} ${correct_user} ${correct_group} failed"
        return $RET_ERR
    fi
    
    return 0
}

##########################################################
#    Description: repair file 
#    Parameter:   $1 src file path
#                 $2 tmp file path 
#                 $3 file mode 
#                 $4 file user
#                 $5 file group   
#    Return:      RET_OK: success
#                 RET_ERR: failed             
##########################################################
repairConfigFile()
{
    local src_file="${1}"
    local src_tmp_file="${2}"
    local file_mode_num="${3}"
    local file_user="${4}"
    local file_group="${5}"

    sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_first "${src_tmp_file}" "${src_file}"
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" " cp -f ${src_tmp_file} ${src_file} failed. "
        return $RET_ERR
    fi 

    sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_second "${file_mode_num}" "${src_file}"
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" " chmod  ${file_mode_num}   ${src_file} failed. "
        return $RET_ERR
    fi 
    sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_third  "${file_user}":"${file_group}"   "${src_file}" 
    if [ $? -ne 0 ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "/bin/chown  ${file_user}:${file_group}   ${src_file} failed. "
        return $RET_ERR
    fi    
    
    return $RET_OK
}


##########################################################
#    Description: check and repair ldap conf file 
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed                 
##########################################################
checkAndRepairLdapConfigFile()
{
    local src_file_list=("/etc/ldap.conf" "/etc/openldap/ldap.conf")    
    local tmp_file="$TMP_DIR/ldap.conf"
    local src_tmp_file="${tmp_file}.tmp"
    local file_mode_str="\-rw\-\-\-\-\-\-\-"
    local file_mode_num="600"
    local file_user="root"
    local file_group="root"    
    local ret=$RET_OK
    local need_repair=$RET_OK
    
    if [ "${g_os_type}" == "${RED_HAT_OS_TYPE}" ];then
        src_file_list=("/etc/openldap/ldap.conf")
    fi
    
    local src_file_num=${#src_file_list[@]}
    
    #generate config file to compare    
    genLdapConfigFile "${tmp_file}" "${installpath}"
    if [ $? -ne $RET_OK ];then
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "generate ldap config file failed."
        return $RET_ERR
    fi  
    
    
    ret=$RET_OK
    for((i=0;i<${src_file_num};i++));
    do
        if [ "${src_file_list[i]}" == "/etc/openldap/ldap.conf" ]; then
            file_user="omm"
            file_group="wheel"
        fi
        
        checkFileModeAndOwner "${src_file_list[i]}" "${file_mode_str}" "${file_user}" "${file_group}"
        if [ $? -ne 0 ]; then
            sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_second "${file_mode_num}" "${src_file_list[i]}"
            if [ $? -ne 0 ];then
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}" " chmod  ${file_mode_num}   ${src_file_list[i]} failed. "
            fi 
            sudo ${SUDO_PATH_NODEAGENT} ldapc_hmon_repairConfigFile_third  "${file_user}":"${file_group}"  "${src_file_list[i]}"
            if [ $? -ne 0 ];then
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "/bin/chown  ${file_user}:${file_group}   ${src_file_list[i]} failed. "
            fi
        fi
    
        #check ldap.conf file config
        checkFileNeedRepair "${src_file_list[i]}" "${tmp_file}" "${file_mode_str}" "${file_user}" "${file_group}"         
        if [ $? -eq $RET_OK ];then
            continue
        fi

        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "${src_file_list[i]} config has changed, need to repair."
        need_repair=$RET_ERR

            #不刷新
        if [ ! -f ${src_tmp_file} ] ; then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}" "${src_tmp_file} is not exist,can not repair ldap config."
            return 1
        fi
        
        repairConfigFile "${src_file_list[i]}" "${src_tmp_file}" "${file_mode_num}" "${file_user}" "${file_group}" 
        if [ $? -ne $RET_OK ];then
            ret=$RET_ERR
        fi     
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}" "Successful  repair ${src_file_list[i]}."
    done  
    
    #ldap config change need to restart nscd
    if [ ${need_repair} -eq $RET_ERR  -a "${g_os_type}" != "${RED_HAT_OS_TYPE}" ];then
        sudo ${SUDO_PATH_NODEAGENT} ldap_restartNscd        
        if [ $? -ne 0 ];then
            ret=$RET_ERR
        fi
        sudo ${SUDO_PATH_NODEAGENT} nscd_clear_cache
    fi 
    
    return $ret                     
}

##########################################################
#    Description: check nscd service  
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed                 
##########################################################
checkNscdService()
{
    if [ "${g_os_type}" == "${RED_HAT_OS_TYPE}" ];then
        return 0        
    fi

    #检查nscd服务
    nscd_alarm_func

    if [ $? -eq 0 ]; then
        return $RET_OK
    else
        return $RET_ERR
    fi
}

##########################################################
#    Description: check sssd service  
#    Parameter:   None
#    Return:      RET_OK: success
#                 RET_ERR: failed                 
##########################################################
checkSssdService()
{
    if [ "${g_os_type}" == "${SUSE_OS_TYPE}" -o "${g_os_type}" == "${SUSE15_OS_TYPE}" ];then
        return 0        
    fi

    #检查sssd服务
    sssd_alarm_func

    if [ $? -eq 0 ]; then
        return $RET_OK
    else
        return $RET_ERR
    fi
}

nscd_alarm_func()
{
    local countFilePath="${g_current_path}/local/tmp"
    local countFile="${countFilePath}/${HOST_NAME}.conf"
    local id_user='backup/manager'

    local nscd_run_cmd="/usr/sbin/nscd"
    local -i times="2"

    local alarmInfo="Local Nscd Service;${HOST_NAME}"
    local additionalInfo="HostName:${HOST_NAME}.Cannot get information from LdapServer."

    if [ ! -d "${countFilePath}" ] ;then 
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "tmp dir does not exist."
        return $RET_ERR
    fi

    if [ ! -f "${countFile}" ]; then
        echo "0" > "${countFile}"
    fi

    process_not_exist_times=$(cat "${countFile}")

    #判断进程是否存在
    pid=$(ps -ww -eo pid,cmd | grep -w "${nscd_run_cmd}" |grep -v grep)

    if [ -z "${pid}" ]; then
        if [ "${process_not_exist_times}" -le "${times}" ]; then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "nscd service has not been started,times=${process_not_exist_times}."
            process_not_exist_times=$((process_not_exist_times+1))
            echo "${process_not_exist_times}" > "${countFile}"
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "no need to send an alarm."
        else
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "process does not exist,need to send an alarm."
            #send alarm
            alarm_func "25005" "0" "2" "59" "" "LdapClient" "NA" "${alarmInfo}" "${additionalInfo}"
        fi
        #重启nscd服务
        sudo ${SUDO_PATH_NODEAGENT} ldap_restartNscd 
        return $RET_ERR
    else
        id "${id_user}" > /dev/null 2>&1
        result=$?
        if [ "${result}" -ne 0 ];then
            if [ "${process_not_exist_times}" -le "${times}" ]; then
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "can not detect user,times=${process_not_exist_times}."
                process_not_exist_times=$((process_not_exist_times+1))
                echo "${process_not_exist_times}" > "${countFile}"
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "no need to send an alarm."
            else
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "can not detect the user,need to send an alarm."
                #send an alarm
                alarm_func "25005" "0" "2" "59" "" "LdapClient" "NA" "${alarmInfo}" "${additionalInfo}"
            fi
            #重启nscd服务
            sudo ${SUDO_PATH_NODEAGENT} ldap_restartNscd  
            sudo ${SUDO_PATH_NODEAGENT} nscd_clear_cache
            return $RET_ERR
        else
            echo "0" > "${countFile}"
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "detect the user successfully,nscd service normal."
            #recover alarm
            alarm_func "25005" "1" "2" "59" "" "LdapClient" "NA" "${alarmInfo}" "${additionalInfo}"
            return $RET_OK
        fi
    fi

}

sssd_alarm_func()
{
    local countFilePath="${g_current_path}/local/tmp"
    local countFile="${countFilePath}/${HOST_NAME}.conf"
    local id_user='backup/manager'

    #redhatOS支持以下两种sssd的启动方式
    local sssd_run_cmd=("/usr/sbin/sssd -D" "/usr/sbin/sssd -D -f")
    local sssd_libexec_run_cmd="/usr/libexec/sssd"
    local sssd_libexec_proc_num=0
    local -i times="2"

    local alarmInfo="Local Sssd Service;${HOST_NAME}"
    local additionalInfo="HostName:${HOST_NAME}.Cannot get information from LdapServer."

    if [ ! -d "${countFilePath}" ] ;then 
        echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "tmp dir does not exist."
        return $RET_ERR
    fi

    if [ ! -f "${countFile}" ]; then
        echo "0" > "${countFile}"
    fi

    process_not_exist_times=$(cat "${countFile}")

    #redhatOS的两种启动sssd方式
    pid1=$(ps -ww -eo pid,cmd | grep -w "${sssd_run_cmd[0]}" |grep -v grep)
    pid2=$(ps -ww -eo pid,cmd | grep -w "${sssd_run_cmd[1]}" |grep -v grep)
    sssdprocNum=$(ps -ww -eo pid,cmd | grep -w "/usr/sbin/sssd -D" | grep -v grep | wc -l)

    #sssd服务启动后子进程检查
    sssd_libexec_proc_num=$(ps -ww -eo pid,cmd | grep -w "${sssd_libexec_run_cmd}" | grep -v grep | wc -l)

    if [ -z "${pid1}" -a -z "${pid2}" ]; then
        if [ "${process_not_exist_times}" -le "${times}" ]; then
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "sssd service has not been started,times=${process_not_exist_times}."
            process_not_exist_times=$((process_not_exist_times+1))
            echo "${process_not_exist_times}" > "${countFile}"
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "no need to send an alarm."
        else
            #send alarm
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "process does not exist,need to send an alarm."
            alarm_func "25006" "0" "2" "60" "" "LdapClient" "NA" "${alarmInfo}" "${additionalInfo}"
        fi
        #重启sssd服务
        sudo ${SUDO_PATH_NODEAGENT} ldap_stopSssd 
        sleep 3
        sudo ${SUDO_PATH_NODEAGENT} ldap_sssd_D 
    else
        if [ $sssdprocNum -gt 1 ];then
            #重启sssd服务
            echoLog "sssdprocNum is greater than 1, restart it"
            sudo ${SUDO_PATH_NODEAGENT} ldap_stopSssd
            sleep 3
            sudo ${SUDO_PATH_NODEAGENT} ldap_sssd_D
        fi
        id "${id_user}" > /dev/null 2>&1
        result=$?
        if [ "${result}" -ne 0 -o "${sssd_libexec_proc_num}" -lt 3 ];then
            if [ "${process_not_exist_times}" -le "${times}" ]; then
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "can not detect user,times=${process_not_exist_times}."
                process_not_exist_times=$((process_not_exist_times+1))
                echo "${process_not_exist_times}" > "${countFile}"
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${WARN}"  "no need to send an alarm."
            else
                echoLog  "${LINENO}"  "${LAUNCHROLE}" "${ERR}"  "can not detect the user,need to send an alarm."
                #send an alarm
                alarm_func "25006" "0" "2" "60" "" "LdapClient" "NA" "${alarmInfo}" "${additionalInfo}"
            fi
            #重启sssd服务
            sudo ${SUDO_PATH_NODEAGENT} ldap_stopSssd 
            sleep 3
            sudo ${SUDO_PATH_NODEAGENT} ldap_sssd_D 
        else
            echo "0" > "${countFile}"
            echoLog  "${LINENO}"  "${LAUNCHROLE}" "${INFO}"  "detect the user successfully,sssd service is normal."
            #recover alarm
            alarm_func "25006" "1" "2" "60" "" "LdapClient" "NA" "${alarmInfo}" "${additionalInfo}"
            return $RET_OK
        fi
    fi

}



g_current_path="$(getCurrentPath)"

. "${g_current_path}/common/variable/constants.sh"
   init_env
. "${g_current_path}/common/log/log_tool.sh"
. "${g_current_path}/common/script/ldapclient_common.sh" 
   
g_script_name="$(basename "${BASH_SOURCE-$0}")"
g_os_type="$(getOsType)" 

declare LDAPCLIENT_CHECK_CONFIG="${g_current_path}/ldapclient_check_config"

#确保多个进程访问改文件
  lockfile=$BIGDATA_HOME/tmp/.ldapclient_hmon.lock
{
    if [ -z $(which flock) ]; then
        echoLog  "${LINENO}" "${LAUNCHROLE}" "${ERR}" "flock doesn't exist."
        exit ${FAILED}
    fi
    # flock中的-e选项表示对该文件加排它锁,
    # -w选项表示如果此时文件正在被加锁,当前的flock命令将等待10秒,如果能锁住该文件,就继续执行,否则退出该命令
    flock -e -w 25  201
    if [ $? -ne 0 ]; then
       echoLog  "${LINENO}" "${LAUNCHROLE}" "${ERR}" "$lockfile is running now."
       exit ${FAILED}
    fi
    main
    retVal=$?
    flock -u 201
    rm -f "${lockfile}"
    exit ${retVal}
    
} 201<>"${lockfile}"




