#!/bin/bash #==脚本执行中遇到不存在的变量就报错 set -o nounset #==脚本执行中报错即刻退出 set -o errexit #==脚本执行只要一个子命令失 set -o pipefail readonly BRAND_FORMAL_NAME="Cloudwise" readonly BRAND_PRODUCT_NAME="euspace" #== 根路径 readonly BRAND_PARENT_PRODUCT_NAME="omniagent" readonly BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME}" readonly BRAND_FORMAL_NAME_LOWER="cloudwise" readonly BRAND_PRODUCT_NAME_LOWER="euspace" readonly BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="cloudwise" #== ********************************************************** #== 配置重要文件名称 #== ********************************************************** #== smartagentd readonly AGENT_PROC="euspace" readonly AGENT_INSTALLER_VERSION=1.0.0 #== ********************************************************** #== 配置目录 #== ********************************************************** readonly INSTALL_BASE=/opt #== /opt/cloudwise/omniagent/agents 目录 readonly BASE_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents #== cloudwise/omniagent/agents/agent readonly INSTALL_FOLDER=${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents/${BRAND_PRODUCT_NAME_LOWER} #== cloudwise/omniagent/agents/agent/version readonly INSTALL_VERSION_FOLDER=${INSTALL_FOLDER}/${AGENT_INSTALLER_VERSION} #== /opt/cloudwise/omniagent/agents/agent/version readonly INSTALL_DIR=${INSTALL_BASE}/${INSTALL_VERSION_FOLDER} #== /opt/cloudwise/omniagent/agents/agent readonly AGENT_BASE_DIR=${INSTALL_BASE}/${INSTALL_FOLDER} readonly CURRENT_VERSION_LINK=${AGENT_BASE_DIR}/current #== /opt/cloudwise/omniagent/conf readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf" readonly AGENT_LIBS_DIR="${INSTALL_DIR}/libs" #== agent 初始化脚本目录 /opt/cloudwise/omniagent/scripts readonly AGENT_SCRIPTS_DIR="${INSTALL_DIR}/scripts" #== agent 初始化脚本目录 /opt/cloudwise/omniagent/bin readonly AGENT_BIN_DIR="${INSTALL_DIR}/bin" readonly AGENT_AGENTS_DIR="${INSTALL_DIR}/agents" readonly AGENT_RUNTIME_DIR="${INSTALL_DIR}/runtime" readonly PERL_FILE="/usr/bin/perl" readonly SAFE_RM_FILE="safe-rm" readonly SAFE_RM_BIN="${AGENT_BIN_DIR}/${SAFE_RM_FILE}" if [ -f ${PERL_FILE} ] && [ -f "${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/bin/${SAFE_RM_FILE}" ]; then readonly SAFE_RM_EXEC="${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/bin/${SAFE_RM_FILE}" else readonly SAFE_RM_EXEC="rm" fi readonly LOG_DIR_NAME=logs #== /opt/cloudwise/omniagent/logs readonly LOG_DIR=${INSTALL_DIR}/${LOG_DIR_NAME} #== /var/log/cloudwise/omniagent/ readonly INSTALLER_LOG_DIR="/var/log/${INSTALL_FOLDER}" #readonly INSTALLER_LOG_SUBDIR="installer" ##== /opt/cloudwise/smartagent/log/installer #readonly INSTALLER_LOG_DIR=${LOG_DIR}/${INSTALLER_LOG_SUBDIR} readonly AGENT_PID_FILE="${INSTALL_DIR}/bin/${AGENT_PROC}.pid" #== 【0】= readonly INSTALLER_LOCK_FILE="/tmp/${BRAND_FORMAL_NAME_LOWER}_${BRAND_PRODUCT_NAME_LOWER}.lock" readonly INIT_SYSTEM_SYSV="SysV" #== 系统 systemd readonly INIT_SYSTEM_SYSTEMD="systemd" #== cw-serveragent readonly SERVICE_SCRIPT_FILE="cw-oneagent" #== cw-serveragent.service readonly SYSTEMD_UNIT_FILE_AGENT="${SERVICE_SCRIPT_FILE}.service" #== 系统文件目录 readonly SYSTEMD_UNIT_FILES_DIR="/etc/systemd/system/" readonly EXIT_CODE_OK=0 readonly EXIT_CODE_GENERIC_ERROR=1 readonly EXIT_CODE_SIGNAL_RECEIVED=12 readonly EXIT_CODE_ANOTHER_INSTALLER_RUNNING=13 readonly EXIT_CODE_AGENT_CONTAINER_RUNNING=14 readonly EXIT_CODE_GLIBC_VERSION_TOO_LOW=15 readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17 readonly USER="root" readonly GROUP="root" #== 非root模式 readonly PARAM_NON_ROOT_MODE=false readonly CONTAINER_DEPLOYMENT_STATE_ENTRY=false #== 是否有 SELinux readonly ARCH_HAS_SELINUX=true ################################################################################ # Logs ################################################################################ toLog() { if [ -e "${LOG_FILE}" ]; then printf '%s UTC %s\n' "$(date -u +"%Y-%m-%d %H:%M:%S")" "$*" >>"${LOG_FILE}" 2>/dev/null fi } toConsoleOnly() { printf '%s %s\n' "$(date +"%H:%M:%S")" "$*" 2>/dev/null } toLogInfo() { toLog "[INFO]" "$@" } toLogWarning() { toLog "[WARN]" "$@" } toLogError() { toLog "[ERROR]" "$@" } toLogAdaptive() { local success="${1}" shift if [ "${success}" -eq 0 ]; then toLogInfo "$@" else toLogError "$@" fi } toConsoleInfo() { toConsoleOnly "$@" toLogInfo "$@" } toConsoleWarning() { toConsoleOnly "Warning:" "$@" toLogWarning "$@" } >&2 toConsoleError() { toConsoleOnly "Error:" "$@" toLogError "$@" } >&2 createDirIfNotExistAndSetRights() { local dir="${1}" local rights="${2}" if [ ! -d "${dir}" ]; then toLogInfo "Creating directory ${dir} with rights ${rights}" local message if ! message="$(mkdir -p "${dir}" 2>&1)"; then toConsoleWarning "Cannot create ${dir} directory." toLogWarning "Error message: ${message}" return 1 fi fi if ! message="$(chmod "${rights}" "${dir}" 2>&1)"; then toConsoleWarning "Cannot change permisions of ${dir} directory to ${rights}." toLogWarning "Error message: ${message}" return 1 fi return 0 } #== 创建日志目录及日志文件installation_$$.log createLogDirsIfMissing() { createDirIfNotExistAndSetRights "${INSTALL_BASE}" u+rwx,g+rx,o+rx createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" u+rwx,g+rx,o+rx createDirIfNotExistAndSetRights "${INSTALL_DIR}" 1775 createDirIfNotExistAndSetRights "${LOG_DIR}" 1777 createDirIfNotExistAndSetRights "${INSTALLER_LOG_DIR}" 1777 # for agentLog in ${PLUGIN_LOG_NAMES}; do # createDirIfNotExistAndSetRights "${LOG_DIR}/${agentLog}" 1777 # done touch "${LOG_FILE}" setRightsForFiles "${LOG_FILE}" 766 } ################################################################################ # Platform characteristics detection ################################################################################ #== 设置文件可执行权限 setRightsForFiles() { local file="${1}" local perms="${2}" if [ -f "${file}" ]; then chmod "${perms}" "${file}" elif [ -d "${file}" ]; then chmod -R "${perms}" "${file}" fi } #== 安装类型(f:文件,d:目录)递归设置权限 chmod4FilesRecursively() { local dir="${1}" local type="${2}" local mask="${3}" find "${dir}" -type "${type}" -exec chmod "${mask}" {} \; } detectLinuxDistribution() { if [ -f /etc/redhat-release ]; then cat /etc/redhat-release elif [ -f /etc/os-release ]; then ( . /etc/os-release local distrib="${NAME}" if [ -z "${distrib}" ]; then distrib="${ID}" fi local version="${VERSION_ID}" if printf "%s" "${distrib}" | grep -iq "debian"; then version="$(cat /etc/debian_version)" fi printf "%s %s" "${distrib}" "${version}" ) elif [ -f /etc/SuSE-release ]; then head -1 /etc/SuSE-release elif [ -f /etc/lsb-release ]; then ( . /etc/lsb-release printf "%s %s" "${DISTRIB_ID}" "${DISTRIB_RELEASE}" ) elif ls /etc/*release* >/dev/null 2>&1; then # Generic fallback cat /etc/*release* else printf "AIX %s" "$(oslevel -s 2>&1)" fi } checkInitSystem() { local version if version="$(systemctl --version 2>&1)"; then if [ -d "${SYSTEMD_UNIT_FILES_DIR}" ]; then readonly INIT_SYSTEM=${INIT_SYSTEM_SYSTEMD} else readonly INIT_SYSTEM=${INIT_SYSTEM_SYSV} toLogWarning "${INIT_SYSTEM_SYSTEMD} was detected but ${SYSTEMD_UNIT_FILES_DIR} does not exist, using ${INIT_SYSTEM_SYSV} handling as a fallback" fi else readonly INIT_SYSTEM=${INIT_SYSTEM_SYSV} if ! version="$(init --version 2>&1)"; then if ! version="$(chkconfig --version 2>&1)"; then version="$(head -n1 /etc/inittab 2>&1)" fi fi fi readonly INIT_SYSTEM_VERSION="$(printf '%s' "${version}" 2>/dev/null | head -n1)" } setLocationOfInitScripts() { toLogInfo "Determining location of init scripts..." if [ "${INIT_SYSTEM}" = "${INIT_SYSTEM_SYSTEMD}" ] || [ "${ARCH_ARCH}" = "AIX" ]; then readonly INIT_DIR="${AGENT_SCRIPTS_DIR}" else if [ -d "/etc/init.d" ]; then readonly INIT_DIR="/etc/init.d" elif [ -d "/sbin/init.d" ]; then readonly INIT_DIR="/sbin/init.d" elif [ -d "/etc/rc.d" ]; then readonly INIT_DIR="/etc/rc.d" else return 1 fi fi toLogInfo "Location of init scripts ${INIT_DIR}" return 0 } detectArchitecture() { local detected_arch= if isAvailable arch; then detected_arch="$(arch | tr '[:lower:]' '[:upper:]')" fi if [ -z "${detected_arch}" ]; then detected_arch="$(uname -m | tr '[:lower:]' '[:upper:]')" fi printf '%s' "${detected_arch}" } ################################################################################ # Misc functions ################################################################################ getAgentCtlBinPath() { printf "%s" "${AGENT_TOOLS_DIR}/lib64/${AGENT_CTL_BIN}" } getOsConfigBinPath() { printf "%s" "${AGENT_INSTALL_DIR}/lib64/${AGENT_OS_CONFIG_BIN}" } commandErrorWrapper() { set +e local command="${*}" local errorFile="/tmp/smartagent_commanderror_$$" ${command} 2>"${errorFile}" local returnCode=$? if [ ${returnCode} -ne 0 ]; then toLogWarning "Command '${command}' failed, return code: ${returnCode}, message: $(cat "${errorFile}")" fi ${SAFE_RM_EXEC} -f "${errorFile}" set -e return ${returnCode} } checkRootAccess() { toConsoleInfo "Checking root privileges..." if [ "$(id -u)" != "0" ]; then toConsoleError "NOT OK" return 1 fi toConsoleInfo "OK" return 0 } removeIfExists() { local pathToRemove="${1}" toLogInfo "${SAFE_RM_EXEC} -rf ${pathToRemove}" if [ ! -e "${pathToRemove}" ]; then toLogInfo "${pathToRemove} does not exist, skipping removal" return fi local output if ! output="$(${SAFE_RM_EXEC} -rf "${pathToRemove}" 2>&1)"; then toLogWarning "Failed to remove ${pathToRemove}: ${output}" fi } ################################################################################ # SELinux related functions ################################################################################ executeUsingOsConfigBin() { local command="${1}" local unit="${2}" if [ "${unit}" ]; then command="${command}-${unit}" unit="" fi local output= output="$("$(getOsConfigBinPath)" "${command}" 2>&1)" local exitCode=$? toLogAdaptive ${exitCode} "Executed $(getOsConfigBinPath) ${command} ${unit}, exitCode = ${exitCode}, output: ${output}" return ${exitCode} } executeSystemctlCommand() { local command="${1}" local unit="${2}" if [ "$(id -u)" != 0 ]; then executeUsingOsConfigBin "${command}" "${unit}" return $? fi local output= #== shellcheck disable=SC2086 output="$(systemctl "${command}" ${unit} 2>&1)" local exitCode=$? if [ ${exitCode} -eq 0 ]; then toLogInfo "Successfully executed: systemctl ${command} ${unit}" else toLogError "Failed to execute: systemctl ${command} ${unit}" toLogError "Command output: ${output}" if [ -n "${unit}" ]; then local reachBackNumSeconds=360 toLogError "journalctl output: $(journalctl -u "${unit}" --since=-${reachBackNumSeconds} 2>&1)" fi fi return ${exitCode} } 2>>"${LOG_FILE}" executeInitScriptCommand() { local command= local parameters="$*" local output= local exitCode= if isAvailable service; then command="service" parameters="${SERVICE_SCRIPT_FILE} ${parameters}" else command="${INIT_DIR}/${SERVICE_SCRIPT_FILE}" fi #shellcheck disable=SC2086 output="$("${command}" ${parameters} 2>&1)" exitCode=$? toLogAdaptive ${exitCode} "Executed ${command} ${parameters}, exitCode = ${exitCode}, output: ${output}" return ${exitCode} } signalHandler() { end_exit_code=$? if [ ${end_exit_code} -eq ${EXIT_CODE_SIGNAL_RECEIVED} ]; then return fi local signal="${1}" local callback="${2}" if [ ${end_exit_code} -ne 0 ]; then toLogWarning "Process Received [Signal: ${signal}] [Code : ${end_exit_code}]" fi ${callback} ${end_exit_code} if [ ${end_exit_code} -eq ${EXIT_CODE_OK} ]; then exit ${EXIT_CODE_OK} fi exit ${EXIT_CODE_SIGNAL_RECEIVED} } configureSignalHandling() { local callback="${1}" for signal in HUP INT QUIT ABRT ALRM TERM EXIT; do # shellcheck disable=SC2064 trap "signalHandler '${signal}' '${callback}'" ${signal} done trap "" PIPE } removeSecretsFromString() { printf "%s" "$*" | sed 's#\(Api-Token=\)[[:alnum:]_-]\{21\}#\1***#' | sed 's#\(TENANT_TOKEN=\)[[:alnum:]]\{16\}#\1***#' | sed 's#\(latest/\)[[:alnum:]]\{16\}#\1***#' | sed 's#\(PROXY=\)[^[:space:]]*#\1***#' } #== waitTime must be divisible by 10 sendSignalToProcessAndWaitForStop() { local pidCheckingFunction="${1}" local signal="${2}" local action="${3}" local waitTime="${4}" local pidToStop="${5}" if ! ${pidCheckingFunction} "${pidToStop}"; then toLogInfo "Process with pid ${pidToStop} doesn't exist" return fi toConsoleInfo "Waiting ${waitTime} seconds for process with pid ${pidToStop} to ${action}." while [ "${waitTime}" -gt 0 ]; do if [ "$((waitTime % 10))" -eq 0 ]; then toLogInfo "Sending signal: ${signal} to ${pidToStop}" kill -s "${signal}" "${pidToStop}" 2>>"${LOG_FILE}" fi if ! ${pidCheckingFunction} "${pidToStop}"; then return 0 fi sleep 1 waitTime=$((waitTime - 1)) done return 1 } testWriteAccessToDir() { local errorFile="/tmp/smartagent_commandError_$$" local dir="${1}" local tmpfilename if [ "${ARCH_ARCH}" = "AIX" ]; then tmpfilename="${dir}/.tmp_${BRAND_PRODUCT_NAME_LOWER}.$$${RANDOM}" touch "${tmpfilename}" 2>"${errorFile}" else tmpfilename="$(mktemp -p "${dir}" ".tmp_${BRAND_PRODUCT_NAME_LOWER}.XXXXXXXXXXXXXX" 2>"${errorFile}")" fi #shellcheck disable=SC2181 if [ $? -ne 0 ]; then toLogInfo "$(cat "${errorFile}")" ${SAFE_RM_EXEC} -f "${errorFile}" return 1 fi ${SAFE_RM_EXEC} -f "${tmpfilename}" "${errorFile}" return 0 } setPATH() { local prependToPATH="/usr/sbin:/usr/bin:/sbin:/bin" if [ "${PATH}" ]; then PATH=${prependToPATH}:${PATH} else PATH=${prependToPATH} fi } systemLibDirSanityCheck() { local dir="${1}" if [ ! -d "${dir}" ]; then toLogWarning "Directory: ${dir} does not exist" printf "" return fi if ! testWriteAccessToDir "${dir}"; then toLogWarning "Detected that ${dir} is not writable" dir="${PA_FALLBACK_INSTALLATION_DIR}${dir}" createDirIfNotExistAndSetRights "${dir}" 755 fi printf "%s" "${dir}" } isNonRootModeEnabled() { printf '%s' "${PARAM_NON_ROOT_MODE}" | grep -qE "(true|no_ambient)" } runAutostartAddingTool() { local prefix="${1}" local file="${2}" local suffix="${3}" local output if isNonRootModeEnabled && printf '%s' "${prefix}" | grep -q "chkconfig"; then local action="chkconfig-add" if printf '%s' "${prefix}" | grep -q -- "--del"; then action="chkconfig-del" fi toLogInfo "Using ${AGENT_OS_CONFIG_BIN} ${action}-${file} to modify autostart" output="$("$(getOsConfigBinPath)" "${action}-${file}" 2>&1)" else local command="${prefix}${file} ${suffix}" toLogInfo "Executing ${command}" output="$(${command} 2>&1)" fi local status=$? if [ "${output}" ]; then toLogAdaptive ${status} "${output}" fi return ${status} } readLinkFromLs() { local path="${1}" local result="${path}" local lsOutput="$(ls -dl "${path}" 2>/dev/null)" if printf '%s' "${lsOutput}" | grep -q " -> "; then local parsedLinkTarget="$(printf '%s' "${lsOutput}" | sed 's|^.* -> ||')" if [ "${parsedLinkTarget}" ]; then result="${parsedLinkTarget}" else toLogWarning "Failed to parse ls output '${lsOutput}'" fi fi printf '%s' "${result}" } readLink() { local args=-e local path="${1}" if [ "${2}" ]; then args="${1}" path="${2}" fi ( if [ "${ARCH_ARCH}" = "AIX" ]; then PATH="${PATH}:/opt/freeware/bin" fi if isAvailable readlink; then #shellcheck disable=SC2086 readlink ${args} "${path}" else toLogInfo "readlink command not found, falling back to parsing ls output" readLinkFromLs "${path}" fi ) } isAvailable() { command -v "${1}" >/dev/null 2>&1 } getValueFromConfigFile() { local key="${1}" local separator="${2}" local configFile="${3}" local defaultValue="${4}" local value="$(sed -n "s|${key}${separator}||p" "${configFile}" 2>/dev/null)" if [ "${value}" ]; then printf '%s' "${value}" else printf '%s' "${defaultValue}" fi } isAnotherInstallerRunning() { if [ ! -f "${INSTALLER_LOCK_FILE}" ]; then return 1 fi local pidFromLockFile="$(head -n 1 "${INSTALLER_LOCK_FILE}")" local nameFromLockFile="$(tail -n 1 "${INSTALLER_LOCK_FILE}")" if [ "$(wc -l <"${INSTALLER_LOCK_FILE}")" -ne 2 ] || [ -z "${pidFromLockFile}" ] || [ -z "${nameFromLockFile}" ]; then toConsoleWarning "Installer lock file ${INSTALLER_LOCK_FILE} is damaged, skipping uniqueness check." toConsoleWarning "Lock file contents: '$(cat ${INSTALLER_LOCK_FILE})'" return 1 fi #shellcheck disable=SC2009 local foundProcesses="$(ps -e -o "pid,args" 2>&1 | grep -w "${nameFromLockFile}" | grep -v " grep ")" if printf '%s' "${foundProcesses}" | awk '{ print $1 }' | grep -wq "${pidFromLockFile}"; then local errorMessage="Another ${BRAND_PRODUCT_NAME} installer or uninstaller is already running" if printf '%s' "${foundProcesses}" | grep -q "${DOWNLOADS_DIRECTORY}"; then errorMessage="${errorMessage} (AutoUpdate is in progress)" fi toConsoleError "${errorMessage}, PID ${pidFromLockFile}. Exiting." return 0 fi toConsoleInfo "Lock file exists but corresponding installer process does not run, contents of lock file: ${pidFromLockFile}, ${nameFromLockFile}." return 0 } createInstallerLockFile() { printf '%s\n%s\n' "$$" "$0" >"${INSTALLER_LOCK_FILE}" 2>/dev/null } removeInstallerLockFile() { toLogInfo "Removing installer lock file." ${SAFE_RM_EXEC} -f "${INSTALLER_LOCK_FILE}" } logBasicStartupInformation() { toLogInfo "Command line: $(removeSecretsFromString "${@}")" toLogInfo "Shell options: $-" toLogInfo "Working dir: $(pwd)" toLogInfo "PID: $$" toLogInfo "Parent process: $( printf '\n' ps -o user,pid,ppid,comm -p ${PPID} 2>&1 )" toLogInfo "User id: $(id -u)" } mapPidsToName() { local pids="${1}" local output for pid in ${pids}; do local name="$(grep 'Name:' "/proc/${pid}/status" 2>/dev/null | awk '{print $2}')" output="${output}, ${pid} (${name})" done printf '%s' "${output}" | cut -c 3- } readonly ARCH_ARCH="X86" readonly ARCH_VERSIONED_LIB_DIR_PREFIX="linux-x86" arch_checkArchitectureCompatibility() { local arch="$(detectArchitecture)" if [ "${arch}" = "X86_64" ] || [ "${arch}" = "IA64" ]; then arch="X86_64" else arch="$(uname -m | sed -e 's/i.86/x86/' | sed -e 's/i86pc/x86/' | tr '[:lower:]' '[:upper:]')" fi printf '%s' "${arch}" [ "${arch}" = "X86_64" ] } arch_local_getLibraryPathFromLdd() { local binary="${1}" ldd "${binary}" 2>/dev/null | grep libc.so | awk '{ print $3 }' } arch_local_detectProcessAgentInstallerDirectories() { local useLddOutput="false" local systemLib32Prefix systemLib32Prefix="$(arch_local_getSystemLibraryPath 32)" local exitCode=$? if [ ! "${systemLib32Prefix}" ]; then if [ "${exitCode}" -eq 0 ]; then toLogWarning "This is a 64-bit platform with 32-bit libraries installed, but ${AGENT_INSTALL_ACTION_BIN} failed to determine their location" useLddOutput="true" else toLogInfo "This is a 64-bit platform and 32-bit libraries were not detected" fi else systemLib32Prefix="$(systemLibDirSanityCheck "/${systemLib32Prefix}")" if [ ! "${systemLib32Prefix}" ]; then useLddOutput="true" fi fi local systemLib64Prefix="$(arch_local_getSystemLibraryPath 64)" if [ ! "${systemLib64Prefix}" ]; then toLogWarning "This is a 64-bit platform, but ${AGENT_INSTALL_ACTION_BIN} failed to determine location of 64-bit libraries" useLddOutput="true" else systemLib64Prefix="$(systemLibDirSanityCheck "/${systemLib64Prefix}")" if [ ! "${systemLib64Prefix}" ]; then useLddOutput="true" fi fi if [ "${useLddOutput}" = "true" ]; then arch_local_detectProcessAgentDirectoriesBasedOnLdd else readonly SYSTEM_LIB32="${systemLib32Prefix}" readonly SYSTEM_LIB64="${systemLib64Prefix}" fi } 2>>"${LOG_FILE}" arch_detectProcessAgentInstallerDirectories() { if [ "${CONTAINER_DEPLOYMENT_STATE_ENTRY}"x = "true"x ]; then readonly SYSTEM_LIB32="${PA_FALLBACK_INSTALLATION_DIR}/lib32" readonly SYSTEM_LIB64="${PA_FALLBACK_INSTALLATION_DIR}/lib64" createDirIfNotExistAndSetRights "${SYSTEM_LIB32}" 755 createDirIfNotExistAndSetRights "${SYSTEM_LIB64}" 755 return 0 fi arch_local_detectProcessAgentInstallerDirectories } arch_getLibMacro() { local libMacro="" if [ "${SYSTEM_LIB32}" ]; then #shellcheck disable=SC2016 libMacro='/$LIB' fi printf "%s" "${libMacro}" } arch_checkGlibc() { local glibcVersion="$(ldd --version | awk 'NR==1{ print $NF }')" toLogInfo "Detected glibc version: ${glibcVersion}" if [ "$(format_version "${glibcVersion}")" -gt "$(format_version "${GLIBC_SUPPORTED_VERSION}")" ]; then return elif [ "$(format_version "${glibcVersion}")" -lt "$(format_version "${GLIBC_SUPPORTED_VERSION}")" ]; then toConsoleError "We can't continue setup. The glibc version: ${glibcVersion} detected on your system isn't supported." toConsoleError "To install ${BRAND_AGENT_PRODUCT_NAME} you need at least glibc ${GLIBC_SUPPORTED_VERSION}." toConsoleError "Stopping installer process..." finishInstaller "${EXIT_CODE_GLIBC_VERSION_TOO_LOW}" fi if ! isAvailable rpm; then toLogInfo "RPM not detected - skipping glibc patch version check." return fi local glibcFullVersion="$(arch_runCommandWithTimeout 60 "rpm" "-q" "glibc" | tail -n 1)" if [ ! "${glibcFullVersion}" ]; then toConsoleError "Could not determine exact glibc version using RPM." finishInstaller "${EXIT_CODE_GLIBC_VERSION_TOO_LOW}" fi # fix for RedHat 5.x with unsufficient glibc 2.5 patch version local glibcPatchVersion="$(format_patch "${glibcFullVersion}")" if [ "$(format_version "${glibcVersion}")" -eq "$(format_version "${GLIBC_SUPPORTED_VERSION}")" ] && [ "${glibcPatchVersion}" -lt "${GLIBC_SUPPORTED_VERSION_MINIMAL_PATCH}" ]; then toConsoleError "glibc patch version: ${glibcPatchVersion} detected on your system is not supported, setup won't continue." toConsoleError "To install ${BRAND_AGENT_PRODUCT_NAME} you need at least glibc ${GLIBC_SUPPORTED_VERSION}-${GLIBC_SUPPORTED_VERSION_MINIMAL_PATCH}." finishInstaller "${EXIT_CODE_GLIBC_VERSION_TOO_LOW}" fi } # 'timeout' requires gnu-coreutils8, i.e. it is not available on RHEL5, that's why we need this utility function arch_runCommandWithTimeout() { local commandTimeout="${1}" shift local resultFile="/tmp/smartagent_commandResult_$$" local errorFile="/tmp/smartagent_commandError_$$" local loopErrorsFile="/tmp/smartagent_loopErrors_$$" toLogInfo "Executing $* with timeout ${commandTimeout} seconds" ( "$@" >${resultFile} 2>${errorFile} & child=$! while [ "${commandTimeout}" -gt 0 ]; do toLogInfo "Time left: ${commandTimeout} s, pid: ${child}" sleep 1 kill -0 "${child}" 2>/dev/null || exit 0 commandTimeout=$((commandTimeout - 1)) done # Be nice, post SIGTERM first. # The 'exit 0' below will be executed if any preceeding command fails. toLogInfo "Killing ${child} with SIGTERM" kill -s 15 "${child}" && kill -0 "${child}" || exit 0 sleep 1 toLogWarning "Killing ${child} with SIGKILL" kill -s 9 "${child}" ) 2>"${loopErrorsFile}" local errorOutput="$(cat "${errorFile}")" local commandOutput="$(cat "${resultFile}")" local loopErrors="$(cat "${loopErrorsFile}")" ${SAFE_RM_EXEC} -f "${errorFile}" "${resultFile}" "${loopErrorsFile}" if [ -n "${errorOutput}" ]; then toLogInfo "Failed to execute command, error output: ${errorOutput}" if [ "${loopErrors}" ]; then toLogInfo "Loop errors: ${loopErrors}" fi printf "" return 1 else toLogInfo "Command executed successfully, output: ${commandOutput}" if [ "${loopErrors}" ]; then toLogInfo "Loop errors: ${loopErrors}" fi printf '%s' "${commandOutput}" return 0 fi } arch_getAccessRights() { stat --format='%A' "${1}" } arch_preloadTest() { if [ "${SYSTEM_LIB32}" ]; then runSanityCheckCommand "performLdPreloadSanityCheck" "32" local returnCode=$? if [ ${returnCode} -ne 0 ]; then return ${returnCode} fi fi if [ "${SYSTEM_LIB64}" ]; then runSanityCheckCommand "performLdPreloadSanityCheck" "64" fi } arch_checkEnvironmentConfiguration() { if ! stat --format='%t,%T' /dev/null | grep -q "1,3"; then toLogInfo "$(stat /dev/null)" toConsoleError "Installer detected corruption of '/dev/null': Not a character device" return "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}" fi return 0 } arch_moveReplaceTarget() { local source="${1}" local target="${2}" mv -fT "${source}" "${target}" } initLog() { if [ "${CONTAINER_DEPLOYMENT_STATE_ENTRY}"x != "true"x ]; then createLogDirsIfMissing fi toLogInfo "Uninstaller started." toLogInfo "Distribution: $(detectLinuxDistribution)" logBasicStartupInformation "${@}" } finishUninstaller() { removeInstallerLockFile if [ -z "$(ls -A ${INSTALL_DIR})" ];then ${SAFE_RM_EXEC} -df ${INSTALL_DIR} ${SAFE_RM_EXEC} -f ${CURRENT_VERSION_LINK} fi if [ $1 -eq 0 ]; then toConsoleInfo "Uninstaller finished successfully" else toConsoleInfo "Uninstaller finished failed" fi exit "${EXIT_CODE_OK}" } setLogFilePath() { #== - 反安装日志: uninstallation-{timestamp}.log 如: uninstallation-20220601110912.log readonly LOG_FILE="${INSTALLER_LOG_DIR}/uninstallation-"$(date -u +"%Y%m%d%H%M%S")".log" } removeScriptsFromAutostart() { local prefix="${1}" local suffix="${2}" if ! runAutostartAddingTool "${prefix}" "${SERVICE_SCRIPT_FILE}" "${suffix}"; then toConsoleError "Failed to remove ${SERVICE_SCRIPT_FILE} from autostart. For details, see ${LOG_FILE}" fi } removeUnitFromSystemd() { local unit=${1} if [ ! -e "${SYSTEMD_UNIT_FILES_DIR}/${unit}" ]; then toLogInfo "${unit} does not exist and will not be removed from ${INIT_SYSTEM_SYSTEMD} autostart" return fi executeSystemctlCommand disable "${unit}" ${SAFE_RM_EXEC} -f "${SYSTEMD_UNIT_FILES_DIR}/${unit}" } removeSystemvAutostart() { toConsoleInfo "Removing ${BRAND_AGENT_PRODUCT_NAME} from autostart" #Order of checking is important if [ -x /usr/bin/update-rc.d ]; then #Ubuntu removeScriptsFromAutostart "/usr/bin/update-rc.d -f " "remove" elif [ -x /usr/sbin/update-rc.d ]; then #Ubuntu removeScriptsFromAutostart "/usr/sbin/update-rc.d -f " "remove" elif [ -x /sbin/chkconfig ]; then #RedHat removeScriptsFromAutostart "/sbin/chkconfig --del " elif [ -x /usr/lib/lsb/install_initd ]; then #Suse removeScriptsFromAutostart "/usr/lib/lsb/install_initd ${INIT_DIR}/" elif [ "${ARCH_ARCH}" = "AIX" ]; then #== 不存在 arch_removeAutostart else toConsoleError "Couldn't remove ${BRAND_AGENT_PRODUCT_NAME} from autostart." fi } removeSystemdAutostart() { removeUnitFromSystemd "${SYSTEMD_UNIT_FILE_AGENT}" executeSystemctlCommand daemon-reload "" } stopAgentService() { if [ -s "${AGENT_PID_FILE}" ]; then toLogInfo "Stop ${AGENT_PROC}..." commandErrorWrapper ${AGENT_BIN_DIR}/agentctl stop fi } removeSystemvInitScripts() { if [ "${ARCH_ARCH}" = "AIX" ]; then return fi toConsoleInfo "Removing ${SERVICE_SCRIPT_FILE} from ${INIT_DIR}" ${SAFE_RM_EXEC} -f "${INIT_DIR}/${SERVICE_SCRIPT_FILE}" } removeAutostartScripts() { if [ "${INIT_SYSTEM}" = "${INIT_SYSTEM_SYSV}" ]; then removeSystemvAutostart removeSystemvInitScripts else removeSystemdAutostart fi } createUninstallInfoFile() { local reason if [ "${IS_UPGRADING}"x = "true"x ]; then reason="upgrade" else reason="uninstall" fi toLogInfo "Creating uninstall.info file: ${reason}" } initializeUninstaller() { local installerPid= local skipRootPrivilegesCheck= if [ $# -eq 1 ]; then installerPid="${1}" fi if [ $# -eq 2 ]; then installerPid="${1}" skipRootPrivilegesCheck="${2}" fi setPATH #setLogFilePath "${installerPid}" setLogFilePath if [ "${installerPid}" ] && [ "${installerPid}"x != "online"x ]; then IS_UPGRADING="true" else IS_UPGRADING="false" fi toConsoleInfo "IS_UPGRADING :${IS_UPGRADING}" if [ "${skipRootPrivilegesCheck}"x = "true"x ] && [ "${IS_UPGRADING}"x = "true"x ]; then toConsoleInfo "Skipping root privileges check" else if ! checkRootAccess; then toConsoleError "You must run uninstaller with root privileges" exit "${EXIT_CODE_GENERIC_ERROR}" fi fi initLog "${@}" toLogInfo "Launched during upgrade: ${IS_UPGRADING}" createUninstallInfoFile configureSignalHandling "finishUninstaller" if [ "${IS_UPGRADING}"x = "false"x ] && [ "${CONTAINER_DEPLOYMENT_STATE_ENTRY}"x != "true"x ]; then if isAnotherInstallerRunning; then exit "${EXIT_CODE_ANOTHER_INSTALLER_RUNNING}" fi createInstallerLockFile fi if [ ! -f ${PERL_FILE} ]; then toConsoleInfo "/usr/bin/perl file not found so ${SAFE_RM_EXEC} is used." fi toConsoleInfo "Using ${SAFE_RM_EXEC} to uninstall" } getVolumeStorageAgentInstallDir() { readLink "$(dirname "${0}")" } cleanUpSELinux() { if [ ! "${ARCH_HAS_SELINUX}" ] || ! isAvailable semodule; then return fi toConsoleInfo "Removing ${BRAND_FORMAL_NAME} SELinux policies, this may take a while..." } cleanUpFilesDuringUninstall() { toLogInfo "This is a full uninstaller, cleaning up rest of the files" local fileNames="${AGENT_CONF_DIR} ${AGENT_BIN_DIR} ${LOG_DIR} ${AGENT_SCRIPTS_DIR} ${AGENT_LIBS_DIR} ${AGENT_AGENTS_DIR} ${AGENT_RUNTIME_DIR}" for fileName in ${fileNames}; do removeIfExists "${fileName}" done fileNames="uninstall.sh installer.version" for fileName in ${fileNames}; do removeIfExists "${INSTALL_DIR}/${fileName}" done } handleRegularUninstaller() { checkInitSystem toLogInfo "Detected init system: ${INIT_SYSTEM}, version: ${INIT_SYSTEM_VERSION}" if ! setLocationOfInitScripts; then toLogWarning "Cannot determine location of init scripts." fi stopAgentService cleanUpFilesDuringUninstall } main() { initializeUninstaller "$@" handleRegularUninstaller "$@" # finishUninstaller } ################################################################################ # # Script start # ################################################################################ main "$@"