فهرست منبع

Feature #TASK_QT-18250 中央国债arm 5.0验证

Carl 10 ماه پیش
والد
کامیت
1352bfd9dc
36فایلهای تغییر یافته به همراه10028 افزوده شده و 0 حذف شده
  1. 6 0
      dist/aarch64/.gitignore
  2. 87 0
      dist/aarch64/README.md
  3. BIN
      dist/aarch64/package_dir/agents/NativeAgent/lib/apmAgent.jar
  4. BIN
      dist/aarch64/package_dir/agents/NativeAgent/lib/apmCore.jar
  5. BIN
      dist/aarch64/package_dir/agents/NativeAgent/lib/apmSpy.jar
  6. BIN
      dist/aarch64/package_dir/agents/NativeAgent/lib/libnativeAgent.so
  7. BIN
      dist/aarch64/package_dir/agents/NativeAgent/plugins/cloudwise-javacode-plugin-ssl-socket.jar
  8. 240 0
      dist/aarch64/package_dir/bin/agentctl
  9. 0 0
      dist/aarch64/package_dir/conf/.gitkeep
  10. BIN
      dist/aarch64/package_dir/libs/amd64/jvm/cwlibnet.so
  11. BIN
      dist/aarch64/package_dir/libs/arm64/jvm/cwlibnet.so
  12. 0 0
      dist/aarch64/package_dir/logs/.gitkeep
  13. 0 0
      dist/aarch64/package_dir/runtime/.gitkeep
  14. BIN
      dist/aarch64/package_dir/scripts/cwjattach
  15. 2954 0
      dist/aarch64/scripts/install_temp.sh
  16. 611 0
      dist/aarch64/scripts/package.sh
  17. 1116 0
      dist/aarch64/scripts/uninstall.sh
  18. BIN
      dist/aarch64/scripts/xzdec
  19. 6 0
      dist/x86_64/.gitignore
  20. 87 0
      dist/x86_64/README.md
  21. BIN
      dist/x86_64/package_dir/agents/NativeAgent/lib/apmAgent.jar
  22. BIN
      dist/x86_64/package_dir/agents/NativeAgent/lib/apmCore.jar
  23. BIN
      dist/x86_64/package_dir/agents/NativeAgent/lib/apmSpy.jar
  24. BIN
      dist/x86_64/package_dir/agents/NativeAgent/lib/libnativeAgent.so
  25. BIN
      dist/x86_64/package_dir/agents/NativeAgent/plugins/cloudwise-javacode-plugin-ssl-socket.jar
  26. 240 0
      dist/x86_64/package_dir/bin/agentctl
  27. 0 0
      dist/x86_64/package_dir/conf/.gitkeep
  28. BIN
      dist/x86_64/package_dir/libs/amd64/jvm/cwlibnet.so
  29. BIN
      dist/x86_64/package_dir/libs/arm64/jvm/cwlibnet.so
  30. 0 0
      dist/x86_64/package_dir/logs/.gitkeep
  31. 0 0
      dist/x86_64/package_dir/runtime/.gitkeep
  32. BIN
      dist/x86_64/package_dir/scripts/cwjattach
  33. 2954 0
      dist/x86_64/scripts/install_temp.sh
  34. 611 0
      dist/x86_64/scripts/package.sh
  35. 1116 0
      dist/x86_64/scripts/uninstall.sh
  36. BIN
      dist/x86_64/scripts/xzdec

+ 6 - 0
dist/aarch64/.gitignore

@@ -0,0 +1,6 @@
+.idea
+installer.version
+Cloudwise-euspace-installer*.sh
+logs/*
+package_dir/logs/*.log
+package_dir/runtime/memdump

+ 87 - 0
dist/aarch64/README.md

@@ -0,0 +1,87 @@
+
+## package.sh 介绍
+
+[scripts/package.sh](../../scripts/package.sh) 主要是将 SmartAgent 安装目录下所有内容(脚本无自动去除无用目录或内容功能)压缩,
+通过`base64`编码后写入 [scripts/install_temp.sh](../../scripts/install_temp.sh) 中,
+最终生成安装文件 `cwserveragent-installer-version.sh` (version为SmartSgent版本)。
+
+### 安装帮助
+
+执行命令 `sh scripts/package.sh -h` 即可查看安装帮助详情。详情如下:
+
+```
+Usage: package.sh [-h] [-v] [DEBUG=true|false] [AGENT_VERSION=8.6]
+
+
+-h, --help     Display this help and exit.
+-v, --version  Print version and exit.
+
+RELEASE        Default true; Whether to delete the publish parameter in the script.
+VERSION        Configure the Cloudwise SmartAgent version.
+DEBUG          Default false; 1、Debug mode executed script package.sh;
+               2、Remove the debug log from the scripts (Cloudwise-SmartAgent-Linux-1.2.0.sh、smartagent、uninstall.sh).
+
+```
+
+### smartagent目录结构
+
+打包前目录结构(请保持目录及内容最简)
+```
+smartagent
+├── cwserveragent-installer-1.1.0.sh
+├── bin
+│   ├── CW-ServerAgent
+│   └── safe-rm
+├── conf
+│   └── server-agent.ini
+└── scripts
+    ├── install_temp.sh
+    ├── package.sh
+    ├── cw-serveragent
+    ├── uninstall.sh
+    ├── uninstall_temp.sh
+    └── xzdec
+```
+
+打包后目录结构
+```
+smartagent
+├── cwserveragent-installer-1.1.0.sh
+├── installer.version
+├── bin
+│   ├── CW-ServerAgent
+│   └── safe-rm
+├── conf
+│   └── server-agent.ini
+└── scripts
+    ├── install_temp.sh
+    ├── package.sh
+    ├── cw-serveragent
+    ├── uninstall.sh
+    ├── uninstall_temp.sh
+    └── xzdec
+```
+
+安装后目录结构
+
+```
+├── bin
+│   ├── CW-ServerAgent
+│   └── safe-rm
+├── conf
+│   ├── cwserveragent.conf
+│   ├── installation.conf
+│   └── server-agent.ini
+├── installer.version
+├── logs
+│   └── serveragent
+│       ├── CW-ServerAgent.error.log
+│       ├── CW-ServerAgent.fatal.log
+│       └── CW-ServerAgent.panic.log
+├── runtime
+│   └── .pid
+├── scripts
+│   ├── cw-serveragent
+│   └── uninstall.sh
+└── uninstall.sh
+```

BIN
dist/aarch64/package_dir/agents/NativeAgent/lib/apmAgent.jar


BIN
dist/aarch64/package_dir/agents/NativeAgent/lib/apmCore.jar


BIN
dist/aarch64/package_dir/agents/NativeAgent/lib/apmSpy.jar


BIN
dist/aarch64/package_dir/agents/NativeAgent/lib/libnativeAgent.so


BIN
dist/aarch64/package_dir/agents/NativeAgent/plugins/cloudwise-javacode-plugin-ssl-socket.jar


+ 240 - 0
dist/aarch64/package_dir/bin/agentctl

@@ -0,0 +1,240 @@
+#!/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 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}/current
+#== /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 AGENT_BIN_DIR="${INSTALL_DIR}/bin"
+readonly AGENT_LOG_DIR="${INSTALL_DIR}/logs"
+
+#readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
+#readonly MAIN_CONF_FILE="${AGENT_CONF_DIR}/${AGENT_MAIN_CONF}"
+readonly EXIT_CODE_OK=0
+readonly EXIT_CODE_GENERIC_ERROR=1
+
+#== **********************************************************
+#==  配置重要文件名称
+#== **********************************************************
+readonly AGENT_PROC="euspace"
+readonly AGENT_CONFIG_PATH=""
+
+readonly AGENT_PID_FILE="${INSTALL_DIR}/bin/${AGENT_PROC}.pid"
+
+
+getDaemonPid(){
+    local agent="${1}"
+    #== 约定pid文件
+    local pidFilePath="${AGENT_PID_FILE}"
+    #== 二进制文件绝对路径
+    # shellcheck disable=SC2155
+    local procPath="$(readlink -m "${AGENT_BIN_DIR}/${agent}" 2>&1)"
+    local cmdline
+    local pid
+    #== 查询pid文件
+    if [ -s "${pidFilePath}" ] ; then
+      pid="$(cat "${pidFilePath}" 2>&1)"
+      cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
+      if [ -d "/proc/${pid}" ] && ( [[ ${cmdline} =~ ${procPath} ]] || [[ ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]] ); then
+#        toLogInfo "[${agent}] Find pid by ${pidFilePath} [content:${pid}][cmdline:${cmdline}]"
+          printf '%s' ${pid}
+          return 0
+      else
+        #== 进程绝对路径查询
+#        toLogWarning "[${agent}] Pidfile exist [content:${pid}]. But process not find or not myself. [cmdline:${cmdline}]"
+        if ! pid="$(listProcesses "${agent} pid" "${procPath}|${AGENT_BIN_DIR}/${agent}" "sudo|tail")"; then
+#          toLogWarning "[${agent}] Not find process grep '${procPath}'"
+          return 1
+        fi
+        cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
+        if ! [[ ${cmdline} =~ ${procPath} || ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]]; then
+#            toLogWarning "[${agent}] Find process success. But process not myself. [cmdline:${cmdline}]"
+            return 1
+        fi
+#        toLogInfo "[${agent}] Find pid by process name [${procPath}|${AGENT_BIN_DIR}/${agent}]"
+      fi
+    else
+      #== 进程绝对路径查询
+#      toLogWarning "[${agent}] Pidfile [${pidFilePath}] not find. Use abs path queries."
+      if ! pid="$(listProcesses "${agent} pid" "${procPath}|${AGENT_BIN_DIR}/${agent}" "sudo|tail")"; then
+#        toLogWarning "[${agent}] Not find process by grep '${procPath}'"
+        return 1
+      fi
+      cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
+      if ! [[ ${cmdline} =~ ${procPath} || ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]]; then
+#          toLogWarning "[${agent}] Find process success. But process not myself. [cmdline:${cmdline}]"
+          return 1
+      fi
+#      toLogInfo "[${agent}] Find pid by process name [${procPath}|${AGENT_BIN_DIR}/${agent}]."
+    fi
+
+    printf '%s' ${pid}
+    return 0
+}
+
+listProcesses() {
+  local errorMessage="${1}"
+  local includeRegex="${2}"
+
+  local excludeRegex=" grep"
+  if [ "${3}" ]; then
+    excludeRegex="grep|${3}"
+  fi
+
+#  toLogInfo "#DEBUG== listProcesses command: ps -e -o \"pid,args\" 2>&1 | grep -E "${includeRegex}" | awk '{{ print \$1,\$2 }}' | grep -vE \"${excludeRegex}\""
+  local output
+  if ! output="$(ps -e -o "pid,args" 2>&1 | grep -E "${includeRegex}" | awk '{{ print $1,$2 }}')"; then
+#    toLogError "Failed to get ${errorMessage}, output: ${output}"
+    return 1
+  fi
+
+  local foundProcesses="$(printf '%s' "${output}" | grep -vE "${excludeRegex}")"
+  if [ ! "${foundProcesses}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${foundProcesses}" | awk '{{ print $1 }}'
+  return 0
+}
+
+getAgentPid() {
+  local DAEMONPID="$(getDaemonPid "${AGENT_PROC}")"
+  if [ -z ${DAEMONPID} ]; then
+      return 1
+  fi
+  printf '%s' "${DAEMONPID}"
+
+}
+
+startAgent() {
+  local pid
+  if [ -f "${AGENT_BIN_DIR}/${AGENT_PROC}" ]; then
+    export DISABLE_E2E_TRACING=false
+    export DISABLE_STACK_TRACING=true
+    export SEND=1
+    local params="--listen=0.0.0.0:8123"
+#    if [ -f "/etc/chaosd/pki/ca.crt" ] && [ -f "/etc/chaosd/pki/chaosd.crt" ] && [ -f "/etc/chaosd/pki/chaosd.key" ]; then
+#        params="server  --https-port 31768 --CA=/etc/chaosd/pki/ca.crt --cert=/etc/chaosd/pki/chaosd.crt --key=/etc/chaosd/pki/chaosd.key"
+#    fi
+    pid=$(nohup ${AGENT_BIN_DIR}/${AGENT_PROC} ${params}>>"${AGENT_LOG_DIR}/service.log" 2>&1 & echo $!)
+    echo ${pid} > "${AGENT_PID_FILE}"
+  else
+    echo "${AGENT_BIN_DIR}/${AGENT_PROC} not exist."
+    exit "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+}
+
+agentStart() {
+  local agentPid
+  if agentPid="$(getAgentPid)"; then
+    echo "${BRAND_AGENT_PRODUCT_NAME} is running. Agent pid: ${agentPid}."
+    return
+  fi
+
+  startAgent
+	local exitCode=$?
+	if [ "${exitCode}" -ne 0 ]; then
+		echo "Failed to start ${BRAND_AGENT_PRODUCT_NAME} service."
+		exit "${EXIT_CODE_GENERIC_ERROR}"
+	fi
+
+  if agentPid="$(getAgentPid)"; then
+    echo "${BRAND_AGENT_PRODUCT_NAME} service started. Agent pid: ${agentPid}."
+  else
+    echo "${BRAND_AGENT_PRODUCT_NAME} not start!"
+    exit "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+agentStop() {
+  local agentPid
+  if agentPid="$(getAgentPid)"; then
+#    ${AGENT_BIN_DIR}/stop.sh ${agentPid}
+    kill ${agentPid}
+    echo "${BRAND_AGENT_PRODUCT_NAME} service stopped success."
+    cat /dev/null > "${AGENT_PID_FILE}"
+  else
+      echo "${BRAND_AGENT_PRODUCT_NAME} is stopped. service stopped success."
+  fi
+}
+
+agentRestart(){
+  agentStop
+  sleep 1
+  agentStart
+}
+
+agentStatus() {
+  local agentPid
+	local statusOutput
+  if agentPid="$(getAgentPid)"; then
+    statusOutput="${BRAND_AGENT_PRODUCT_NAME} is running. ${BRAND_AGENT_PRODUCT_NAME} pid: ${agentPid}"
+  else
+    statusOutput="${BRAND_AGENT_PRODUCT_NAME} is not running. ${BRAND_AGENT_PRODUCT_NAME} process not found or stop."
+  fi
+
+  echo "${statusOutput}"
+}
+
+info() {
+  local agentPid="$(getAgentPid)"
+  local version=$(cat "${INSTALL_DIR}/installer.version" | tr -d '\n')
+  printf '{"pid":%d,"version":"%s","agent_id":"%s","config":"%s","pipe": true}' "${agentPid}" "${version}" "${BRAND_PRODUCT_NAME_LOWER}" "${AGENT_CONFIG_PATH}"
+}
+
+################################################################################
+#
+# Script start
+#
+################################################################################
+
+main() {
+  case "$1" in
+  start)
+    agentStart
+    ;;
+  stop)
+    agentStop
+    ;;
+  restart)
+    agentRestart
+    ;;
+  status)
+    agentStatus
+    ;;
+  info)
+    info
+    ;;
+  *)
+    toConsoleInfo "usage: $0 {start|stop|restart|status}"
+    ;;
+  esac
+
+  exit "${EXIT_CODE_OK}"
+}
+
+main "$@"

+ 0 - 0
dist/aarch64/package_dir/conf/.gitkeep


BIN
dist/aarch64/package_dir/libs/amd64/jvm/cwlibnet.so


BIN
dist/aarch64/package_dir/libs/arm64/jvm/cwlibnet.so


+ 0 - 0
dist/aarch64/package_dir/logs/.gitkeep


+ 0 - 0
dist/aarch64/package_dir/runtime/.gitkeep


BIN
dist/aarch64/package_dir/scripts/cwjattach


+ 2954 - 0
dist/aarch64/scripts/install_temp.sh

@@ -0,0 +1,2954 @@
+#!/bin/bash
+#== AIX(Advanced Interactive eXecutive)是IBM基于AT&T Unix System V开发的一套类UNIX操作系统,运行在IBM专有的Power系列芯片设计的小型机硬件系统之上
+#== 以【#== 】开头的注释会在打包时删除
+#DEBUG== 以【#DEBUG== 】开头的注释会在调试打包时保留,正式打包时删除
+
+
+#==脚本执行中遇到不存在的变量就报错
+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="cloudwise"
+
+readonly AIX_DF_SPECIFIC_FLAG=
+readonly CONF_LD_PRELOAD=
+
+PARAM_DISABLE_SYSTEM_LOGS_ACCESS=
+
+#== 安装包版本项
+readonly AGENT_BUILD_DATE=25.09.2020
+readonly AGENT_INSTALLER_VERSION=1.2.0
+readonly AGENT_BUILD_DATE_INFO=""
+readonly AGENT_BUILD_TAG=""
+readonly AGENT_BUILD_UPLOADER=""
+#== 安装包版本项
+
+#== **********************************************************
+#==  配置重要文件名称
+#== **********************************************************
+#== CW-ServerAgent
+readonly AGENT_PROC="euspace"
+#== **********************************************************
+#==  配置目录
+#== **********************************************************
+readonly INSTALL_BASE=/opt
+#== /opt/cloudwise/oneagent/agents 目录
+readonly BASE_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents
+#== cloudwise/oneagent/agents/chaosd
+readonly INSTALL_FOLDER=${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents/${BRAND_PRODUCT_NAME_LOWER}
+#== cloudwise/oneagent/agents/chaosd/version
+readonly INSTALL_VERSION_FOLDER=${INSTALL_FOLDER}/${AGENT_INSTALLER_VERSION}
+#== /opt/cloudwise/oneagent/agents/chaosd/version
+readonly INSTALL_DIR=${INSTALL_BASE}/${INSTALL_VERSION_FOLDER}
+#== /opt/cloudwise/oneagent/agents/chaosd
+readonly AGENT_BASE_DIR=${INSTALL_BASE}/${INSTALL_FOLDER}
+
+#== /opt/cloudwise/cwserveragent/conf
+readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/scripts
+readonly AGENT_SCRIPTS_DIR="${INSTALL_DIR}/scripts"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/runtime
+readonly AGENT_RUNTIME_DIR="${INSTALL_DIR}/runtime"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/bin
+readonly AGENT_BIN_DIR="${INSTALL_DIR}/bin"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/lib
+#== readonly AGENT_LIB_DIR="${INSTALL_DIR}/lib"
+
+
+readonly AGENTS_BASE_DIR="${INSTALL_DIR}/agents"
+
+readonly META_BASE_DIR="${INSTALL_DIR}/meta"
+
+readonly LOG_DIR_NAME="logs"
+#== /opt/cloudwise/cwserveragent/logs
+readonly LOG_DIR=${INSTALL_DIR}/${LOG_DIR_NAME}
+
+#== /var/log/cloudwise/cwserveragent/
+readonly INSTALLER_LOG_DIR="/var/log/${INSTALL_FOLDER}"
+
+
+#== server-agent.ini
+#== hostId文件
+readonly INSTALLER_CONF_FILE_NAME="installation.conf"
+#== 部署在容器内的状态信息
+readonly INSTALLER_CONF_FILE="${AGENT_CONF_DIR}/${INSTALLER_CONF_FILE_NAME}"
+
+#== 【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/"
+
+#== 【0】=【退出码】执行成功
+readonly EXIT_CODE_OK=0
+readonly EXIT_CODE_GENERIC_ERROR=1
+readonly EXIT_CODE_NOT_ENOUGH_SPACE=6
+readonly EXIT_CODE_NOT_ENOUGH_MEMORY=7
+#== 【0】=无效参数
+readonly EXIT_CODE_INVALID_PARAM=8
+readonly EXIT_CODE_INSUFFICIENT_PERMISSIONS=9
+
+#== 【退出码】接收信号
+readonly EXIT_CODE_SIGNAL_RECEIVED=12
+readonly EXIT_CODE_ANOTHER_INSTALLER_RUNNING=13
+readonly EXIT_CODE_CORRUPTED_PACKAGE=16
+#== 【退出码】管理系统环境变量配置
+readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
+readonly EXIT_CODE_UNSUPPORTED_DOWNGRADE=18
+readonly EXIT_CODE_OS_NOT_SUPPORTED=19
+
+readonly EXTERNAL_TAR_SIZE=233820160
+readonly ARTIFACTS_SIZE=953271934
+#**********************************************************
+# Logs
+#**********************************************************
+toLogFile() {
+  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() {
+  toLogFile "[INFO]" "$@"
+}
+
+toLogWarn() {
+  toLogFile "[WARN]" "$@"
+}
+
+toLogError() {
+  toLogFile "[ERROR]" "$@"
+}
+
+toLogAdaptive() {
+  local success="${1}"
+  shift
+  if [ "${success}" -eq 0 ]; then
+    toLogInfo "$@"
+  else
+    toLogError "$@"
+  fi
+}
+
+toConsoleInfo() {
+  toConsoleOnly "$@"
+  toLogInfo "$@"
+}
+
+toConsoleWarn() {
+  toConsoleOnly "Warn:" "$@"
+  toLogWarn "$@"
+} >&2
+
+toConsoleError() {
+  toConsoleOnly "Error:" "$@"
+  toLogError "$@"
+} >&2
+
+#== 【0】【3】【4】=创建不存在的目录,并设置权限
+createDirIfNotExistAndSetRights() {
+  local dir="${1}"
+  local rights="${2}"
+
+  toConsoleInfo "#DEBUG== createDirIfNotExistAndSetRights --- ${rights} --- ${dir}"
+  if [ ! -d "${dir}" ]; then
+    toLogInfo "Creating directory ${dir} with rights ${rights}"
+    local message
+    if ! message="$(mkdir -p "${dir}" 2>&1)"; then
+      toConsoleWarn "Cannot create ${dir} directory."
+      toLogWarn "Error message: ${message}"
+      return 1
+    fi
+  fi
+
+  if ! message="$(chmod "${rights}" "${dir}" 2>&1)"; then
+    toConsoleWarn "Cannot change permisions of ${dir} directory to ${rights}."
+    toLogWarn "Error message: ${message}"
+    return 1
+  fi
+
+  return 0
+}
+
+createCurrentVersionSymlink() {
+	toLogInfo "Creating symlink to current version..."
+
+	local currentVersionLink="${AGENT_BASE_DIR}/current"
+	local tempLink="${currentVersionLink}.tmp"
+
+	if ! commandErrorWrapper ln -s "${AGENT_INSTALLER_VERSION}" "${tempLink}"; then
+		toLogError "Failed to create current version link"
+		return
+	fi
+
+	if ! commandErrorWrapper arch_moveReplaceTarget "${tempLink}" "${currentVersionLink}"; then
+		toLogError "Failed to set up current version link"
+		commandErrorWrapper rm -f "${tempLink}"
+		return
+	fi
+
+	toLogInfo "Current version link created: ${currentVersionLink} -> ${AGENT_INSTALLER_VERSION}"
+}
+
+#== 【0】=创建日志目录及日志文件installation_$$.log
+createLogDirsIfMissing() {
+  createDirIfNotExistAndSetRights "${INSTALL_BASE}" u+rwx,g+rx,o+rx
+  createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" u+rwx,g+rx,o+rx
+  #== agents根目录
+  createDirIfNotExistAndSetRights "${AGENT_BASE_DIR}" 1775
+  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
+#**********************************************************
+
+#== 【5】=获取系统发型版本
+getOsReleasePath() {
+	local osReleasePath="/etc/os-release"
+	if [ ! -f "${osReleasePath}" ]; then
+		osReleasePath="/usr/lib/os-release"
+	fi
+
+	printf '%s' "${osReleasePath}"
+}
+
+parseOsReleaseFile() {
+	local osReleasePath="$(getOsReleasePath)"
+
+	#shellcheck disable=SC1090
+	. "${osReleasePath}"
+	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)"
+	elif printf '%s' "${distrib}" | grep -iq "fedora" && [ "${VARIANT_ID-}" = "coreos" ]; then
+		distrib="${distrib} CoreOS"
+	fi
+
+	printf '%s %s' "${distrib}" "${version}"
+}
+
+#== 【5】=获取系统发型版本
+detectLinuxDistribution() {
+	if [ -f /etc/oracle-release ]; then
+		cat /etc/oracle-release
+	elif [ -f /etc/fedora-release ]; then
+		if [ -f "$(getOsReleasePath)" ]; then
+			(
+				parseOsReleaseFile
+			)
+		else
+			cat /etc/fedora-release
+		fi
+	elif [ -f /etc/redhat-release ]; then
+		cat /etc/redhat-release
+	elif [ -f "$(getOsReleasePath)" ]; then
+		(
+			parseOsReleaseFile
+		)
+	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
+}
+
+#== 【3】=检查系统init (INIT_SYSTEM、INIT_SYSTEM_VERSION)
+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}
+      toLogWarn "${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)"
+}
+
+#== 【3】=设置系统初始化脚本目录
+setLocationOfScripts() {
+  toLogInfo "Determining location of scripts..."
+
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSTEMD}"x ] || [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    #== /opt/cloudwise/cwserveragent/scripts
+    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 scripts ${INIT_DIR}"
+  return 0
+}
+
+#== 【0】=检查系统结构(X86_64\IA64\X86)
+detectArchitecture() {
+  local detected_arch=
+  if isAvailable arch; then
+    #== arch指令主要用于显示当前主机的硬件结构类型,查询结果与uname一致,我们可以看到它输出的结果有:i386、i486、mips、alpha等
+    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
+#**********************************************************
+
+#== 【1】【4】【5】【6】=获取 agent (64\32)位数lib目录(""或lib64)
+getBinariesFolderByBitness() {
+  local bitness="${1}"
+  if [ "${bitness}" -eq 32 ]; then
+    bitness=""
+  fi
+  printf 'lib%s' "${bitness}"
+}
+
+#== 【1】【2】【5】【6】=获取 agent tools/lib64/smartagentctl 路径
+#== getAgentCtlBinPath
+
+#== 【1】【4】【5】【6】=获取 agent 64位数lib路径(lib64/installaction)
+#== getAgentInstallActionPath
+
+#== 【5】【6】=获取OS bin配置路径 /opt/cloudwise/cwserveragent/lib64/cloudwiseosconfig
+getOsConfigBinPath() {
+  printf "%s" "${INSTALL_DIR}/lib64/${AGENT_OS_CONFIG_BIN}"
+}
+
+#== 【5】=设置agent进程可用
+setProcessAgentEnabled() {
+  local enabled="${1}"
+  toLogInfo "Setting process agent enabled: ${enabled}..."
+  local changeStatus=
+  #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --set-process-agent-enabled
+  changeStatus=$("$(getAgentInstallActionPath)" --set-process-agent-enabled "${enabled}" 2>&1)
+  toLogAdaptive $? "Process agent enable(${enabled}) status: ${changeStatus}"
+}
+
+#== 【1】【4】【5】【6】=获取命令执行错误信息,并写日志
+commandErrorWrapper() {
+  local command="${*}"
+  local errorFile="/tmp/smartagent_commanderror_$$"
+
+  ${command} 2>"${errorFile}"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 0 ]; then
+    toLogWarn "Command '${command}' failed, return code: ${returnCode}, message: $(cat "${errorFile}")"
+  fi
+
+  rm -f "${errorFile}"
+
+  return ${returnCode}
+}
+
+#== 【3】=是否独立的namespace
+isNamespaceIsolated() {
+  local pid="${1}"
+  local namespace="${2}"
+  local initNamespaceId
+  local processNamespaceId
+  initNamespaceId="$(readlink "/proc/1/ns/${namespace}" 2>/dev/null | tr -dc '0-9')"
+  processNamespaceId="$(readlink "/proc/${pid}/ns/${namespace}" 2>/dev/null | tr -dc '0-9')"
+
+  if [ ! "${initNamespaceId}" ] || [ ! "${processNamespaceId}" ]; then
+    toLogInfo "Link to /proc/*/ns/${namespace} does not exist"
+    printf 'error'
+    return
+  fi
+
+  if [ "${initNamespaceId}"x != "${processNamespaceId}"x ]; then
+    printf 'true'
+  else
+    printf 'false'
+  fi
+}
+
+#== 【0】=检查是否root
+checkRootAccess() {
+  toConsoleInfo "Checking root privileges..."
+
+  if [ "$(id -u)"x != "0"x ]; then
+    toConsoleError "NOT OK"
+    return 1
+  fi
+
+  toConsoleInfo "OK"
+  return 0
+}
+
+#== 【3】=删除存在的路径
+removeIfExists() {
+  local pathToRemove="${1}"
+  if [ ! -e "${pathToRemove}" ]; then
+    toLogInfo "${pathToRemove} does not exist, skipping removal"
+    return
+  fi
+
+  local output
+  if ! output="$(rm -rf "${pathToRemove}" 2>&1)"; then
+    toLogWarn "Failed to remove ${pathToRemove}: ${output}"
+  fi
+}
+
+#**********************************************************
+# SELinux related functions
+#**********************************************************
+
+#== 【5】【6】=执行 systemctl 命令
+executeSystemctlCommand() {
+  local command="${1}"
+  local unit="${2}"
+
+  if [ "$(id -u)" != 0 ]; then
+    #== 执行使用 os config bin
+    executeUsingOsConfigBin "${command}" "${unit}"
+    return $?
+  fi
+
+  local output=
+  #== shellcheck disable=SC2086
+  #== 执行 systemctl 命令
+  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}"
+
+#== 【6】=运行初始化命令(通过 service 方式 或 直接运行可执行命令)
+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
+  output="$("${command}" "${parameters}" 2>&1)"
+  exitCode=$?
+  toLogAdaptive ${exitCode} "Executed ${command} ${parameters}, exitCode = ${exitCode}, output: ${output}"
+  return ${exitCode}
+}
+
+#== 【0】=信号捕获,并执行回调函数
+signalHandler() {
+  local signal="${1}"
+  local callback="${2}"
+  toLogWarn "process received signal: ${signal}"
+  ${callback}
+  exit ${EXIT_CODE_SIGNAL_RECEIVED}
+}
+
+#== 【0】=配置信号捕获和回调
+configureSignalHandling() {
+  local callback="${1}"
+  for signal in HUP INT QUIT ABRT ALRM TERM; do
+    # shellcheck disable=SC2064
+    trap "signalHandler '${signal}' '${callback}'" ${signal}
+  done
+
+  trap "" PIPE
+}
+
+#== 【0】删除权限
+removeSecretsFromString() {
+  printf "%s" "$*" | sed 's#\(LICENSE=\)[[:alnum:]]\{16\}#\1***#'
+}
+
+#== 【3】【5】=检查目录写权限
+testWriteAccessToDir() {
+  local errorFile="/tmp/smartagent_commandError_$$"
+  local dir="${1}"
+  local tmpfilename
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; 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}")"
+    rm -f "${errorFile}"
+    return 1
+  fi
+
+  rm -f "${tmpfilename}" "${errorFile}"
+  return 0
+}
+
+#== 【0】=设置PATH
+setPATH() {
+  local prependToPATH="/usr/sbin:/usr/bin:/sbin:/bin"
+  if [ "${PATH}" ]; then
+    PATH=${prependToPATH}:${PATH}
+  else
+    PATH=${prependToPATH}
+  fi
+}
+
+#== 【5】【6】=是否非root权限
+isNonRootModeEnabled() {
+  #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-drop-root-privileges
+  local output
+  output="$(getValueFromConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "${LEGACY_AGENT_CONF_FILE}" "${PARAM_NON_ROOT_MODE}")"
+  printf '%s' "${output}" | grep -qE "(true|no_ambient)"
+}
+
+#== 【5】=自动启动工具
+runAutostartAddingTool() {
+  local prefix="${1}"
+  local file="${2}"
+  local suffix="${3}"
+  local output
+
+  local command="${prefix} ${file} ${suffix}"
+  toLogInfo "Executing ${command}"
+  output="$(${command} 2>&1)"
+  local status=$?
+  if [ "${output}" ]; then
+    toLogAdaptive ${status} "${output}"
+  fi
+
+  return ${status}
+}
+
+#== 【0】【5】=查找软链接真实地址(通过ls命令)
+readLinkFromLs() {
+  local path="${1}"
+  local result="${path}"
+  local lsOutput
+  local parsedLinkTarget
+  lsOutput="$(ls -dl "${path}" 2>/dev/null)"
+  if printf '%s' "${lsOutput}" | grep -q " -> "; then
+    parsedLinkTarget="$(printf '%s' "${lsOutput}" | sed 's|^.* -> ||')"
+    if [ "${parsedLinkTarget}" ]; then
+      result="${parsedLinkTarget}"
+    else
+      toLogWarn "Failed to parse ls output '${lsOutput}'"
+    fi
+  fi
+  printf '%s' "${result}"
+}
+
+#== 【0】【5】=查找软链接真实地址(通过readlink 或 ls 命令)
+readLink() {
+  local args=-e
+  local path="${1}"
+  if [ "${2}" ]; then
+    args="${1}"
+    path="${2}"
+  fi
+
+  (
+    if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+      path="${PATH}:/opt/freeware/bin"
+    fi
+
+    #== 通过 readlink 命令查找地址
+    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
+  )
+}
+
+#== 【0】【3】【4】【5】【6】=检查命令是否有效/是否存在
+isAvailable() {
+  command -v "${1}" >/dev/null 2>&1
+}
+
+#== 【0】【1】【3】【5】=读取配置文件配置参数信息
+getValueFromConfigFile() {
+  local key="${1}"
+  local configFile="${2}"
+  local defaultValue="${3}"
+  local value
+  value="$(sed -n "s|^${key}=||p" "${configFile}" 2>/dev/null)"
+
+  if [ "${value}" ]; then
+    printf '%s' "${value}"
+  else
+    printf '%s' "${defaultValue}"
+  fi
+}
+
+#== 【1】【5】=删除配置文件中配置
+removeValueFromConfigFile() {
+  local key="${1}"
+  local configFile="${2}"
+  local output
+  if ! output="$(cp -p "${configFile}" "${configFile}.tmp" 2>&1)"; then
+    toLogWarn "Unable to initialize ${configFile}.tmp file using source file, privileges and ownership will not be preserved: ${output}"
+  fi
+
+  if sed "/^${key}/d" "${configFile}" >"${configFile}.tmp"; then
+    mv -f "${configFile}.tmp" "${configFile}"
+  else
+    toLogWarn "Failed to remove ${key} from ${configFile}"
+    rm -f "${configFile}.tmp"
+  fi
+}
+
+#== 写配置到配置文件信息
+writeParamToConfigFile() {
+  local key="${1}"
+  local newValue="${2}"
+  local configFile="${3}"
+  local value
+  value="$(sed -n "s|^${key}=||p" "${configFile}" 2>/dev/null)"
+  toConsoleInfo "#DEBUG== writeParamToConfigFile --> edit ${key}=${value} to ${key}=${newValue}, configFile: ${configFile}"
+  if [ "${value}" ]; then
+    sed -i "s|^${key}=.*|${key}=${newValue}|" "${configFile}" 2>/dev/null
+  else
+    echo "${key}=${newValue}" >>"${configFile}" 2>/dev/null
+  fi
+}
+
+writeContentToConfigFile() {
+  local newValue="${1}"
+  local configFile="${2}"
+  toConsoleInfo "#DEBUG== writeContentToConfigFile --> edit ${newValue}, configFile: ${configFile}"
+
+  echo "${newValue}" > "${configFile}" 2>/dev/null
+}
+
+#== 修改scripts/smartagent脚本配置信息
+editScriptFileParam() {
+  local key="${1}"
+  local newValue="${2}"
+  local file="${3}"
+  local value
+  value="$(sed -n "s|^${key}=||p" "${file}" 2>/dev/null)"
+  toConsoleInfo "#DEBUG== editScriptFileParam --> edit ${key}=${value} to ${key}=${newValue}, configFile: ${file}"
+  if [ "${value}" ]; then
+    sed -i "s|^${key}=.*|${key}=${newValue}|" "${file}" 2>/dev/null
+  fi
+}
+
+#== 【0】=是否存在多个同时安装操作【通过判断 INSTALLER_LOCK_FILE 】
+isAnotherInstallationRunning() {
+  if [ ! -f "${INSTALLER_LOCK_FILE}" ]; then
+    return 1
+  fi
+  local pidFromLockFile
+  local nameFromLockFile
+  pidFromLockFile="$(head -n 1 "${INSTALLER_LOCK_FILE}")"
+  nameFromLockFile="$(tail -n 1 "${INSTALLER_LOCK_FILE}")"
+  if [ "$(wc -l <"${INSTALLER_LOCK_FILE}")" -ne 2 ] || [ -z "${pidFromLockFile}" ] || [ -z "${nameFromLockFile}" ]; then
+    toConsoleWarn "Installation lock file ${INSTALLER_LOCK_FILE} is damaged, skipping uniqueness check."
+    toConsoleWarn "Lock file contents: '$(cat ${INSTALLER_LOCK_FILE})'"
+    return 1
+  fi
+
+  #== shellcheck disable=SC2009
+  #== 获取正在执行安装的进程信息
+  local foundProcesses
+  foundProcesses="$(pgrep -f "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_DIR}"; then
+      errorMessage="${errorMessage} (AutoUpdate is in progress)"
+    fi
+
+    toConsoleError "${errorMessage}, PID ${pidFromLockFile}. Exiting."
+    return 0
+  fi
+
+  toConsoleInfo "Lock file exists but corresponding installation process does not run, contents of lock file: ${pidFromLockFile}, ${nameFromLockFile}."
+  return 1
+}
+
+#== 【0】=创建安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+createInstallationLockFile() {
+  printf '%s\n%s\n' "$$" "$0" >"${INSTALLER_LOCK_FILE}" 2>/dev/null
+}
+
+#== 【0】【6】删除安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+removeInstallationLockFile() {
+  toLogInfo "Removing installation lock file."
+  rm -f "${INSTALLER_LOCK_FILE}"
+}
+
+#== 【0】基础启动日志信息
+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)"
+}
+
+#== 解压文件编码
+readonly UNPACK_BINARY=base64
+#== 解压文件编码参数
+readonly UNPACK_BINARY_ARGS="-di"
+
+readonly ARCH_ARCH="X86"
+
+#== 【0】=检查系统指令集(X86_64\IA64\X86)
+arch_checkArchitectureCompatibility() {
+  #== 【0】=检查系统结构(X86_64)
+  local arch
+  arch="$(detectArchitecture)"
+  if [ "${arch}"x = "X86_64"x ] || [ "${arch}"x = "IA64"x ]; 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}"x = "X86_64"x ] || [ "${arch}"x = "AARCH64"x ]
+}
+
+#== 【5】=获取 lib 目录
+arch_getLibMacro() {
+  local libMacro=""
+  if [ "${SYSTEM_LIB32}" ]; then
+    #== shellcheck disable=SC2016
+    libMacro="/${LIB}"
+  fi
+  printf "%s" "${libMacro}"
+}
+#== 'timeout' requires gnu-coreutils8, i.e. it is not available on RHEL5, that's why we need this utility function
+#== 【3】【5】=执行命令超时配置
+
+#== 【0】【3】=获取文件权限信息
+arch_getAccessRights() {
+  stat --format='%A' "${1}"
+}
+
+#== 【4】=替换目录
+arch_moveReplaceTarget() {
+  local source="${1}"
+  local target="${2}"
+  mv -fT "${source}" "${target}"
+}
+
+
+#== xz 压缩包文件名 Cloudwise-SmartAgent
+readonly INTERNAL_TAR_FILE_NAME=${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}.tar.xz
+
+#== -安装日志: installation-{timestamp}.log,如,installation-20220601110912.log
+readonly LOG_FILE="${INSTALLER_LOG_DIR}/installation-$(date -u +"%Y%m%d%H%M%S").log"
+#readonly LOG_FILE="${INSTALLER_LOG_DIR}/installation_$$.log"
+
+
+
+#== 【临时目录】安装临时目录
+readonly TMP_DIR=${INSTALL_DIR}_install_$$
+#== 【临时目录】解压缓存目录
+readonly UNPACK_CACHE=${BASE_INSTALL_DIR}/unpack_cache
+#== 【临时目录】从sh文件读取压缩文件 tarfile_$$.base64
+readonly EXTERNAL_TAR_FILE=${BASE_INSTALL_DIR}/tarfile_$$.base64
+#== 【临时目录】xz 压缩包文件
+readonly INTERNAL_TAR_FILE=${INSTALL_DIR}/${INTERNAL_TAR_FILE_NAME}
+
+#== 【0】=
+readonly INSTALLER_FILE=${0}
+#== 旧配置文件
+readonly LEGACY_AGENT_CONF_FILE="${AGENT_CONF_DIR}/${BRAND_PRODUCT_NAME_LOWER}.conf"
+
+#== 【0】=
+readonly LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS=50
+
+#== 【0】=
+readonly HELP_URL=""
+
+readonly CONF_FIELD_NM_DATA_SERVER="DataServer"
+readonly CONF_FIELD_NM_CONFIG_SERVER="ConfigServer"
+readonly CONF_FIELD_NM_LICENSE="License"
+readonly CONF_FIELD_NM_JSON_CONF="JSON_CONF"
+readonly CONF_FIELD_NM_USER="User"
+readonly CONF_FIELD_NM_GROUP="Group"
+readonly CONF_FIELD_NM_DATA_STORAGE="DataStorage"
+readonly CONF_FIELD_NM_NON_ROOT_MODE="NonRootMode"
+
+
+#== 配置默认用户权限
+readonly BASE_OMNI_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}
+readonly BASE_OMNI_INSTALL_CONF_DIR=${BASE_OMNI_INSTALL_DIR}/conf/installation.conf
+BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${BASE_OMNI_INSTALL_CONF_DIR}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME_CLOUDWISE}")"
+
+#== Those are read from params section appended to installer by the server
+#== 【0】=【参数】数据服务地址
+PARAM_DATA_SERVER=
+#== 【0】=【参数】配置服务地址
+PARAM_CONFIG_SERVER=
+#== 【0】=【参数】license
+PARAM_LICENSE=
+
+PARAM_JSON_CONF=
+
+#== 【0】=【参数】安装路径
+PARAM_INSTALL_DIR=${INSTALL_DIR}
+#== 【0】=【参数】用户
+PARAM_USER=
+#== 【0】=【参数】用户组
+PARAM_GROUP=
+#== 【0】=【参数】非root模式
+PARAM_NON_ROOT_MODE=true
+
+PARAM_USER_LOGIN=false
+
+#== 【0】=【参数】不允许root回退
+PARAM_DISABLE_ROOT_FALLBACK=false
+#== 【0】=【参数】数据存储目录
+PARAM_DATA_STORAGE=
+#== 【0】=【参数】通过容器部署
+#== PARAM_INTERNAL_DEPLOYED_VIA_CONTAINER=false
+#== 【0】=【参数】跳过SELinux策略安装
+#== PARAM_INTERNAL_SKIP_SELINUX_POLICY_INSTALLER=false
+#== 【0】=【参数】是否使用解压缓存
+PARAM_INTERNAL_USE_UNPACK_CACHE=false
+#== 【0】=【参数】是否不使用 dump
+#== PARAM_INTERNAL_DISABLE_DUMPPROC=
+#== 【0】=【参数】是否跳过非root检查
+PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK=false
+#== 【0】【1】=【参数】额外的配置
+#== PARAM_INTERNAL_PASS_THROUGH_SETTERS=
+#== 【0】=检查是否降级安装
+SKIP_DOWNGRADE_CHECK=false
+
+SKIP_PRIVILEGES_CHECK=false
+
+#== 自定义字符串参数
+PARAM_TEST=
+#== 自定义字BOOL参数
+PARAM_BOOL=
+
+#== 【0】=常规日志
+initializeLog() {
+  toConsoleInfo "Installation started, version ${AGENT_INSTALLER_VERSION}, build date: ${AGENT_BUILD_DATE}, PID $$."
+  toLogInfo "Started from: ${INSTALLER_FILE}"
+
+  if [ -f /proc/version ]; then
+    toLogInfo "System version: $(cat /proc/version)"
+  else
+    toLogInfo "System version: $(uname -a)"
+  fi
+
+  toLogInfo "Path: ${PATH}"
+  toLogInfo "INSTALL_DIR: ${INSTALL_DIR}"
+  toLogInfo "Resolved installation path: $(readLink -e "${INSTALL_DIR}" 2>/dev/null)"
+  logBasicStartupInformation "${@}"
+}
+
+#**********************************************************
+# Signing related stuff
+#**********************************************************
+#== 【0】【4】=通过占位分割读取位置
+locateDelimiter() {
+  #== 占位符
+  local delimiter="${1}"
+  #== 从文件结尾读取行数
+  local linesToReadFromEnd="${2}"
+  local linesCount
+  local offset
+  if [ "${linesToReadFromEnd}" ]; then
+    #== 文件总行数n(实际行数=n+1)
+    linesCount="$(wc -l "${INSTALLER_FILE}" | awk '{print $1}')"
+    #== 从后往前读取【linesToReadFromEnd】行
+    offset="$(tail -n"${linesToReadFromEnd}" "${INSTALLER_FILE}" 2>/dev/null | awk '/^'"${delimiter}"'/ { print NR; exit }')"
+    if [ -n "${offset}" ]; then
+      printf "%d" "$((linesCount - linesToReadFromEnd + offset))"
+    fi
+  else
+    #== 读取占位符所在行(实际行数=n+1)
+    awk '/^'"${delimiter}"'/ { print NR; exit }' "${INSTALLER_FILE}"
+  fi
+}
+
+#== 【0】=从指定行范围读取配置参数
+readParam() {
+  local paramName="${1}"
+  local paramsSectionBeggining="${2}"
+  local paramsSectionEnd="${3}"
+
+  sed -n "${paramsSectionBeggining},${paramsSectionEnd} s/^${paramName}=//p" "${INSTALLER_FILE}"
+}
+
+#== 【0】=读取以【----PARAMETERS】开始到 【----PARAMETERS--】之间的参数
+readParamsSection() {
+  local sectionName="----PARAMETERS"
+  local begin
+  local end
+  begin=$(locateDelimiter "${sectionName}" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})
+  end=$(locateDelimiter "${sectionName}--" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})
+
+  if [ -z "${begin}" ] || [ -z "${end}" ]; then
+    return
+  fi
+  #== 从指定行范围读取配置参数
+  local value
+  if value="$(readParam PARAM_DATA_SERVER "${begin}" "${end}")"; then
+    PARAM_DATA_SERVER="${value}"
+  fi
+  if value="$(readParam PARAM_CONFIG_SERVER "${begin}" "${end}")"; then
+    PARAM_CONFIG_SERVER="${value}"
+  fi
+  if value="$(readParam PARAM_LICENSE "${begin}" "${end}")"; then
+    PARAM_LICENSE="${value}"
+  fi
+
+  if value="$(readParam PARAM_JSON_CONF "${begin}" "${end}")"; then
+    PARAM_JSON_CONF="${value}"
+  fi
+
+  if value="$(readParam PARAM_USER "${begin}" "${end}")"; then
+    PARAM_USER="${value}"
+  fi
+  if value="$(readParam PARAM_GROUP "${begin}" "${end}")"; then
+    PARAM_GROUP="${value}"
+  fi
+  if value="$(readParam PARAM_NON_ROOT_MODE "${begin}" "${end}")"; then
+    if value="$(getBoolParam "${value}")"; then
+      PARAM_NON_ROOT_MODE="${value}"
+    fi
+  fi
+
+  if value="$(readParam PARAM_USER_LOGIN "${begin}" "${end}")"; then
+    if value="$(getBoolParam "${value}")"; then
+      PARAM_USER_LOGIN="${value}"
+    fi
+  fi
+  toConsoleInfo "#DEBUG== install sh params, DATA_SERVER: ${PARAM_DATA_SERVER}, PARAM_CONFIG_SERVER: ${PARAM_CONFIG_SERVER}, PARAM_LICENSE:${PARAM_LICENSE}"
+  toConsoleInfo "#DEBUG== install sh params, PARAM_USER: ${PARAM_USER}, PARAM_GROUP: ${PARAM_GROUP}, PARAM_USER_LOGIN: ${PARAM_USER_LOGIN}, PARAM_NON_ROOT_MODE:${PARAM_NON_ROOT_MODE}"
+}
+
+#== 【0】【6】=清空安装临时文件
+#== ${INSTALL_DIR}_install_$$
+#== EXTERNAL_TAR_FILE=${INSTALL_DIR}/tarfile_$$.base64
+#== ${INSTALL_DIR}/Dynatrace-OneAgent.tar.xz
+#== ${INSTALL_DIR}/xzdec
+#== /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+cleanInstallationTemporaryFiles() {
+  toLogInfo "Cleaning installation temporary files"
+
+  rm -f "${EXTERNAL_TAR_FILE}" "${INTERNAL_TAR_FILE}" "${INSTALL_DIR}/xzdec"
+  rm -Rf "${TMP_DIR}"
+
+  local keepInstallationLockFile="${1}"
+  if [ -z "${keepInstallationLockFile}" ]; then
+    removeInstallationLockFile
+  fi
+}
+
+#== 完成安装后清理临时目录
+finishInstallation() {
+  if [ $# -eq 2 ]; then
+    cleanInstallationTemporaryFiles "${2}"
+  else
+    cleanInstallationTemporaryFiles ""
+  fi
+  toLogInfo "Installation finished, PID $$, exit code: ${1}."
+  changeWorkingDir "${CURR_PATH}"
+  if [ "${CONF_LD_PRELOAD}"x = "true"x ]; then
+    exec /bin/bash && exit 0
+  fi
+  exit "${1}"
+}
+
+#**********************************************************
+# Create folders, copy files, set rights
+#**********************************************************
+
+#== 【3】=创建临时目录
+prepareTempFolder() {
+  #== 删除存在的路径
+  removeIfExists "${TMP_DIR}"
+
+  toLogInfo "Creating temporary folder $TMP_DIR"
+  createDirIfNotExistAndSetRights "${TMP_DIR}" 755
+}
+
+#== 【4】=设置文件可执行权限
+setRightsForFiles() {
+  local file="${1}"
+  local perms="${2}"
+
+  if [ -e "${file}" ]; then
+    chmod "${perms}" "${file}"
+  fi
+}
+
+setRightsForDir() {
+  local dir="${1}"
+  local perms="${2}"
+
+  if [ -d "${dir}" ]; then
+    chmod -R "${perms}" "${dir}"
+  fi
+}
+
+#== 【4】=安装类型(f:文件,d:目录)递归设置权限
+chmod4FilesRecursively() {
+  local dir="${1}"
+  local type="${2}"
+  local mask="${3}"
+  find "${dir}" -type "${type}" -exec chmod "${mask}" {} \;
+}
+
+#== 【4】=移动目录到指定位置
+moveFolderToDestination() {
+  local source="${1}"
+  local destination="${2}"
+  local fullDestination
+  fullDestination="${destination}/$(basename "${source}")"
+  local output
+
+  toLogInfo "Moving ${source} to ${destination}"
+  if [ ! -e "${fullDestination}" ]; then
+    if output="$(mv -f "${source}" "${destination}" 2>&1)"; then
+      toLogInfo "Moving Successfully."
+      return
+    fi
+    toLogWarn "Failed to move ${source} to ${destination}: ${output}, attempting to copy"
+  else
+    toLogInfo "${fullDestination} already exists, attempting to copy"
+  fi
+
+  if ! output="$(cp -Rfp "${source}" "${destination}" 2>&1)"; then
+    toLogError "Failed to copy ${source} to ${destination}: ${output}"
+  fi
+}
+
+#== 【4】=将 bin 下版本内容移动到安装目录
+installVersionedContent() {
+  toLogInfo "Installing versioned content..."
+  createDirIfNotExistAndSetRights "${AGENT_BIN_DIR}" 755
+
+  local sourceDir="${TMP_DIR}/bin"
+  if [ ! -d "${AGENT_BIN_DIR}" ]; then
+    moveFolderToDestination "${sourceDir}" "${AGENT_BIN_DIR}"
+    return
+  fi
+
+  toLogInfo "Directory ${AGENT_BIN_DIR} already exist, repairing the directory"
+  rm -rf "${AGENT_BIN_DIR}"
+  moveFolderToDestination "${sourceDir}" "${AGENT_BIN_DIR}"
+}
+
+#== 【4】=创建当前版本软连接
+
+#== 【4】=删除存在的目录
+listAndRemoveDirectoryIfExists() {
+  local directory="${1}"
+  if [ -d "${directory}" ]; then
+    toLogInfo "${directory} exists, removing it."
+    toLogInfo "Contents: $(ls -lR "${directory}")"
+    rm -rf "${directory}"
+  fi
+}
+
+#== 【4】=临时目录中conf 移动到 agent 安装目录中
+setupConfFolder() {
+  toLogInfo "Setup conf folder..."
+  #== 移动目录到指定位置
+  moveFolderToDestination "${TMP_DIR}/conf" "${INSTALL_DIR}"
+
+  chmod 755 "${AGENT_CONF_DIR}"
+
+  toLogInfo "Setup conf done."
+}
+
+#== 【4】=给距离当前目录至少 ${mindepth} 个子目录的所有文件设置权限
+chmodFilesWithMindepth() {
+  local dir="${1}"
+  local mindepth="${2}"
+  local mask="${3}"
+
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    #== 安装类型(f:文件,d:目录)递归设置权限
+    chmod4FilesRecursively "${1}" f "${3}"
+  else
+    #== 查找深度距离当前目录至少 ${mindepth} 个子目录的所有文件
+    find "${dir}" -mindepth "${mindepth}" -print0 | xargs -r -0 chmod "${mask}"
+  fi
+}
+
+#== 【4】=配置其他文件(cwserveragent.service、installer.version)
+setupMiscFiles() {
+  toLogInfo "Setup misc files..."
+  #== 创建 cwserveragent.service
+  createSystemdUnitFile
+  #== echo "${AGENT_INSTALLER_VERSION}" >"${INSTALL_DIR}/installer.version"
+  mv -f "${TMP_DIR}/installer.version" "${INSTALL_DIR}/"
+  toLogInfo "Setup misc done."
+}
+
+#== 【4】=创建 cwserveragent.service
+createSystemdUnitFile() {
+  toLogInfo "creating init scripts ${AGENT_SCRIPTS_DIR}"
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+    return
+  fi
+  createDirIfNotExistAndSetRights "${AGENT_SCRIPTS_DIR}" 755
+  cat <<EOF >${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}
+[Unit]
+Description=${BRAND_AGENT_PRODUCT_NAME}
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+User=root
+ExecStart=${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} start
+ExecStop=${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} stop
+Type=forking
+#Restart=always
+KillMode=process
+TimeoutSec=240
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+  setRightsForFiles "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" 755
+  if [ "${INIT_DIR}"x != "${AGENT_SCRIPTS_DIR}"x ]; then
+    cp -f "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" ${INIT_DIR}
+    toLogInfo "Copy scripts ${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT} to ${INIT_DIR} done."
+  fi
+  toLogInfo "creating init scripts ${AGENT_SCRIPTS_DIR} done."
+}
+
+setupAll() {
+#  moveFolderToDestination "${TMP_DIR}/package_dir/*" "${INSTALL_DIR}"
+#ls  ${TMP_DIR}/package_dir/*
+
+  #== 移动所有文件到目录
+  cp -Rfp ${TMP_DIR}/package_dir/* "${INSTALL_DIR}"
+  local installVersionFile="${INSTALL_DIR}/installer.version"
+  echo ${AGENT_INSTALLER_VERSION} > ${installVersionFile}
+#  mv ${INSTALL_DIR}/package_dir/* ${INSTALL_DIR}
+#     echo "${TMP_DIR}/*" "${INSTALL_DIR}/"
+}
+
+#== 【4】=配置 lib、conf、bin、cwserveragent.service、installer.version、plugins
+setupOptDir() {
+  createDirIfNotExistAndSetRights "${INSTALL_DIR}" 1775
+  #== 临时目录中conf 移动到 agent 安装目录中
+  setupConfFolder
+  #== 将 bin 下版本内容移动到安装目录
+  installVersionedContent
+  #== 配置其他文件(cwserveragent.service、installer.version)
+  setupMiscFiles
+}
+
+#== 【4】=复制临时目录 scripts/cwserveragent 到指定目录下
+copyScriptsToDirectory() {
+  local scriptLocation="${1}"
+  #== scripts/cwserveragent
+  local scriptFile="${TMP_DIR}/scripts/${SERVICE_SCRIPT_FILE}"
+
+  toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} begin."
+
+  local output
+  if ! output="$(cp "${scriptFile}" "${scriptLocation}/" 2>&1)"; then
+    toLogError "Failed to copy ${scriptFile} to ${scriptLocation}, output: ${output}"
+    return
+  fi
+
+  setRightsForFiles "${scriptLocation}/${SERVICE_SCRIPT_FILE}" 755
+  toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} done."
+
+  #== scripts/uninstall.sh
+#  local scriptLocation="${1}"
+#    #== scripts/cwserveragent
+#    local scriptFile="${TMP_DIR}/scripts/uninstall.sh"
+#
+#    toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} begin."
+#
+#    local output
+#    if ! output="$(cp "${scriptFile}" "${scriptLocation}/" 2>&1)"; then
+#      toLogError "Failed to copy ${scriptFile} to ${scriptLocation}, output: ${output}"
+#      return
+#    fi
+#    setRightsForFiles "${scriptLocation}/uninstall.sh" 755
+#    toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} done."
+}
+
+#== 【4】=复制临时目录 scripts/cwserveragent 到指定目录下
+copyScripts() {
+  toLogInfo "Copy scripts..."
+  #== 创建目录 /opt/cloudwise/cwserveragent/scripts
+  createDirIfNotExistAndSetRights "${AGENT_SCRIPTS_DIR}" 755
+  #== 创建目录 /opt/cloudwise/{product}/agents
+  createDirIfNotExistAndSetRights "${AGENTS_BASE_DIR}" 775
+  #== 创建目录 /opt/cloudwise/{product}/meta
+  createDirIfNotExistAndSetRights "${META_BASE_DIR}" 775
+  #== 创建目录 /opt/cloudwise/{product}/runtime
+  createDirIfNotExistAndSetRights "${AGENT_RUNTIME_DIR}" 775
+
+  #== scripts/uninstall.sh
+  local uninstallScript="${TMP_DIR}/scripts/uninstall.sh"
+  toLogInfo "Copy scripts ${uninstallScript} to ${INSTALL_DIR} begin."
+  local output
+  if ! output="$(cp "${uninstallScript}" "${INSTALL_DIR}/uninstall.sh" 2>&1)"; then
+    toLogError "Failed to copy ${uninstallScript} to ${INSTALL_DIR}/uninstall.sh, output: ${output}"
+  else
+    setRightsForFiles "${INSTALL_DIR}/uninstall.sh" 755
+  fi
+  toLogInfo "Copy scripts ${uninstallScript} to ${INSTALL_DIR} done."
+
+  #== 复制临时目录 scripts/ 到安装目录 /opt/cloudwise/cwserveragent/scripts
+  copyScriptsToDirectory "${AGENT_SCRIPTS_DIR}"
+  if [ "${INIT_DIR}"x != "${AGENT_SCRIPTS_DIR}"x ]; then
+    copyScriptsToDirectory "${INIT_DIR}"
+  fi
+  toLogInfo "Copy scripts done."
+}
+
+#== 【4】=调用 agent 64位数lib路径(lib64/installaction)执行指令 --create-cluster-timestamp-file
+createFirstClusterTimestampFile() {
+  toLogInfo "Creating firstClusterTimestamp file"
+  #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --create-cluster-timestamp-file
+  "$(getAgentInstallActionPath)" "--create-cluster-timestamp-file" >>"${LOG_FILE}" 2>&1
+}
+
+#== 【4】=配置数据存储目录
+setupDataStorageDir() {
+  toLogInfo "Setup datastorage dir..."
+  local dataStorage
+  dataStorage="$(getValueFromConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${LEGACY_AGENT_CONF_FILE}" "${DATA_STORAGE_DIR}")"
+  if [ "${dataStorage}"x = "${LOG_DIR}"x ]; then
+    toLogInfo "Detected legacy data storage setting, changing it to the new default location"
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${DATA_STORAGE_DIR}" "${LEGACY_AGENT_CONF_FILE}"
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${DATA_STORAGE_DIR}" "${INSTALLER_CONF_FILE}"
+  fi
+
+  if [ "${PARAM_DATA_STORAGE}" ]; then
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${PARAM_DATA_STORAGE}" "${LEGACY_AGENT_CONF_FILE}"
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${PARAM_DATA_STORAGE}" "${INSTALLER_CONF_FILE}"
+  fi
+
+  toLogInfo "Setup datastorage dir done."
+}
+
+#**********************************************************
+# Processing command line parameters
+#**********************************************************
+#== 【0】=help
+displayHelp() {
+  printf '%s\n' "Usage: $(basename "${INSTALLER_FILE}") [-h] [-v] "
+  #== printf '%s\n' "Usage: $(basename "${INSTALLER_FILE}") [-h] [-v] [DATA_SERVER=https://server_address:server_port] [CONFIG_SERVER=configService] [LICENSE=license] [INSTALL_DIR=install_path]"
+  local beginStr="Usage: "
+  local pad="${#beginStr}"
+
+  printf "\n\n"
+
+  pad=25
+  printf "%-${pad}s%s\n" "-h, --help" "Display this help and exit."
+  printf "%-${pad}s%s\n" "-v, --version" "Print version and exit."
+
+}
+
+printParamMessage() {
+  local paramNm="${1}"
+  local paramValue="${2}"
+  toConsoleInfo "---> Parameter ${paramNm}=${paramValue}."
+}
+
+printOtherParamMessage() {
+  local param="${1}"
+  toConsoleInfo "---> Parameter ${param}"
+}
+
+#== 【0】=大小写转化,并返回判断结果
+istrcmp() {
+  local s1
+  local s2
+  s1="$(printf '%s' "${1}" | tr '[:upper:]' '[:lower:]')"
+  s2="$(printf '%s' "${2}" | tr '[:upper:]' '[:lower:]')"
+  [ "${s1}"x = "${s2}"x ]
+}
+
+#== 【0】=
+isParamTrue() {
+  [ "${1}"x = "1"x ] || [ "${1}"x = "true"x ] || [ "${1}"x = "enable"x ] || [ "${1}"x = "yes"x ]
+}
+#== 【1】【5】=
+isParamFalse() {
+  [ "${1}"x = "0"x ] || [ "${1}"x = "false"x ] || [ "${1}"x = "disable"x ] || [ "${1}"x = "no"x ]
+}
+
+#== 【1】【5】=
+invertBoolValue() {
+  local valueToInvert="${1}"
+  if isParamFalse "${valueToInvert}"; then
+    printf '%s' "true"
+  else
+    printf '%s' "false"
+  fi
+}
+
+#== shellcheck disable=SC2003
+#== 【0】=获取参数值
+getParamValue() {
+  local paramName="${1}"
+  local input="${2}"
+  local paramNameLength="${#paramName}"
+  paramNameLength=$((paramNameLength + 1))
+  local partParam
+  partParam="$(expr substr "${input}" 1 ${paramNameLength})"
+#  partParam=$(substr "${input}" 1 ${paramNameLength})
+  if ! istrcmp "${partParam}" "${paramName}="; then
+    return 1
+  fi
+
+  local valueSeparator=$((paramNameLength + 1))
+  local value
+  value="$(expr substr "${input}" ${valueSeparator} 1000)"
+#  value=$(substr "${input}" ${valueSeparator} 1000)
+  if [ -z "${value}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${value}"
+  return 0
+}
+
+#== 【0】=获取bool参数
+readBoolParam() {
+  local value
+  value="$(getParamValue "${1}" "${2}")"
+
+  if value="$(getBoolParam "${value}")"; then
+    printf "%s" "${value}"
+    return 0
+  fi
+
+  return 1
+}
+
+#== 【0】=获取bool参数
+getBoolParam() {
+  local value="${1}"
+  if [ "${value}" ]; then
+    if isParamFalse "${value}"; then
+      printf "false"
+      return 0
+    fi
+    if isParamTrue "${value}"; then
+      printf "true"
+      return 0
+    fi
+  fi
+
+  return 1
+}
+
+#== 【0】=校验格式是否规范[1、大于4个字符且不能"cw."开头,2、不能超过100字符,3、只能包含字母数字字符,连字符,下划线和点。]
+validateParameter() {
+  local name="${1}"
+  local value="${2}"
+  if [ "$(printf '%s' "${value}" | cut -c -3)"x = "cw."x ]; then
+    toConsoleError "${name} must not begin with 'cw.'"
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "${#value}" -gt 100 ]; then
+    toConsoleError "Maximum allowed length of ${name} is 100."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if printf '%s' "${value}" | grep -q "[^[:alnum:]._-]"; then
+    toConsoleError "${name} can only contain alphanumeric characters, hyphen, underscore and dot."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】=验证用户和用户组是否匹配
+validateUserAndGroupParameters() {
+  local user="${1}"
+  local group="${2}"
+  local permittedNameRegex='^[[:alnum:]._][[:alnum:]._-]{2,31}$'
+
+  if [ ! "${group}" ]; then
+    group="${user}"
+  fi
+
+  if ! printf '%s' "${user}" | grep -qE "${permittedNameRegex}"; then
+    toConsoleError "USER can only contain alphanumeric characters, hyphen, underscore and dot, and must have length from 3 to 32 characters."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if ! printf '%s' "${group}" | grep -qE "${permittedNameRegex}"; then
+    toConsoleError "GROUP can only contain alphanumeric characters, hyphen, underscore and dot, and must have length from 3 to 32 characters."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  #== 校验用户/用户组信息
+  validateUserPrimaryGroup "${user}" "${group}"
+}
+
+#== 【0】【3】【5】=获取系统权限信息
+getSystemEntityInfo() {
+  local database="${1}"
+  local valueToCheck="${2}"
+
+  #== 校验命令getent是否存在
+  if ! isAvailable "getent"; then
+    toLogInfo "Command getent is not available"
+    return 2
+  fi
+
+  #== 查看系统权限
+  local output
+  output="$(getent "${database}" "${valueToCheck}" 2>&1)"
+  local returnCode=$?
+
+  if [ "${returnCode}" != 0 ]; then
+    if [ "${returnCode}" != 2 ]; then
+      toLogWarn "Failed to check ${valueToCheck} in ${database} database, message: ${output}, code: ${returnCode}"
+    fi
+    return 1
+  elif [ ! "${output}" ]; then
+    toLogWarn "Failed to get user information: getent returned no output"
+  fi
+
+  printf '%s' "${output}"
+  return 0
+}
+
+#== 【0】【3】=查看用户/用户组信息
+isEntityPassedById() {
+  local database="${1}"
+  local name="${2}"
+
+  local output
+  output="$(getSystemEntityInfo "${database}" "${name}")"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 0 ]; then
+    if [ ${returnCode} -eq 2 ]; then
+      toLogInfo "Installer will not be able to verify whether entity was passed by name or by ID"
+    fi
+    return 1
+  fi
+
+  local nameFromDatabase
+  nameFromDatabase="$(printf '%s' "${output}" | cut -d: -f1)"
+
+  if [ "${nameFromDatabase}"x = "${name}"x ]; then
+    return 1
+  fi
+
+  toLogWarn "Name from config and from ${database} system database do not match"
+  toLogWarn "Config: ${name}, database: ${nameFromDatabase}"
+  return 0
+}
+
+#== 【0】【3】【5】=用户是否存在
+userExistsInSystem() {
+  local user="${1}"
+
+  getSystemEntityInfo "passwd" "${user}" >/dev/null
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    return ${returnCode}
+  fi
+
+  toLogInfo "Trying to determine user existence using 'id' command"
+  id "${user}" >/dev/null 2>&1
+}
+
+#== 【5】= 查看group
+groupExistsInSystem() {
+  local group="${1}"
+
+  getSystemEntityInfo "group" "${group}" >/dev/null
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    return ${returnCode}
+  fi
+
+  toLogInfo "Installer will not be able to determine group existence"
+  return 1
+}
+
+#== 【3】=用户是否存在
+validateUserExistence() {
+  local user="${1}"
+  if ! userExistsInSystem "${user}"; then
+    toConsoleError "User named '${user}' configured for ${BRAND_PRODUCT_NAME} does not exist. Installation aborted."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】【3】=检查用户/用户组信息
+checkIfEntityWasNotPassedById() {
+  local database="${1}"
+  local valueToCheck="${2}"
+  local valueTypeToLog="user"
+
+  if [ "${database}"x = "group"x ]; then
+    valueTypeToLog="group"
+  fi
+
+  if isEntityPassedById "${database}" "${valueToCheck}"; then
+    toConsoleError "\"${valueToCheck}\" is not a ${valueTypeToLog} name but its ID. Installation aborted."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】【3】=用户权限下用户组ID
+getUserPrimaryGroupIdForComparison() {
+  local user="${1}"
+
+  local userPrimaryGroupId
+  userPrimaryGroupId="$(getSystemEntityInfo "passwd" "${user}")"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    printf '%s' "${userPrimaryGroupId}" | cut -d: -f4
+    return ${returnCode}
+  fi
+
+  toLogInfo "Returning user primary group name instead of its id"
+  id -gn "${user}"
+}
+
+#== 【0】【3】=获取用户组信息
+getGroupIdForComparison() {
+  local group="${1}"
+
+  local groupId
+  groupId="$(getSystemEntityInfo "group" "${group}")"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    printf '%s' "${groupId}" | cut -d: -f3
+    return ${returnCode}
+  fi
+
+  toLogInfo "Returning group name instead of its id"
+  printf '%s' "${group}"
+}
+
+#== 【0】【3】=校验用户/用户组信息
+validateUserPrimaryGroup() {
+  local user="${1}"
+  local group="${2}"
+
+  if ! userExistsInSystem "${user}"; then
+    return
+  fi
+
+  checkIfEntityWasNotPassedById "passwd" "${user}"
+  checkIfEntityWasNotPassedById "group" "${group}"
+
+  #== 获取用户组ID
+  local groupId
+  groupId="$(getGroupIdForComparison "${group}")"
+  #== 获取用户下用户组ID
+  local userPrimaryGroupId
+  userPrimaryGroupId="$(getUserPrimaryGroupIdForComparison "${user}")"
+
+  toConsoleInfo "#DEBUG== group \"${group}\" id: \"${groupId}\", user \"${user}\" primaryGroupId: \"${userPrimaryGroupId}\""
+  if [ "${userPrimaryGroupId}"x != "${groupId}"x ]; then
+    toConsoleError "User named \"${user}\" does not have group named \"${group}\" as its primary group. Installation aborted."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【3】=检查用户/用户组是否存在和匹配
+checkUserAndGroupFromConfig() {
+  local configUser
+  local configGroup
+  configUser="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  configGroup="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+
+  toLogInfo "Checking validity of user account '${configUser}:${configGroup}'"
+
+  if [ "${PARAM_UPGRADE}"x = "yes"x ]; then
+    validateUserExistence "${configUser}"
+  fi
+
+  #== 校验用户/用户组信息
+  validateUserPrimaryGroup "${configUser}" "${configGroup}"
+}
+
+#== 【0】=解析命令行中参数
+parseCommandLineParameters() {
+  local dataServerIsEmpty=true
+  local configServerIsEmpty=true
+  while [ $# -gt 0 ]; do
+    local param="${1}"
+    local value=
+
+    if value=$(getParamValue DATA_SERVER "${param}"); then
+      PARAM_DATA_SERVER="${value}"
+      dataServerIsEmpty=false
+      printParamMessage "DATA_SERVER" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue CONFIG_SERVER "${param}"); then
+      PARAM_CONFIG_SERVER="${value}"
+      configServerIsEmpty=false
+      printParamMessage "CONFIG_SERVER" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue LICENSE "${param}"); then
+      PARAM_LICENSE="${value}"
+      printParamMessage "LICENSE" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue JSON_CONF "${param}"); then
+      PARAM_JSON_CONF="${value}"
+      printParamMessage "JSON_CONF" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue INSTALL_DIR "${param}"); then
+      PARAM_INSTALL_DIR="${value}"
+      printParamMessage "INSTALL_DIR" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue DATA_STORAGE "${param}"); then
+      PARAM_DATA_STORAGE="${value}"
+      printParamMessage "DATA_STORAGE" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(readBoolParam DISABLE_SYSTEM_LOGS_ACCESS "${param}"); then
+      PARAM_DISABLE_SYSTEM_LOGS_ACCESS="${value}"
+      printParamMessage "DISABLE_SYSTEM_LOGS_ACCESS" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue INTERNAL_OVERRIDE_CHECKS "${param}"); then
+      if printf '%s' "${value}" | grep -wq "privileges"; then
+        PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK=true
+      fi
+
+      if printf '%s' "${value}" | grep -wq "downgrade"; then
+        SKIP_DOWNGRADE_CHECK=true
+      fi
+      printParamMessage "INTERNAL_OVERRIDE_CHECKS" "${value}"
+
+      shift
+      continue
+    fi
+
+    if value=$(readBoolParam INTERNAL_USE_UNPACK_CACHE "${param}"); then
+      PARAM_INTERNAL_USE_UNPACK_CACHE="${value}"
+      printParamMessage "INTERNAL_USE_UNPACK_CACHE" "${value}"
+      shift
+      continue
+    fi
+
+    if [ "${ARCH_ARCH}"x != "AIX"x ]; then
+      if value=$(getParamValue USER "${param}"); then
+        PARAM_USER="${value}"
+        printParamMessage "USER" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(getParamValue GROUP "${param}"); then
+        PARAM_GROUP="${value}"
+        printParamMessage "GROUP" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam NON_ROOT_MODE "${param}"); then
+        PARAM_NON_ROOT_MODE="${value}"
+        printParamMessage "NON_ROOT_MODE" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam USER_LOGIN "${param}"); then
+        PARAM_USER_LOGIN="${value}"
+        printParamMessage "USER_LOGIN" "${value}"
+        shift
+        continue
+      fi
+
+      #== 自定义参数获取
+      if value=$(getParamValue TEST "${param}"); then
+        PARAM_TEST="${value}"
+        printParamMessage "TEST" "${value}"
+        shift
+        continue
+      fi
+
+      #== 自定义bool参数
+      if value=$(readBoolParam BOOL "${param}"); then
+        PARAM_BOOL="${value}"
+        printParamMessage "BOOL" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam DISABLE_ROOT_FALLBACK "${param}"); then
+        PARAM_DISABLE_ROOT_FALLBACK="${value}"
+        printParamMessage "DISABLE_ROOT_FALLBACK" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK "${param}"); then
+        PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK="${value}"
+        printParamMessage "NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam INTERNAL_SKIP_SELINUX_POLICY_INSTALLER "${param}"); then
+        #== PARAM_INTERNAL_SKIP_SELINUX_POLICY_INSTALLER="${value}"
+        printParamMessage "INTERNAL_SKIP_SELINUX_POLICY_INSTALLER" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam DOCKER_ENABLED "${param}"); then
+        #== PARAM_INTERNAL_DEPLOYED_VIA_CONTAINER="${value}"
+        printParamMessage "DOCKER_ENABLED" "${value}"
+        shift
+        continue
+      fi
+    fi
+
+    if [ "${ARCH_ARCH}"x != "AIX"x ] && [ "${ARCH_ARCH}"x != "S390"x ]; then
+      if value=$(readBoolParam INTERNAL_DISABLE_DUMPPROC "${param}"); then
+        #== PARAM_INTERNAL_DISABLE_DUMPPROC="${value}"
+        printParamMessage "INTERNAL_DISABLE_DUMPPROC" "${value}"
+        shift
+        continue
+      fi
+    fi
+
+    if [ "${param}"x = "-h"x ] || [ "${param}"x = "--help"x ]; then
+      displayHelp
+      finishInstallation "${EXIT_CODE_OK}"
+    fi
+
+    if [ "${param}"x = "-v"x ] || [ "${param}"x = "--version"x ]; then
+      printf "%s\n" "${AGENT_INSTALLER_VERSION}"
+      finishInstallation "${EXIT_CODE_OK}"
+    fi
+    
+    printOtherParamMessage ${param}
+    shift
+  done
+
+  if [ "${configServerIsEmpty}"x = "true"x ] && [ "${dataServerIsEmpty}"x != "true"x ]; then
+    PARAM_CONFIG_SERVER="${PARAM_DATA_SERVER}"
+  fi
+}
+
+#== 【0】=校验PARAM_INSTALL_DIR是否规范【1、不能包含空格,2、不能在根目录,3、安装路径必须是绝对的】
+validateInstallPathParameter() {
+  if printf '%s' "${PARAM_INSTALL_DIR}" | grep -q "[[:space:]]"; then
+    toConsoleError "Installation path must not contain spaces."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "${PARAM_INSTALL_DIR}"x = "/"x ]; then
+    toConsoleError "Installation path must not point to the filesystem root directory."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "$(printf '%s' "${PARAM_INSTALL_DIR}" | cut -c 1)"x != "/"x ]; then
+    toConsoleError "Installation path must be absolute."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】=校验PARAM_DATA_STORAGE是否规范【1、不能包含空格,2、不能在根目录,3、安装路径必须是绝对的,4、数据目录不能放在安装目录下】
+validateDataStorageParameter() {
+  if printf '%s' "${PARAM_DATA_STORAGE}" | grep -q "[[:space:]]"; then
+    toConsoleError "Data storage path must not contain spaces."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "${PARAM_DATA_STORAGE}"x = "/"x ]; then
+    toConsoleError "Data storage path must not point to the filesystem root directory."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "$(printf '%s' "${PARAM_DATA_STORAGE}" | cut -c 1)"x != "/"x ]; then
+    toConsoleError "Data storage path must be absolute."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if printf '%s' "${PARAM_DATA_STORAGE}" | grep -q "^${INSTALL_DIR}"; then
+    toConsoleError "Data storage path must not be located within ${INSTALL_DIR}."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+
+#**********************************************************
+# Config files
+#**********************************************************
+
+#== 【3】【5】=格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
+formatSize() {
+  local sizeInKiB="${1}"
+  local formattedSize
+
+  for symbol in "KiB" "MiB" "GiB" "TiB"; do
+    if printf '%s' "${sizeInKiB}" | awk '$1 >= 1024 { exit 1; }'; then
+      formattedSize="${sizeInKiB} ${symbol}"
+      break
+    fi
+    sizeInKiB="$(printf '%s' "${sizeInKiB}" | awk '{ print $1 / 1024 }')"
+  done
+
+  printf '%s' "${formattedSize}"
+}
+
+#== 【3】【5】=
+cropSizeValue() {
+  local size="${1}"
+  local value
+  local unit
+  value="$(printf '%s' "${size}" | cut -d' ' -f1)"
+  unit="$(printf '%s' "${size}" | cut -d' ' -f2)"
+  printf '%.2f %s' "${value}" "${unit}"
+}
+
+#== 【3】【5】=检查目录可用空间(单位:k)
+checkFreeSpace() {
+  local path="${1}"
+  local requiredSpaceInKiB="${2}"
+  local dfOutput
+  local baseFilesystem
+  local freeSpace
+  local formattedRequiredSpace
+  local formattedFreeSpace
+
+  #== shellcheck disable=SC2086
+  dfOutput="$(df -P ${AIX_DF_SPECIFIC_FLAG} "${path}" | tail -n +2)"
+  #== 文件系统目录
+  baseFilesystem="$(printf "%s" "${dfOutput}" | awk '{ print $NF }')"
+  #== 剩余空间(单位:k)
+  freeSpace="$(printf "%s" "${dfOutput}" | awk '{ print $4 }')"
+
+  #== 格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
+  formattedRequiredSpace="$(formatSize "${requiredSpaceInKiB}")"
+  toLogInfo "Filesystem with ${path} is mounted under ${baseFilesystem}. Space required: ${formattedRequiredSpace}."
+
+  if [ ! "${freeSpace}" ]; then
+    printf 'Cannot determine amount of free space on %s (filesystem mounted under %s)' "${path}" "${baseFilesystem}"
+    return 1
+  fi
+
+  #== 格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
+  formattedFreeSpace="$(formatSize "${freeSpace}")"
+  toLogInfo "Available free space: ${formattedFreeSpace}"
+
+  if [ "${freeSpace}" -lt "${requiredSpaceInKiB}" ]; then
+    printf 'Not enough free space on %s (filesystem mounted under %s). ' "${path}" "${baseFilesystem}"
+    printf 'Required: %s, available: %s' "$(cropSizeValue "${formattedRequiredSpace}")" "$(cropSizeValue "${formattedFreeSpace}")"
+    return 2
+  fi
+
+  printf 'Free space is sufficient'
+  return 0
+}
+
+#== 【3】=检查文件系统类型
+
+#== 【3】=检查安装目录空间
+checkInstallPathFreeSpace() {
+  local externalTarSize=${EXTERNAL_TAR_SIZE}
+  local artifactsSize=${ARTIFACTS_SIZE}
+  #== use 10% additional margin
+  local requiredSpace=$((externalTarSize + artifactsSize * 11 / 10))
+  #== convert to kibibytes
+  requiredSpace=$((requiredSpace / 1024))
+
+  toConsoleInfo "Checking free space in ${INSTALL_DIR}"
+
+  local message
+  #== 检查目录可用空间(单位:k)
+  message="$(checkFreeSpace "${INSTALL_DIR}" "${requiredSpace}")"
+  case $? in
+  0) toLogInfo "${message}" ;;
+  1) toConsoleWarn "${message}. Installation may be incomplete." ;;
+  2)
+    toConsoleError "${message}"
+    finishInstallation "${EXIT_CODE_NOT_ENOUGH_SPACE}"
+    ;;
+  esac
+}
+
+#== 【3】=获取指定路径的文件系统信息
+getFilesystemInfo() {
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    mount | grep " ${1} "
+  else
+    grep " ${1} " /proc/self/mounts
+  fi
+}
+
+#== 【3】=检查目录指定权限信息
+checkAccessRightsTo() {
+  local dir="${1}"
+  toLogInfo "Checking access to ${dir}..."
+  #== 获取文件权限信息
+  local accessRights
+  accessRights="$(arch_getAccessRights "${dir}" | cut -c 2-4)"
+  if ! printf '%s' "${accessRights}" | grep -q rwx; then
+    toConsoleError "Insufficient permissions on ${dir}: '${accessRights}'."
+    toLogInfo "$(ls -dl "${dir}" 2>&1)"
+    finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
+  fi
+
+  local dfResult
+  local filesystem
+  local filesystemInfo
+  dfResult="$(df -P "${dir}")"
+  #== 获取目录文件系统路径
+  filesystem="$(printf '%s' "${dfResult}" | tail -1 | awk '{ print $NF }')"
+  #== 获取指定路径的文件系统信息
+  filesystemInfo="$(getFilesystemInfo "${filesystem}")"
+  if ! printf '%s' "${filesystemInfo}" | grep -qw rw; then
+    toLogWarn "df-based check determined filesystem mounted under ${filesystem} as readonly, trying fallback."
+    toLogWarn "Filesystem access rights: '${filesystemInfo}'"
+    toLogWarn "df returned: ${dfResult}"
+
+    if ! testWriteAccessToDir "${dir}"; then
+      toConsoleError "readonly filesystem mounted under ${filesystem}"
+      finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
+    fi
+  fi
+
+  toLogInfo "Rights on directory ${dir} are sufficient"
+} 2>>"${LOG_FILE}"
+
+#== 【3】=目录是否写权限
+checkIfInstallationPathIsWriteable() {
+  for dir in "${@}"; do
+    if [ -d "${dir}" ]; then
+      checkAccessRightsTo "${dir}"
+      break
+    fi
+  done
+}
+
+#== 【3】=检查目录权限
+checkAccessRightsToDirs() {
+  checkIfInstallationPathIsWriteable "${INSTALL_DIR}" "${BASE_INSTALL_DIR}" "${INSTALL_BASE}" /
+
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+    checkAccessRightsTo "${INIT_DIR}"
+  fi
+}
+
+
+#== 【0】=检查系统是 LINUX、AIX及指令集(X86_64\IA64\X86)
+checkSystemCompatibility() {
+  local expectedPlatform="LINUX"
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    expectedPlatform="AIX"
+  fi
+
+  #== 获取系统名称
+  local platform
+  platform="$(uname | sed -e 's/_.*//' | sed -e 's/\///' | tr '[:lower:]' '[:upper:]')"
+  if [ "${platform}"x != "${expectedPlatform}"x ]; then
+    printf "Cannot determine platform or platform not supported: <%s>" "${platform}"
+    return 1
+  fi
+
+  #== 检查系统指令集(X86_64\IA64\X86)
+  local detectedArchitecture
+  if ! detectedArchitecture="$(arch_checkArchitectureCompatibility)"; then
+    printf "Cannot determine architecture or architecture not supported: <%s>" "${detectedArchitecture}"
+    return 1
+  fi
+
+  printf 'Detected platform: %s' "${platform}"
+  if [ "${detectedArchitecture}" ]; then
+    printf ' arch: %s' "${detectedArchitecture}"
+  fi
+
+  return 0
+}
+
+#== 【4】=从sh文件读取压缩文件 tarfile_$$.base64
+separateExternalTar() {
+  toLogInfo "Determining begin of tar archive..."
+  local tarBegin
+  local tarEnd
+  #== 压缩文件开始行数,占位符为【#################ENDOFSCRIPTMARK############】
+  tarBegin="$(locateDelimiter "#################ENDOFSCRIPTMARK############" "")"
+  tarBegin=$((tarBegin + 1))
+  #== 压缩文件结束行数,占位符为【----SIGNED-INSTALLER】
+  tarEnd="$(locateDelimiter "----SIGNED-INSTALLER" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})"
+  toLogInfo "tarBegin=${tarBegin} tarEnd=${tarEnd}"
+
+  if [ ! "${tarEnd}" ]; then
+    toConsoleError "S/MIME signature is missing, installation package is corrupted."
+    finishInstallation "${EXIT_CODE_CORRUPTED_PACKAGE}"
+  fi
+
+  local tarLength=$((tarEnd - tarBegin))
+  toLogInfo "tarLength=${tarLength}"
+  #== 从sh文件读取压缩文件 tarfile_$$.base64
+  tail -n +"${tarBegin}" "${INSTALLER_FILE}" 2>/dev/null | head -${tarLength} >"${EXTERNAL_TAR_FILE}"
+}
+
+#== 【4】【5】=进入目录
+changeWorkingDir() {
+  if ! cd "${1}"; then
+    toLogError "Failed to change working directory to ${1}"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== shellcheck disable=SC2181
+#== 【4】=解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+unpackArchiveWithoutCache() {
+  #== 解压文件编码
+  local base64Binary="${UNPACK_BINARY}"
+  #== 解压文件编码参数
+  local base64BinaryArgs="${UNPACK_BINARY_ARGS}"
+  #== 使用xzdec命令可以进行liblzma为基础的xz文件解压缩
+  local xzBinary="${INSTALL_DIR}/xzdec"
+  #== 进入目录
+  changeWorkingDir "${INSTALL_DIR}"
+
+  if ! isAvailable tar; then
+    toConsoleError "tar binary not found. Setup can't continue"
+    finishInstallation "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
+  fi
+
+  local totalLines
+  if ! isAvailable "${base64Binary}"; then
+    toLogInfo "${base64Binary} not found. Falling back to openssl decode"
+    if ! isAvailable openssl; then
+      toConsoleError "Neither ${base64Binary} nor openssl can be found. Setup can't continue"
+      finishInstallation "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
+    fi
+    #== 如果没有 base64 命令,则使用 openssl 解压文件
+    base64Binary="openssl"
+    base64BinaryArgs="enc -base64 -d -in"
+
+    if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+      #truncate the first and the last one line due to specific format of uuencode on aix
+      totalLines="$(wc -l "${EXTERNAL_TAR_FILE}" | awk '{print $1}')"
+      head -$((totalLines - 1)) "${EXTERNAL_TAR_FILE}" 2>/dev/null | tail +2 >"${EXTERNAL_TAR_FILE}.$$"
+      mv -f "${EXTERNAL_TAR_FILE}.$$" "${EXTERNAL_TAR_FILE}"
+    fi
+  fi
+
+  {
+    #== base64 转编码后,执行 tar 解压
+    "${base64Binary}" "${base64BinaryArgs}" "${EXTERNAL_TAR_FILE}" | tar -x -p -f -
+  } 2>>"${LOG_FILE}"
+
+  #== base64 转编码 或 tar解压失败
+  if [ $? -gt 0 ]; then
+    toConsoleError "Archive is corrupted or memory allocation failed. Installation aborted."
+    finishInstallation "${EXIT_CODE_NOT_ENOUGH_MEMORY}"
+  fi
+
+  #== 进入目录
+  changeWorkingDir "${TMP_DIR}"
+  {
+    #== 使用xzdec命令解压后,执行 tar 解压
+    "${xzBinary}" "${INTERNAL_TAR_FILE}" | tar -x -p -f -
+  } 2>>"${LOG_FILE}"
+
+  if [ $? -gt 0 ]; then
+    toConsoleError "XZ compressed archive is corrupted or memory allocation failed. Installation aborted."
+    finishInstallation "${EXIT_CODE_NOT_ENOUGH_MEMORY}"
+  fi
+  #== 进入目录
+  changeWorkingDir "${INSTALL_DIR}"
+}
+
+#== 【4】=解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+unpackArchive() {
+  toConsoleInfo "Unpacking. This may take a while..."
+
+  #== 【参数】是否使用解压缓存
+  if [ "${PARAM_INTERNAL_USE_UNPACK_CACHE}"x = "true"x ]; then
+    if [ -d "${UNPACK_CACHE}" ]; then
+      toLogInfo "Unpack cache will be used."
+      cp -Rp "${UNPACK_CACHE}"/* "${TMP_DIR}"
+    else
+      toLogInfo "Unpack cache does not exist."
+      mkdir -p "${UNPACK_CACHE}"
+      #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+      unpackArchiveWithoutCache
+      cp -Rp "${TMP_DIR}"/* "${UNPACK_CACHE}"
+    fi
+  else
+    toLogInfo "Unpacking without cache"
+    #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+    unpackArchiveWithoutCache
+  fi
+
+  toConsoleInfo "Unpacking complete."
+}
+
+#== 【3】=检查容器部署、运行情况、配置参数
+#isDeployedInsideOpenVZContainer
+#isProcessRunningInContainer
+#isDeployedViaContainer
+
+
+#== Checking if libc is new enough
+#== 【3】=格式化version
+format_version() {
+  printf '%s' "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }'
+}
+
+#== 【3】=格式化路径
+format_patch() {
+  printf '%s' "$@" | tail -n 1 | awk -F- '{ printf("%d\n", $3); }'
+}
+
+#== 【3】=检查是否降级安装
+checkIfDowngrade() {
+  if [ "${SKIP_DOWNGRADE_CHECK}"x = "true"x ]; then
+    toConsoleInfo "Skipped downgrade check"
+    return
+  fi
+
+  local installVersionFile="${INSTALL_DIR}/installer.version"
+  if [ ! -f "${installVersionFile}" ]; then
+    toLogWarn "Could not perform downgrade check, ${installVersionFile} file is missing"
+    return
+  fi
+
+  local oldVersion
+  oldVersion="$(cat "${installVersionFile}")"
+  if [ "$(format_version "${AGENT_INSTALLER_VERSION}")" -eq "$(format_version "${oldVersion}")" ]; then
+    toConsoleError "${BRAND_PRODUCT_NAME} is already installed, please uninstall the old version using [${INSTALL_DIR}/uninstall.sh]."
+#    toLogError "Attempted downgrade from ${oldVersion} to ${AGENT_INSTALLER_VERSION}"
+    finishInstallation "${EXIT_CODE_UNSUPPORTED_DOWNGRADE}"
+  fi
+}
+
+#== 【3】=检查是否已经安装
+checkIfAlreadyInstalled() {
+  if [ -f "${INSTALL_DIR}/uninstall.sh" ] && [ -f "${AGENT_BIN_DIR}/${AGENT_PROC}" ] ; then
+#    toConsoleError "Agent already installed. Uninstalling previous version."
+#    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+
+    checkIfDowngrade
+    PARAM_UPGRADE="yes"
+  else
+#  		if [ -f "${SIF_AGENT_INSTALL_PATH}/lib64/${AGENT_BIN}" ]; then
+#  			sif_toConsoleError "Upgrade is not possible because uninstall script is missing"
+#  			finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+#  		fi
+      local fileNum
+      fileNum=`ls ${INSTALL_DIR} | wc -l`
+      if [ "${fileNum}" -gt 1 ];then
+         toConsoleError "${INSTALL_DIR} is not empty. Please clean or change the installation directory manually."
+         finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+      fi
+  fi
+
+
+
+}
+
+#**********************************************************
+# Init related functions
+#**********************************************************
+
+#== clears dependencies in LSB init script
+#== 【5】=清除LSB init脚本中的依赖项
+clearDependenciesInLSBInit() {
+  local file="${1}"
+  toConsoleInfo "Clearing dependencies in file ${file}"
+  awk '
+		BEGIN {
+			req_start_found=0;
+			req_stop_found=0;
+			REQ_START="# Required-Start:";
+			REQ_STOP="# Required-Stop:";
+			PATTERN_REQ_START="^" REQ_START;
+			PATTERN_REQ_STOP="^" REQ_STOP;
+		}
+		{
+			if ($0 ~ PATTERN_REQ_START && req_start_found == 0) {
+				print REQ_START;
+				req_start_found++;
+			} else if ($0 ~ PATTERN_REQ_STOP && req_stop_found == 0) {
+				print REQ_STOP;
+				req_stop_found++;
+			} else
+				print $0
+		}' "${file}" >"${file}.tmp" && mv -f "${file}.tmp" "${file}"
+
+  chmod +x "${file}"
+}
+
+#== 【5】=指定目录添加自动启动脚本
+addScriptToSystemvAutostart() {
+  local prefix="${1}"
+  local file="${2}"
+  local suffix="${3}"
+
+  toLogInfo "Adding ${file} to autostart"
+  #== 自动启动工具
+  if ! runAutostartAddingTool "${prefix}" "${file}" "${suffix}"; then
+    toLogWarn "Failed to add ${file} script to autostart. Trying without dependencies..."
+    #== 清除LSB init脚本中的依赖项
+    clearDependenciesInLSBInit "${INIT_DIR}/${file}"
+    if ! runAutostartAddingTool "${prefix}" "${file}" "${suffix}"; then
+      toConsoleError "Cannot add ${file} to autostart. For details, see: ${LOG_FILE}"
+    fi
+  fi
+}
+
+#== 【5】=指定目录添加自动启动脚本
+addScriptsToAutostart() {
+  local prefix="${1}"
+  local suffix="${2}"
+  #== 指定目录添加自动启动脚本
+  addScriptToSystemvAutostart "${prefix}" "${SERVICE_SCRIPT_FILE}" "${suffix}"
+}
+
+#== 【5】=设置自动启动
+#setupSystemvAutostart() {
+#  toLogInfo "Adding ${BRAND_AGENT_PRODUCT_NAME} to autostart..."
+#
+#  if [ -x /usr/bin/update-rc.d ]; then #Ubuntu
+#    #== 指定目录添加自动启动脚本
+#    addScriptsToAutostart "/usr/bin/update-rc.d " "defaults"
+#  elif [ -x /usr/sbin/update-rc.d ]; then #Ubuntu
+#    addScriptsToAutostart "/usr/sbin/update-rc.d " "defaults"
+#  elif [ -x /sbin/chkconfig ]; then #RedHat
+#    addScriptsToAutostart "/sbin/chkconfig --add "
+#  elif [ -x /usr/lib/lsb/install_initd ]; then #Suse
+#    addScriptsToAutostart "/usr/lib/lsb/install_initd ${INIT_DIR}/"
+#  elif [ "${ARCH_ARCH}"x = "AIX"x ]; then
+#    #== 【不存在】
+#    arch_setAutostart
+#  else
+#    toConsoleError "Couldn't add ${BRAND_AGENT_PRODUCT_NAME} to autostart. Please adjust and add it manually."
+#  fi
+#}
+
+#== 【5】=设置 cwserveragent.service 中用户
+setServiceScriptUser() {
+  if ! isNonRootModeEnabled; then
+    return
+  fi
+  #== 读取用户名(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-user)
+  local user
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 修改 cwserveragent.service 中用户信息
+  sed -i "s/User=.*/User=${user}/g" "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}"
+}
+
+#== 【5】=配置自动启动 cwserveragent.service
+setupSystemdAutostart() {
+  mv -f "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" "${SYSTEMD_UNIT_FILES_DIR}/"
+  setRightsForFiles "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" 644
+
+  #== 设置 cwserveragent.service 中用户
+  setServiceScriptUser
+
+  if isAvailable restorecon; then
+    restorecon "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}"
+  fi
+
+  #== 执行 systemctl 命令配置允许开机启动 cwserveragent.service
+  executeSystemctlCommand enable "${SYSTEMD_UNIT_FILE_AGENT}"
+  #== 执行 systemctl 命令重新加载模块
+  executeSystemctlCommand daemon-reload ""
+}
+
+#== 【6】=运行service 脚本
+execIntoServiceScript() {
+  toConsoleInfo "${SERVICE_SCRIPT_FILE} will be started via exec()"
+  #== 清除安装临时文件
+  cleanInstallationTemporaryFiles
+  toLogInfo "Installation finished, PID $$."
+
+  local command="exec ${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} exec"
+  toLogInfo "Executing: ${command}"
+  #== 执行 cwserveragent exec
+  ${command}
+
+  toLogError "Could not execute: ${command}"
+  finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+}
+
+#== 【6】=运行agent
+runAgents() {
+  toConsoleInfo "Starting agents..."
+
+  toLogInfo "Using ${INIT_SYSTEM} to start the agent"
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+    #== 运行初始化命令(通过 service start 方式 或 直接运行可执行命令)
+    executeInitScriptCommand start "true"
+  else
+    #== 执行 systemctl start 命令
+    executeSystemctlCommand start "${SYSTEMD_UNIT_FILE_AGENT}"
+  fi
+
+  if [ $? -eq 0 ]; then
+    toConsoleInfo "${SERVICE_SCRIPT_FILE} service started"
+  else
+    toConsoleError "Failed to start service: ${SERVICE_SCRIPT_FILE}, it is possible that your init system is not functioning properly. For details, see: ${LOG_FILE}"
+  fi
+}
+
+#== 【5】=配置自动启动
+#setupAutostart() {
+#  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+#    #== 设置自动启动
+#    setupSystemvAutostart
+#  else
+#    #== 配置自动启动 cwserveragent.service
+#    setupSystemdAutostart
+#  fi
+#}
+
+#**********************************************************
+# Process agent related functions
+#**********************************************************
+
+#== 【5】=创建 agent 状态文件
+createAgentStateFile() {
+  local path="${1}"
+  local agentStateContents="RUNNING"
+
+  toLogInfo "Writing ${agentStateContents} to ${path} file"
+  {
+    printf "%s" "${agentStateContents}" >"${path}.tmp"
+    mv -f "${path}.tmp" "${path}"
+  } 2>>"${LOG_FILE}"
+}
+
+#== 【0】=检查全路径是否可读权限(目录最深100层)
+checkIfPathIsGloballyReadable() {
+  local path="${1}"
+  local sourcePath="${path}"
+  local maxDepth=100
+  while [ "${path}"x != "/"x ]; do
+    #== 【0】=获取文件权限信息
+    local accessRights
+    accessRights="$(arch_getAccessRights "${path}")"
+    if ! printf '%s' "${accessRights}" | cut -c 8-10 | grep -qE "r.[xt]"; then
+      toConsoleError "Insufficient access rights (${accessRights}) on: ${path}"
+      toConsoleError "${sourcePath} path must be globally readable (r-x permissions for others)."
+      toConsoleError "Please adjust the permissions and then retry the installation."
+      finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
+    fi
+
+    path="$(dirname "${path}")"
+
+    maxDepth=$((maxDepth - 1))
+    if [ "${maxDepth}" -eq 0 ]; then
+      toLogWarn "Unable to verify access rights on ${path}"
+      return
+    fi
+  done
+}
+
+#== 【0】=创建 PARAM_INSTALL_DIR -> INSTALL_DIR 软连接
+createSymlinkToInstallLocation() {
+  #== INSTALL_DIR 不能是软链接地址
+  if [ -L "${INSTALL_DIR}" ] && [ ! -e "${INSTALL_DIR}" ]; then
+    toConsoleError "Detected that ${INSTALL_DIR} is a dangling symlink, please remove it and then retry the installation"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== PARAM_INSTALL_DIR 和 INSTALL_DIR 都不能是空地址
+  if [ "${PARAM_INSTALL_DIR}"x = "${INSTALL_DIR}"x ] || [ -z "${PARAM_INSTALL_DIR}" ]; then
+    return
+  fi
+
+  #== INSTALL_DIR 是软连接,并获取 PARAM_INSTALL_DIR 和 INSTALL_DIR 的真实地址
+  if [ -L "${INSTALL_DIR}" ] && [ "$(readLink -m "${PARAM_INSTALL_DIR}")"x = "$(readLink -m "${INSTALL_DIR}")"x ]; then
+    return
+  fi
+
+  #== 目录存在,表示未卸载
+  if [ -e "${INSTALL_DIR}" ]; then
+    toConsoleError "Leftovers from previous agent installation detected"
+    toConsoleError "If you wish to use INSTALL_DIR parameter then perform a cleanup by following these steps:"
+    toConsoleError "1. Uninstall the agent"
+    toConsoleError "2. Restart all applications that have Deep Monitoring enabled (host restart is fine as well)"
+    toConsoleError "3. Remove ${INSTALL_DIR}"
+    toConsoleError "and then retry the installation."
+    toConsoleError "#DEBUG==For further information please visit ${HELP_URL}/command-line-install"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 创建不存在的目录
+  createDirIfNotExistAndSetRights "${PARAM_INSTALL_DIR}" 1775
+  #== 检查全路径是否可读权限(目录最深100层)
+  checkIfPathIsGloballyReadable "${PARAM_INSTALL_DIR}"
+  #== 创建不存在的目录 /opt/cloudwise
+  createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" 755
+
+  #== 创建 PARAM_INSTALL_DIR -> INSTALL_DIR
+  local lnOutput
+  if lnOutput="$(ln -fs "${PARAM_INSTALL_DIR}" "${INSTALL_DIR}" 2>&1)"; then
+    toConsoleInfo "Symlink ${INSTALL_DIR} -> ${PARAM_INSTALL_DIR} created"
+  else
+    toConsoleError "Failed to create symlink ${INSTALL_DIR} -> ${PARAM_INSTALL_DIR}, aborting installation: ${lnOutput}"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== 【5】=修改文件系统用户和用户组
+changeFilesOwnership() {
+  local user
+  local group
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  group="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+
+  toLogInfo "Changing ownership of files to root:${group}"
+  #== /opt/cloudwise/cwserveragent 目录下用户和用户组
+  commandErrorWrapper chown "${user}:${group}" "${AGENT_BASE_DIR}"
+  commandErrorWrapper chown -R "${user}:${group}" "${INSTALL_DIR}"
+  toLogInfo "Recursively changing group ownership of ${AGENT_CONF_DIR} to ${group}"
+
+}
+
+#== 【5】=文件用户权限检查
+fileCapabilitiesCompatibilityCheck() {
+  #== 获取配置用户
+  local user
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 获取OS bin配置路径 /opt/cloudwise/cwserveragent/lib64/cloudwiseosconfig
+  if output="$("$(getOsConfigBinPath)" file-capabilities-compatibility-check "${user}" 2>&1)"; then
+    return 0
+  fi
+
+  if [ "${PARAM_NON_ROOT_MODE}" ]; then
+    toConsoleWarn "Failed to enable non-privileged mode, kernel does not support file capabilities. For details, see: ${LOG_FILE}"
+    toLogWarn "Capabilities test output: ${output}"
+  else
+    toConsoleInfo "Non-privileged mode was not enabled, kernel does not support file capabilities. For details, see: ${LOG_FILE}"
+    toLogInfo "Capabilities test output: ${output}"
+  fi
+  #== 设置删除root权限
+  "$(getAgentInstallActionPath)" "--set-drop-root-privileges" "false" >>"${LOG_FILE}" 2>&1
+  return 1
+}
+
+
+#**********************************************************
+# User and group related functions
+#**********************************************************
+
+#== 【5】=添加用户组
+addGroup() {
+  local group="${1}"
+
+  if groupExistsInSystem "${group}"; then
+    toLogInfo "Group '${group}' already exists"
+    return 0
+  fi
+
+  local errorMessage
+  errorMessage="$(groupadd "${group}" 2>&1)"
+  local returnCode=$?
+
+  case ${returnCode} in
+  0) toLogInfo "Group '${group}' successfully created" ;;
+  9) toLogInfo "Group '${group}' already exists" ;;
+  *)
+    toLogError "Error occured while adding '${group}' group, return code: ${returnCode}, message ${errorMessage}"
+    return 1
+    ;;
+  esac
+  return 0
+}
+
+#== 【5】=添加用户
+addUser() {
+  local user="${1}"
+  local group="${2}"
+  local groupCreated="${3}"
+  local errorMessage
+  local mod="/bin/false"
+  if [ "${PARAM_USER_LOGIN}"x == "true"x ]; then
+    mod="/bin/bash"
+  fi
+  if userExistsInSystem "${user}"; then
+    toLogInfo "User '${user}' already exists."
+    #-- 权限更新
+#    errorMessage="$(usermod -s "${mod}" "${user}" 2>&1)"
+    return 0
+  fi
+
+  if [ "${groupCreated}" -eq 0 ]; then
+    errorMessage="$(useradd -r --shell "${mod}" -g "${group}" "${user}" 2>&1)"
+  else
+    errorMessage="$(useradd -r --shell "${mod}" "${user}" 2>&1)"
+  fi
+
+  local returnCode=$?
+  if [ ${returnCode} -ne 0 ]; then
+    toConsoleError "Failed to create user '${user}'"
+    toLogError "Error occured while adding '${user}' user, return value: ${returnCode}, error message: ${errorMessage}."
+    return 1
+  fi
+
+  toConsoleInfo "User '${user}' added successfully."
+  return 0
+}
+
+#== 【5】=添加用户和用户组信息
+addUserAndGroup() {
+  local user="${1}"
+  local group="${2}"
+  #== 添加用户组
+  addGroup "${group}"
+  #== 添加用户
+  addUser "${user}" "${group}" $?
+}
+
+#== 【5】=配置用户和用户组
+handleUser() {
+  toLogInfo "Processing user and group..."
+  local user
+  local group
+  #== 读取用户名(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-user)
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 读取用户组(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-group)
+  group="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 添加用户和用户组信息
+  addUserAndGroup "${user}" "${group}"
+}
+
+#== 【4】=获取agent preLoad 安装路径,并校验是否可执行
+checkCompatibilityWithInstallActionBinary() {
+  local output
+  #== 获取agent preLoad 安装路径,并校验是否可执行
+  output="$("$(getAgentInstallActionPathPreInstallation)" "--sanity-check" 2>&1)"
+  local exitCode=$?
+  toLogAdaptive ${exitCode} "Compatibility check exit code = ${exitCode}, output = ${output}"
+  if [ ${exitCode} -ne 0 ] || [ "${output}"x != "SUCCESS"x ]; then
+    toConsoleError "System compatibility check failed, this may be caused by a problem with glibc, dynamic loader or incompatible operating system version."
+    toConsoleError "Detected version: $(detectLinuxDistribution)"
+    toConsoleError "For a list of supported distributions and versions, see: ${HELP_URL}"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== 【4】=【部署】解压文件
+extractFiles() {
+  umask 000
+  toConsoleInfo "Extracting..."
+  #== 从sh文件读取压缩文件 tarfile_$$.base64
+  separateExternalTar
+  #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+  unpackArchive
+  umask 022
+}
+
+#== 【3】=检查发现初始化系统信息(INIT_SYSTEM、INIT_SYSTEM_VERSION、INIT_DIR)
+detectInitSystem() {
+  #== 获取初始化系统信息 (INIT_SYSTEM、INIT_SYSTEM_VERSION)
+  checkInitSystem
+  toLogInfo "Detected init system: ${INIT_SYSTEM}, version: ${INIT_SYSTEM_VERSION}"
+  #== 设置系统初始化脚本目录
+  if ! setLocationOfScripts; then
+    toConsoleError "Cannot determine location of init scripts."
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== 【4】=【旧配置】读取旧配置参数
+readLegacySetting() {
+  local paramName="${1}"
+  local value
+  value="$(sed -n "s|^${paramName}=||p" "${LEGACY_AGENT_CONF_FILE}" | tr -d '\r' 2>/dev/null)"
+  if [ "${value}" ]; then
+    local valueToPrint="${value}"
+    if [ "${paramName}"x = "${CONF_FIELD_NM_LICENSE}"x ]; then
+      valueToPrint="***"
+    fi
+    toLogInfo "Read legacy value: ${paramName} = ${valueToPrint}"
+  fi
+
+  printf '%s' "${value}"
+}
+
+#== 【4】=【旧配置】迁移旧配置文件
+migrateLegacySettingsFromAgentConf() {
+  toLogInfo "Looking for legacy config to migrate."
+  #== 旧配置文件
+  if [ ! -f "${LEGACY_AGENT_CONF_FILE}" ]; then
+    toLogInfo "Unable to read agent config file, skipping legacy config migration"
+    return
+  fi
+
+  if [ ! "${PARAM_CONFIG_SERVER}" ]; then
+    local configServerValue
+    configServerValue="$(readLegacySetting ${CONF_FIELD_NM_CONFIG_SERVER})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_CONFIG_SERVER}: ${PARAM_CONFIG_SERVER}"
+    if [ "${configServerValue}"x = "http://localhost:8020"x ]; then
+      toLogInfo "Param 'server' has default value set, skipping it"
+    else
+      PARAM_CONFIG_SERVER="${configServerValue}"
+    fi
+  fi
+
+  if [ ! "${PARAM_DATA_SERVER}" ]; then
+    PARAM_DATA_SERVER="$(readLegacySetting ${CONF_FIELD_NM_DATA_SERVER})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_DATA_SERVER}: ${PARAM_DATA_SERVER}"
+  fi
+
+  if [ ! "${PARAM_LICENSE}" ]; then
+    PARAM_LICENSE="$(readLegacySetting ${CONF_FIELD_NM_LICENSE})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_LICENSE}: ${PARAM_LICENSE}"
+  fi
+
+  if [ ! "${PARAM_JSON_CONF}" ]; then
+    PARAM_JSON_CONF="$(readLegacySetting ${CONF_FIELD_NM_JSON_CONF})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_JSON_CONF}: ${PARAM_JSON_CONF}"
+  fi
+
+  if [ ! "${PARAM_USER}" ]; then
+    PARAM_USER="$(readLegacySetting ${CONF_FIELD_NM_USER})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_USER}: ${PARAM_USER}"
+
+    if [ ! "${PARAM_GROUP}" ]; then
+      PARAM_GROUP="$(readLegacySetting ${CONF_FIELD_NM_GROUP})"
+      toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_GROUP}: ${PARAM_GROUP}"
+    fi
+  fi
+}
+listProcesses() {
+  local errorMessage="${1}"
+  local includeRegex="${2}"
+
+  local excludeRegex=" grep"
+  if [ "${3}" ]; then
+    excludeRegex="grep|${3}"
+  fi
+
+  toLogInfo "#DEBUG== listProcesses command: ps -e -o \"pid,args\" 2>&1 | grep -E \"${includeRegex}\" | awk '{{ print \$1,\$2 }}' | grep -vE \"${excludeRegex}\""
+  local output
+  if ! output="$(pgrep -f "pid,args" 2>&1 | grep -E "${includeRegex}" | awk '{{ print $1,$2 }}')"; then
+    toLogError "Failed to get ${errorMessage}, output: ${output}"
+    return 1
+  fi
+
+  local foundProcesses
+  foundProcesses="$(printf '%s' "${output}" | grep -vE "${excludeRegex}")"
+  if [ ! "${foundProcesses}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${foundProcesses}" | awk '{{ print $1 }}'
+  return 0
+}
+
+#== 版本&帮助信息
+preParams() {
+  if [ $# -gt 0 ]; then
+    if [ "${1}"x = "-h"x ] || [ "${1}"x = "--help"x ]; then
+        displayHelp
+        exit "${EXIT_CODE_OK}"
+    fi
+
+    if [ "${1}"x = "-v"x ] || [ "${1}"x = "--version"x ]; then
+       pad=20
+       printf "%-${pad}s%s\n" "Version:" "${AGENT_INSTALLER_VERSION}"
+       printf "%-${pad}s%s\n" "Commit:" "${AGENT_BUILD_TAG}"
+       printf "%-${pad}s%s\n" "Build At(UTC):" "${AGENT_BUILD_DATE_INFO}"
+       printf "%-${pad}s%s\n" "Uploader:" "${AGENT_BUILD_UPLOADER}"
+       exit "${EXIT_CODE_OK}"
+    fi
+  fi
+}
+#**********************************************************
+# Main script functions
+#**********************************************************
+
+#== 【0】=初始化安装环境
+initializeInstallation() {
+  preParams "$@"
+  #== 设置PATH
+  setPATH
+  #== 配置umask权限
+  local initialUmask
+  initialUmask="$(umask)"
+  umask 022
+
+  #== 读取配置参数
+#  readParamsSection
+  #== 解析命令行参数
+  parseCommandLineParameters "$@"
+  #== 校验配置参数
+
+  #== 是否存在多个同时安装操作【通过判断 INSTALLER_LOCK_FILE 】
+  if isAnotherInstallationRunning; then
+    #== 结束安装操作
+    finishInstallation "${EXIT_CODE_ANOTHER_INSTALLER_RUNNING}" "keep_lock_file"
+  fi
+
+  #== 创建安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+  createInstallationLockFile
+  #== 配置是否更新
+  PARAM_UPGRADE="no"
+
+  #== 获取并校验系统兼容性【LINUX/AIX  X86_64/IA64】
+  local platformDetectionString
+  if ! platformDetectionString="$(checkSystemCompatibility)"; then
+    toConsoleError "${platformDetectionString}"
+    finishInstallation "${EXIT_CODE_OS_NOT_SUPPORTED}"
+  fi
+
+  #== 创建 PARAM_INSTALL_DIR -> INSTALL_DIR 软连接
+  createSymlinkToInstallLocation
+  #== 创建日志目录及日志文件installation_$$.log
+  createLogDirsIfMissing
+  #== 配置信号捕获,执行清空安装临时目录
+  configureSignalHandling "cleanInstallationTemporaryFiles"
+  #== 常规日志
+  initializeLog "${@}"
+
+  toLogInfo "Initial umask: ${initialUmask}"
+  toConsoleInfo "${platformDetectionString}"
+  toLogInfo "Distribution: $(detectLinuxDistribution)"
+}
+
+#== 【3】=安装前检查
+preInstallationChecks() {
+  #== 检查发现初始化系统信息(INIT_SYSTEM、INIT_SYSTEM_VERSION、INIT_DIR)
+  detectInitSystem
+
+  #== 检查目录权限
+  checkAccessRightsToDirs
+  #== 创建临时目录
+  prepareTempFolder
+  #== 检查是否已经安装
+  checkIfAlreadyInstalled
+
+  if [ ! "${PARAM_USER}" ] && [ "${ARCH_ARCH}"x != "AIX"x ] ; then
+    #== 配置文件中配置用户和用户组是否存在
+    checkUserAndGroupFromConfig
+  fi
+
+  #== 检查安装目录空间
+  checkInstallPathFreeSpace
+
+}
+
+uninstallAgent() {
+	toConsoleInfo "Agent already installed. Uninstalling previous version."
+#	printf '%s' "upgrade" >"${UNINSTALL_INFO_FILE_LEGACY_PATH}"
+
+	#shellcheck disable=SC2086
+	"${INSTALL_DIR}/uninstall.sh" $$ ${SKIP_PRIVILEGES_CHECK} 2>>"${LOG_FILE}"
+
+	local uninstallExitCode=$?
+	if [ ${uninstallExitCode} -gt 0 ]; then
+		toConsoleError "Error during uninstalling, code: ${uninstallExitCode}. Installation aborted."
+		finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+	fi
+
+	toConsoleInfo "Agent uninstalled."
+}
+
+#== 【4】=部署文件
+deployFiles() {
+  if [ "${PARAM_UPGRADE}" = "yes" ]; then
+    uninstallAgent
+  fi
+  #== 【部署】解压文件
+  extractFiles
+  setupAll
+  createCurrentVersionSymlink
+}
+enableRootDropping() {
+  local output=
+  if ! isAvailable setcap; then
+    toConsoleWarn "Failed to enable non-privileged mode, kernel does not support file capabilities. Set NON_ROOT_MODE=false."
+    #== writeParamToConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "false" "${LEGACY_AGENT_CONF_FILE}"
+    #== writeParamToConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "false" "${INSTALLER_CONF_FILE}"
+    #== editScriptFileParam "readonly PARAM_NON_ROOT_MODE" "false" "${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE}"
+    return
+  fi
+
+  #== 设置文件权限 (https://www.cnblogs.com/xzongblogs/p/14106481.html)
+  #== CAP_DAC_OVERRIDE:绕过文件的读,写,和执行权限检查。
+  #== CAP_FOWNER:对于通常要求进程的文件系统 UID 与文件的 UID 匹配的操作,绕过权限检查 (比如,chmod(2),utime(2)),除了那些包含在 CAP_DAC_OVERRIDE 和 CAP_DAC_READ_SEARCH 中的操作
+  #== CAP_IPC_LOCK:允许锁定共享内存片段
+  #== CAP_SYS_PTRACE:允许跟踪任何进程
+  #== CAP_SYS_ADMIN:访问特权 perf 事件信息
+  #== CAP_SYS_RESOURCE:忽略资源限制
+  #== CAP_NET_ADMIN:允许执行多种网络有关的操作
+  commandErrorWrapper setcap cap_setgid,cap_setuid,cap_dac_override,cap_fowner,cap_chown,cap_ipc_lock,cap_sys_ptrace,cap_sys_admin,cap_sys_resource,cap_net_admin+ep "${AGENT_BIN_DIR}/${AGENT_PROC}"
+  local setCapCwServerAgentExitCode=$?
+  if [ ${setCapCwServerAgentExitCode} -eq 0 ] ; then
+    toConsoleInfo "Set file capabilities [${AGENT_PROC}]"
+  else
+    toConsoleWarn "Failed to enable non-privileged mode. Exit Code : ${setCapCwServerAgentExitCode} . For details, see: ${LOG_FILE}"
+    toLogWarn "Set file capabilities output: ${output}"
+  fi
+}
+
+#== 【5】=配置安装
+configureInstallation() {
+  #== 配置参数(param、installation.conf)
+  #== 自定义修改配置, sed ,echo ...  参考 applyAgentSettings
+  if [ "${PARAM_TEST}" ]; then
+    toConsoleOnly "Applying test value is: ${PARAM_TEST}"
+  fi
+  #== 获取bool值参数
+  if [ "${PARAM_BOOL}" ]; then
+    toConsoleOnly "Applying bool value is: ${PARAM_BOOL}"
+  fi
+
+
+  if [ "${ARCH_ARCH}"x != "AIX"x ]; then
+    #== 配置用户和用户组
+    if handleUser; then
+      #== 修改文件系统用户和用户组
+      changeFilesOwnership
+    fi
+    #== 设置root权限
+    enableRootDropping
+  fi
+  #== 系统配置(策略配置、dump proc、agent 进程配置、自动启动)
+#  setupAutostart
+}
+
+#== 【6】=验证安装状态、运行启动脚本
+postInstallationSteps() {
+  #== 运行agent
+#  runAgents
+  finishInstallation "${EXIT_CODE_OK}"
+}
+
+readonly CURR_PATH="$(pwd)"
+main() {
+  #== 【0】=初始化安装环境
+  initializeInstallation "$@"
+  #== 【3】=安装前检查
+  preInstallationChecks
+  #== 【4】=部署文件
+  deployFiles
+  #== 【5】=配置安装
+  configureInstallation
+  #== 【6】=验证安装状态、运行启动脚本
+  postInstallationSteps
+
+}
+
+#**********************************************************
+# Script start
+#**********************************************************
+main "$@"
+
+################################################
+############# DO NOT REMOVE THIS ###############
+#### DO NOT ADD ANYTHING BELOW THIS COMMENT ####
+################################################
+#################ENDOFSCRIPTMARK################
+
+----SIGNED-INSTALLER

+ 611 - 0
dist/aarch64/scripts/package.sh

@@ -0,0 +1,611 @@
+#!/bin/bash
+
+AGENT_INSTALLER_VERSION=1.0.0
+
+#== 当前脚本必须放在 smartagent/scripts 目录下
+readonly SCRIPT_PATH=$(dirname $0)
+readonly SCRIPT_DIR=$(cd $SCRIPT_PATH && pwd)
+readonly CURR_FILE_NAME="$(basename "$0")"
+readonly SMARTAGENT_DIR=$(cd $SCRIPT_DIR/../ && pwd)
+readonly SMARTAGENT_PARENT_DIR=$(cd $SCRIPT_DIR/../../ && pwd)
+
+readonly BRAND_FORMAL_NAME="Cloudwise"
+BRAND_PRODUCT_NAME="euspace"
+BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}"
+readonly BRAND_FORMAL_NAME_LOWER="cloudwise"
+readonly BRAND_PRODUCT_NAME_LOWER="cwserveragent"
+readonly BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="ucloudwise"
+
+
+readonly BAK_EXT_NAME=".bak"
+#== cw-serveragent
+readonly SERVICE_SCRIPT_FILE="cw-oneagent"
+readonly XZDEC_NAME="xzdec"
+readonly INSTALL_TEMP_FILE_NAME="install_temp.sh"
+readonly INSTALL_VERSION_FILE_NAME="installer.version"
+#== {productName}-installer-{version}.sh 即 cwserveragent-installer-1.1.0.sh
+ARCH=$(uname -m)
+TARGET_INSTALL_FILE_NAME="${BRAND_AGENT_PRODUCT_NAME}-installer-Linux-${ARCH}-${AGENT_INSTALLER_VERSION}.sh"
+#TARGET_INSTALL_FILE_NAME="${BRAND_PRODUCT_NAME_LOWER}-installer-${AGENT_INSTALLER_VERSION}.sh"
+
+TARGET_INSTALL_TMP_FILE="${SMARTAGENT_PARENT_DIR}/${TARGET_INSTALL_FILE_NAME}.tmp"
+
+readonly LOG_DIR="${SMARTAGENT_PARENT_DIR}/logs"
+readonly LOG_FILE_NAME="release.log"
+readonly LOG_FILE="${LOG_DIR}/${LOG_FILE_NAME}"
+
+#== 【0】=【退出码】执行成功
+readonly EXIT_CODE_OK=0
+readonly EXIT_CODE_GENERIC_ERROR=1
+readonly EXIT_CODE_NOT_ENOUGH_SPACE=6
+readonly EXIT_CODE_NOT_ENOUGH_MEMORY=7
+#== 【0】=无效参数
+readonly EXIT_CODE_INVALID_PARAM=8
+readonly EXIT_CODE_INSUFFICIENT_PERMISSIONS=9
+readonly EXIT_CODE_SEMANAGE_NOT_FOUND=10
+readonly EXIT_CODE_WATCHDOG_ALREADY_RUNNING=11
+#== 【退出码】接收信号
+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_CORRUPTED_PACKAGE=16
+#== 【退出码】管理系统环境变量配置
+readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
+readonly EXIT_CODE_UNSUPPORTED_DOWNGRADE=18
+readonly EXIT_CODE_OS_NOT_SUPPORTED=19
+readonly EXIT_CODE_DEL_DEFAULT_PARAMS=20
+
+readonly LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS=50
+#**********************************************************
+# Logs
+#**********************************************************
+toLogFile() {
+  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() {
+  toLogFile "[INFO]" "$@"
+}
+
+toLogWarn() {
+  toLogFile "[WARN]" "$@"
+}
+
+toLogError() {
+  toLogFile "[ERROR]" "$@"
+}
+
+toLogAdaptive() {
+  local success="${1}"
+  shift
+  if [ "${success}" -eq 0 ]; then
+    toLogInfo "$@"
+  else
+    toLogError "$@"
+  fi
+}
+
+toConsoleInfo() {
+  toConsoleOnly "$@"
+  toLogInfo "$@"
+}
+
+toConsoleWarn() {
+  toConsoleOnly "Warn:" "$@"
+  toLogWarn "$@"
+} >&2
+
+toConsoleError() {
+  toConsoleOnly "Error:" "$@"
+  toLogError "$@"
+} >&2
+
+#**********************************************************
+# compress
+#**********************************************************
+tarSmartAgent() {
+  toConsoleInfo "There are 5 steps to packing, begin package ${BRAND_AGENT_PRODUCT_NAME}...."
+  #== 将打包脚本(package.sh、xzdec、install_temp.sh、smartagent、uninstall.sh)移动到临时目录
+  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
+    mv -f "${SCRIPT_DIR}/${fileNm}" "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" 2>>"${LOG_FILE}"
+  done
+  mv -f "${SCRIPT_DIR}/${XZDEC_NAME}" "${SMARTAGENT_PARENT_DIR}/" 2>>"${LOG_FILE}"
+  cp -f "${SMARTAGENT_PARENT_DIR}/${INSTALL_TEMP_FILE_NAME}${BAK_EXT_NAME}" "${TARGET_INSTALL_TMP_FILE}" 2>>"${LOG_FILE}"
+
+  for fileNm in "uninstall.sh"; do
+    cp -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" "${SCRIPT_DIR}/${fileNm}" 2>>"${LOG_FILE}"
+  done
+
+  #== 删除安装脚本中注释
+  if [ "${PARAM_DEBUG}"x != "true"x ]; then
+    toConsoleInfo "Delete the type [#==] comment ..."
+    sed -i '/#==/d' "${TARGET_INSTALL_TMP_FILE}"
+#    sed -i '/#==/d' "${SCRIPT_DIR}/${SERVICE_SCRIPT_FILE}"
+    sed -i '/#==/d' "${SCRIPT_DIR}/uninstall.sh"
+    toConsoleInfo "Delete the type [#DEBUG==] comment ..."
+    sed -i '/#DEBUG==/d' "${TARGET_INSTALL_TMP_FILE}"
+#    sed -i '/#DEBUG==/d' "${SCRIPT_DIR}/${SERVICE_SCRIPT_FILE}"
+    sed -i '/#DEBUG==/d' "${SCRIPT_DIR}/uninstall.sh"
+  fi
+
+  if [ "${PARAM_RELEASE}"x = "true"x ]; then
+    deleteDefaultParams "${TARGET_INSTALL_TMP_FILE}"
+  fi
+
+  #== 进入 smartagent 目录下
+  cd "${SMARTAGENT_DIR}"
+  cp -f "${SCRIPT_DIR}/uninstall.sh" ./package_dir
+  #== 执行第一阶段压缩(源码压缩)Cloudwise-SmartAgent.tar
+  toConsoleInfo "step【1】start【tar -cpf "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar" ./package_dir/*】to ${BRAND_AGENT_PRODUCT_NAME}.tar"
+  tar -cpf "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar" --exclude="*.gitkeep" --exclude="*.log" ./package_dir/* >>"${LOG_FILE}" 2>&1
+  rm -f "./package_dir/uninstall.sh"
+
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+  local agentTarSize="$(getStorageSize "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar")"
+
+  cd "${SMARTAGENT_PARENT_DIR}"
+  #== 执行第二阶段压缩(源码压缩 Cloudwise-SmartAgent.tar.xz
+  toConsoleInfo "step【2】start【xz -T0 -z ${BRAND_AGENT_PRODUCT_NAME}.tar】to ${BRAND_AGENT_PRODUCT_NAME}.tar.zx"
+  xz -T0 -1 -z "${BRAND_AGENT_PRODUCT_NAME}.tar" -vv
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 执行第三阶段压缩 Cloudwise-SmartAgent.tar.xz xzdec to Cloudwise-SmartAgent.tar
+  toConsoleInfo "step【3】start【tar -cpf ${BRAND_AGENT_PRODUCT_NAME}.tar ${BRAND_AGENT_PRODUCT_NAME}.tar.xz xzdec】 to ${BRAND_AGENT_PRODUCT_NAME}.tar"
+  tar -cpf "${BRAND_AGENT_PRODUCT_NAME}.tar" "${BRAND_AGENT_PRODUCT_NAME}.tar.xz" xzdec >>"${LOG_FILE}" 2>&1
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 执行第四阶段压缩 Cloudwise-SmartAgent.tar to Cloudwise-SmartAgent.tar.base64
+  toConsoleInfo "step【4】start【base64 ${BRAND_AGENT_PRODUCT_NAME}.tar > ${BRAND_AGENT_PRODUCT_NAME}.tar.base64】 to ${BRAND_AGENT_PRODUCT_NAME}.tar.base64"
+  base64 "${BRAND_AGENT_PRODUCT_NAME}.tar" >"${BRAND_AGENT_PRODUCT_NAME}.tar.base64" 2>>"${LOG_FILE}"
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 执行第五阶段将 base64 文件写入安装脚本
+  toConsoleInfo "step【5】start write 【${BRAND_AGENT_PRODUCT_NAME}.tar.base64】 to ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}"
+  #== 设置脚本中版本、创建时间、占用空间信息
+  editInstallScriptParam "${TARGET_INSTALL_TMP_FILE}" ${agentTarSize}
+
+  sed -i "/#################ENDOFSCRIPTMARK################/r ${BRAND_AGENT_PRODUCT_NAME}.tar.base64" "${TARGET_INSTALL_TMP_FILE}"
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  toConsoleInfo "${BRAND_AGENT_PRODUCT_NAME} packaging success."
+  finishPackage "${EXIT_CODE_OK}"
+}
+
+buildVersion() {
+  local oldVersion
+  if oldVersion="$(getOldVersion)"; then
+    setInstallVersion "${oldVersion}"
+    removeIfExist "${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}"
+		toConsoleInfo "Delete file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}."
+  fi
+
+  if [ "${PARAM_VERSION}" ]; then
+    setInstallVersion "${PARAM_VERSION}"
+    return
+  fi
+}
+
+setInstallVersion() {
+  local version="${1}"
+  if [ ! "${version}" ]; then
+    toConsoleWarn "Set install version failed,not found version version."
+    return
+  fi
+
+  AGENT_INSTALLER_VERSION="${version}"
+  BRAND_PRODUCT_NAME="${PARAM_NAME}"
+  BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}"
+  TARGET_INSTALL_FILE_NAME="${BRAND_AGENT_PRODUCT_NAME}-installer-Linux-${ARCH}-${AGENT_INSTALLER_VERSION}.sh"
+  #== {productName}-installer-{version}.sh 即 cwserveragent-installer-1.1.0.sh
+#  TARGET_INSTALL_FILE_NAME="${BRAND_PRODUCT_NAME_LOWER}-installer-${AGENT_INSTALLER_VERSION}.sh"
+  TARGET_INSTALL_TMP_FILE="${SMARTAGENT_PARENT_DIR}/${TARGET_INSTALL_FILE_NAME}.tmp"
+}
+
+getOldVersion() {
+	local installVersionFile="${SMARTAGENT_DIR}/installer.version"
+	if [ ! -f "${installVersionFile}" ]; then
+		toLogWarn "Could not find ${installVersionFile} file."
+		return 1
+	fi
+
+	local oldVersion="$(cat "${installVersionFile}")"
+	if [ ! "${oldVersion}" ]; then
+		toLogWarn "Could not read install version from ${installVersionFile} file."
+	  return 1
+  fi
+
+  printf '%s' "${oldVersion}"
+  return 0
+}
+
+#== 通过占位分割读取位置
+locateDelimiter() {
+  #== 占位符
+  local delimiter="${1}"
+  #== 从文件结尾读取行数
+  local linesToReadFromEnd="${2}"
+  local filePath="${3}"
+
+  if [ "${linesToReadFromEnd}" ]; then
+    #== 文件总行数n(实际行数=n+1)
+    local linesCount="$(wc -l "${filePath}" | awk '{print $1}')"
+    #== 从后往前读取【linesToReadFromEnd】行
+    local offset="$(tail -n"${linesToReadFromEnd}" "${filePath}" 2>/dev/null | awk '/^'"${delimiter}"'/ { print NR; exit }')"
+    if [ -n "${offset}" ]; then
+      printf "%d" "$((linesCount - linesToReadFromEnd + offset))"
+    fi
+  else
+    #== 读取占位符所在行(实际行数=n+1)
+    awk '/^'"${delimiter}"'/ { print NR; exit }' "${filePath}"
+  fi
+}
+
+#== 删除安装脚本中默认参数
+deleteDefaultParams() {
+  local filePath="${1}"
+  local sectionName="----PARAMETERS"
+  local begin=$(locateDelimiter "${sectionName}" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS} ${filePath})
+  local end=$(locateDelimiter "${sectionName}--" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS} ${filePath})
+
+  if [ -z "${begin}" ] || [ -z "${end}" ]; then
+    return
+  fi
+
+  toConsoleInfo "Begin delete default params from line ${begin} to ${end}..."
+  local output="$(sed -i "${begin},${end}d" "${filePath}") 2>&1"
+  if [ ! "${output}" ]; then
+    toConsoleError "Delete install script file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME} default params error:${output}"
+    finishPackage "${EXIT_CODE_DEL_DEFAULT_PARAMS}"
+  fi
+  toConsoleInfo "Delete install script file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME} default params success."
+}
+
+#== 设置脚本中版本、创建时间、占用空间信息
+editInstallScriptParam() {
+  local targetFile="${1}"
+  local agentTarSize="${2}"
+  #== 设置版本信息
+  local buildDate="$(date +"%Y-%m-%d")"
+  local buildTag="$(git rev-parse --short HEAD)"
+  local buildDateInfo="$(date +"%Y-%m-%d %H:%M:%S")"
+  local buildUploader="$(hostname)/${USER}"
+  #== 构建日期
+  editScriptFileParam "readonly AGENT_BUILD_DATE" "${buildDate}" "${targetFile}"
+  #== 构建版本
+  editScriptFileParam "readonly AGENT_INSTALLER_VERSION" "${AGENT_INSTALLER_VERSION}" "${targetFile}"
+  #== commitid
+  editScriptFileParam "readonly AGENT_BUILD_TAG" "'${buildTag}'" "${targetFile}"
+  #== 构建日期
+  editScriptFileParam "readonly AGENT_BUILD_DATE_INFO" "'${buildDateInfo}'" "${targetFile}"
+  #== 构建环境信息
+  editScriptFileParam "readonly AGENT_BUILD_UPLOADER" "'${buildUploader}'" "${targetFile}"
+
+  #== 设置占用空间信息
+  local agentDirSize="$(getStorageSize "${SMARTAGENT_DIR}")"
+  local agentBase64FileSize="$(getStorageSize "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar.base64")"
+  local agentInstallFileSize="$(getStorageSize "${TARGET_INSTALL_TMP_FILE}")"
+  local artifactsSize="$((agentBase64FileSize + agentInstallFileSize + agentDirSize))";
+  editScriptFileParam "readonly EXTERNAL_TAR_SIZE" "${agentTarSize}" "${targetFile}"
+  editScriptFileParam "readonly ARTIFACTS_SIZE" "${artifactsSize}" "${targetFile}"
+}
+
+getStorageSize() {
+  local dirName="${1}"
+  if [ ! -e "${dirName}" ]; then
+    printf '%s' "0"
+    return 0
+  fi
+  printf '%s' "$(du -sb "${dirName}" | awk '{print $1}')"
+}
+
+finishFinally() {
+  #== 将打包脚本文件移动到当前目录下
+  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
+    if [ -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" ]; then
+      mv -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" "${SCRIPT_DIR}/${fileNm}" 2>>"${LOG_FILE}"
+    fi
+  done
+  removeIfExist "${SMARTAGENT_DIR}/uninstall.sh"
+  if [ -f "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}" ]; then
+    mv -f "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}" "${SCRIPT_DIR}/" 2>>"${LOG_FILE}"
+  fi
+
+  if [ -f "${TARGET_INSTALL_TMP_FILE}" ]; then
+    mv -f "${TARGET_INSTALL_TMP_FILE}" "${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}" 2>>"${LOG_FILE}"
+  fi
+
+  if [ "${PARAM_DEBUG}"x != "true"x ]; then
+    for fileNmExt in "tar" "tar.xz" "tar.base64"; do
+      removeIfExist "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.${fileNmExt}"
+    done
+  fi
+
+
+}
+
+removeIfExist() {
+  local filePath="${1}"
+  if [ ! -e "${filePath}" ]; then
+    return
+  fi
+  rm -rf "${filePath}" 2>>"${LOG_FILE}"
+}
+
+deleteParentTmpFile() {
+  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
+    removeIfExist "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}"
+  done
+  removeIfExist "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}"
+  removeIfExist "${TARGET_INSTALL_TMP_FILE}"
+
+  for fileNmExt in "tar" "tar.xz" "tar.base64"; do
+    removeIfExist "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.${fileNmExt}"
+  done
+}
+
+#**********************************************************
+# Param
+#**********************************************************
+PARAM_DEBUG=false
+PARAM_RELEASE=false
+#PARAM_VERSION=1.1.0
+PARAM_NAME=euspace
+PARAM_AGENT_PROC=$PARAM_NAME
+PARAM_CONFIG_PATH=
+
+#== 大小写转化,并返回判断结果
+istrcmp() {
+  local s1="$(printf '%s' "${1}" | tr '[:upper:]' '[:lower:]')"
+  local s2="$(printf '%s' "${2}" | tr '[:upper:]' '[:lower:]')"
+  [ "${s1}"x = "${s2}"x ]
+}
+
+isParamTrue() {
+  [ "${1}"x = "1"x ] || [ "${1}"x = "true"x ] || [ "${1}"x = "enable"x ] || [ "${1}"x = "yes"x ]
+}
+
+isParamFalse() {
+  [ "${1}"x = "0"x ] || [ "${1}"x = "false"x ] || [ "${1}"x = "disable"x ] || [ "${1}"x = "no"x ]
+}
+
+#== 获取参数值
+getParamValue() {
+  local paramName="${1}"
+  local input="${2}"
+  local paramNameLength="${#paramName}"
+  paramNameLength=$((paramNameLength + 1))
+
+  local partParam="$(expr substr "${input}" 1 ${paramNameLength})"
+  if ! istrcmp "${partParam}" "${paramName}="; then
+    return 1
+  fi
+
+  local valueSeparator=$((paramNameLength + 1))
+  local value="$(expr substr "${input}" ${valueSeparator} 1000)"
+  if [ -z "${value}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${value}"
+  return 0
+}
+
+#== 获取bool参数
+readBoolParam() {
+  local value=
+  if value="$(getParamValue "${1}" "${2}")"; then
+    if isParamFalse "${value}"; then
+      printf "false"
+      return 0
+    fi
+    if isParamTrue "${value}"; then
+      printf "true"
+      return 0
+    fi
+  fi
+
+  return 1
+}
+
+#== 解析命令行中参数
+parseCommandLineParameters() {
+  while [ $# -gt 0 ]; do
+    local param="${1}"
+    local value=
+
+    if value=$(getParamValue RELEASE "${param}"); then
+      PARAM_RELEASE="${value}"
+      printParamMessage "RELEASE" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue VERSION "${param}"); then
+      PARAM_VERSION="${value}"
+      printParamMessage "VERSION" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue NAME "${param}"); then
+      PARAM_NAME="${value}"
+      printParamMessage "NAME" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue CONFIG "${param}"); then
+      PARAM_CONFIG_PATH="${value}"
+      printParamMessage "CONFIG" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue PROC "${param}"); then
+      PARAM_AGENT_PROC="${value}"
+      printParamMessage "PROC" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(readBoolParam DEBUG "${param}"); then
+      PARAM_DEBUG="${value}"
+      printParamMessage "DEBUG" "${value}"
+      shift
+      continue
+    fi
+
+    if [ "${param}"x = "-h"x ] || [ "${param}"x = "--help"x ]; then
+      displayHelp
+      finishPackage "${EXIT_CODE_OK}"
+    fi
+
+    if [ "${param}"x = "-v"x ] || [ "${param}"x = "--version"x ]; then
+      printf "%s\n" "${AGENT_INSTALLER_VERSION}"
+      finishPackage "${EXIT_CODE_OK}"
+    fi
+
+    toConsoleError "Unrecognized parameter: ${param}"
+
+    displayHelp
+    finishPackage "${EXIT_CODE_INVALID_PARAM}"
+  done
+}
+
+displayHelp() {
+  printf '\n'
+  printf '%s\n' "Usage: "${CURR_FILE_NAME}" [-h] [-v] [NAME=pluginName] [PROC=mainProcess] [RELEASE=true|false] [DEBUG=true|false] [VERSION=1.0]"
+  printf '\n\n'
+
+  local pad=15
+  printf "%-${pad}s%s\n" "-h, --help" "Display this help and exit."
+  printf "%-${pad}s%s\n" "-v, --version" "Print version and exit."
+  printf '\n'
+  printf "%-${pad}s%s\n" "RELEASE" "Default true; Whether to delete the publish parameter in the script."
+  printf "%-${pad}s%s\n" "VERSION" "Configure the ${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME} version."
+  printf "%-${pad}s%s\n" "NAME" "Setting agent name like 'bash ./scripts/package.sh NAME=pluginName PROC=mainProcess'"
+  printf "%-${pad}s%s\n" "PROC" "Setting agent main process name."
+  printf "%-${pad}s%s\n" "DEBUG" "Default false; 1、Debug mode executed script ${CURR_FILE_NAME};"
+  printf "%-${pad}s%s\n" "" "2、Remove the debug log from the scripts (${TARGET_INSTALL_FILE_NAME}、${SERVICE_SCRIPT_FILE}、uninstall.sh)."
+}
+
+#== 完成安装后清理临时目录
+finishPackage() {
+  finishFinally
+  toLogInfo "Installation finished, PID $$, exit code: ${1}."
+  exit "${1}"
+}
+
+printParamMessage() {
+  local paramNm="${1}"
+  local paramValue="${2}"
+  toConsoleInfo "---> Parameter ${paramNm}=${paramValue}."
+}
+
+#**********************************************************
+# SELinux related functions
+#**********************************************************
+#== 修改scripts/smartagent脚本配置信息
+editScriptFileParam() {
+  local key="${1}"
+  local newValue="${2}"
+  local file="${3}"
+
+  local value="$(sed -n "s|^${key}=||p" "${file}" 2>/dev/null)"
+  toConsoleInfo "---> edit ${key}=${value} to ${key}=${newValue}, configFile: ${file}"
+  if [ "${value}" ]; then
+    sed -i "s|^${key}=.*|${key}=${newValue}|" "${file}" 2>/dev/null
+  fi
+}
+
+#== 信号捕获,并执行回调函数
+signalHandler() {
+  local signal="${1}"
+  local callback="${2}"
+  toLogWarn "process received signal: ${signal}"
+  ${callback} "${signal}"
+  exit ${EXIT_CODE_SIGNAL_RECEIVED}
+}
+
+#== 配置信号捕获和回调
+configureSignalHandling() {
+  local callback="${1}"
+  for signal in HUP INT QUIT ABRT ALRM TERM; do
+    #== shellcheck disable=SC2064
+    trap "signalHandler ${signal} ${callback}" ${signal}
+  done
+
+  trap "" PIPE
+}
+
+#**********************************************************
+# main
+#**********************************************************
+main() {
+  mkdir -p "${LOG_DIR}"
+  echo "" >"${LOG_FILE}"
+
+  toConsoleInfo "package script run path: ${SCRIPT_DIR}"
+  toConsoleInfo "package logs path: ${LOG_DIR}"
+
+  chmod +x ${SCRIPT_DIR}/*
+
+  #== 解析命令行参数
+  parseCommandLineParameters "$@"
+  toConsoleInfo "-----params PARAM_RELEASE: ${PARAM_RELEASE}, PARAM_DEBUG: ${PARAM_DEBUG}, PARAM_VERSION: ${PARAM_VERSION}"
+
+  configureSignalHandling "finishFinally"
+
+  #== 设置 package 插件名
+  editScriptFileParam "BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/package.sh"
+  #== 设置 install 插件名
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/install_temp.sh"
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/install_temp.sh"
+  #== 设置 agentctl 插件名(存在时)
+  if [ -f "${SMARTAGENT_DIR}/package_dir/bin/agentctl" ];then
+    editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+    editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+  #== 设置 agentctl 配置文件路径(存在时)
+    editScriptFileParam "readonly AGENT_CONFIG_PATH" "\"${PARAM_CONFIG_PATH}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+  fi
+
+  #== 设置 uninstall 插件名
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/uninstall.sh"
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/uninstall.sh"
+  #== 设置主进程名
+  if [ -n "${PARAM_AGENT_PROC}" ]; then
+    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SCRIPT_DIR}/install_temp.sh"
+    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SCRIPT_DIR}/uninstall.sh"
+    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+  fi
+  buildVersion
+  toConsoleInfo "-----Write release version ${AGENT_INSTALLER_VERSION} to ${SMARTAGENT_DIR}/${INSTALL_VERSION_FILE_NAME} file."
+  echo "${AGENT_INSTALLER_VERSION}">"${SMARTAGENT_DIR}/${INSTALL_VERSION_FILE_NAME}"
+
+  #== 修改uninstall.sh 版本
+  editScriptFileParam "readonly AGENT_INSTALLER_VERSION" "${AGENT_INSTALLER_VERSION}" "${SCRIPT_DIR}/uninstall.sh"
+
+  deleteParentTmpFile
+
+  #== 压缩 并生成安装脚本
+  tarSmartAgent
+}
+
+main "$@"

+ 1116 - 0
dist/aarch64/scripts/uninstall.sh

@@ -0,0 +1,1116 @@
+#!/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 heartbeat"
+  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 "$@"

BIN
dist/aarch64/scripts/xzdec


+ 6 - 0
dist/x86_64/.gitignore

@@ -0,0 +1,6 @@
+.idea
+installer.version
+Cloudwise-euspace-installer*.sh
+logs/*
+package_dir/logs/*.log
+package_dir/runtime/memdump

+ 87 - 0
dist/x86_64/README.md

@@ -0,0 +1,87 @@
+
+## package.sh 介绍
+
+[scripts/package.sh](../../scripts/package.sh) 主要是将 SmartAgent 安装目录下所有内容(脚本无自动去除无用目录或内容功能)压缩,
+通过`base64`编码后写入 [scripts/install_temp.sh](../../scripts/install_temp.sh) 中,
+最终生成安装文件 `cwserveragent-installer-version.sh` (version为SmartSgent版本)。
+
+### 安装帮助
+
+执行命令 `sh scripts/package.sh -h` 即可查看安装帮助详情。详情如下:
+
+```
+Usage: package.sh [-h] [-v] [DEBUG=true|false] [AGENT_VERSION=8.6]
+
+
+-h, --help     Display this help and exit.
+-v, --version  Print version and exit.
+
+RELEASE        Default true; Whether to delete the publish parameter in the script.
+VERSION        Configure the Cloudwise SmartAgent version.
+DEBUG          Default false; 1、Debug mode executed script package.sh;
+               2、Remove the debug log from the scripts (Cloudwise-SmartAgent-Linux-1.2.0.sh、smartagent、uninstall.sh).
+
+```
+
+### smartagent目录结构
+
+打包前目录结构(请保持目录及内容最简)
+```
+smartagent
+├── cwserveragent-installer-1.1.0.sh
+├── bin
+│   ├── CW-ServerAgent
+│   └── safe-rm
+├── conf
+│   └── server-agent.ini
+└── scripts
+    ├── install_temp.sh
+    ├── package.sh
+    ├── cw-serveragent
+    ├── uninstall.sh
+    ├── uninstall_temp.sh
+    └── xzdec
+```
+
+打包后目录结构
+```
+smartagent
+├── cwserveragent-installer-1.1.0.sh
+├── installer.version
+├── bin
+│   ├── CW-ServerAgent
+│   └── safe-rm
+├── conf
+│   └── server-agent.ini
+└── scripts
+    ├── install_temp.sh
+    ├── package.sh
+    ├── cw-serveragent
+    ├── uninstall.sh
+    ├── uninstall_temp.sh
+    └── xzdec
+```
+
+安装后目录结构
+
+```
+├── bin
+│   ├── CW-ServerAgent
+│   └── safe-rm
+├── conf
+│   ├── cwserveragent.conf
+│   ├── installation.conf
+│   └── server-agent.ini
+├── installer.version
+├── logs
+│   └── serveragent
+│       ├── CW-ServerAgent.error.log
+│       ├── CW-ServerAgent.fatal.log
+│       └── CW-ServerAgent.panic.log
+├── runtime
+│   └── .pid
+├── scripts
+│   ├── cw-serveragent
+│   └── uninstall.sh
+└── uninstall.sh
+```

BIN
dist/x86_64/package_dir/agents/NativeAgent/lib/apmAgent.jar


BIN
dist/x86_64/package_dir/agents/NativeAgent/lib/apmCore.jar


BIN
dist/x86_64/package_dir/agents/NativeAgent/lib/apmSpy.jar


BIN
dist/x86_64/package_dir/agents/NativeAgent/lib/libnativeAgent.so


BIN
dist/x86_64/package_dir/agents/NativeAgent/plugins/cloudwise-javacode-plugin-ssl-socket.jar


+ 240 - 0
dist/x86_64/package_dir/bin/agentctl

@@ -0,0 +1,240 @@
+#!/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 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}/current
+#== /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 AGENT_BIN_DIR="${INSTALL_DIR}/bin"
+readonly AGENT_LOG_DIR="${INSTALL_DIR}/logs"
+
+#readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
+#readonly MAIN_CONF_FILE="${AGENT_CONF_DIR}/${AGENT_MAIN_CONF}"
+readonly EXIT_CODE_OK=0
+readonly EXIT_CODE_GENERIC_ERROR=1
+
+#== **********************************************************
+#==  配置重要文件名称
+#== **********************************************************
+readonly AGENT_PROC="euspace"
+readonly AGENT_CONFIG_PATH=""
+
+readonly AGENT_PID_FILE="${INSTALL_DIR}/bin/${AGENT_PROC}.pid"
+
+
+getDaemonPid(){
+    local agent="${1}"
+    #== 约定pid文件
+    local pidFilePath="${AGENT_PID_FILE}"
+    #== 二进制文件绝对路径
+    # shellcheck disable=SC2155
+    local procPath="$(readlink -m "${AGENT_BIN_DIR}/${agent}" 2>&1)"
+    local cmdline
+    local pid
+    #== 查询pid文件
+    if [ -s "${pidFilePath}" ] ; then
+      pid="$(cat "${pidFilePath}" 2>&1)"
+      cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
+      if [ -d "/proc/${pid}" ] && ( [[ ${cmdline} =~ ${procPath} ]] || [[ ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]] ); then
+#        toLogInfo "[${agent}] Find pid by ${pidFilePath} [content:${pid}][cmdline:${cmdline}]"
+          printf '%s' ${pid}
+          return 0
+      else
+        #== 进程绝对路径查询
+#        toLogWarning "[${agent}] Pidfile exist [content:${pid}]. But process not find or not myself. [cmdline:${cmdline}]"
+        if ! pid="$(listProcesses "${agent} pid" "${procPath}|${AGENT_BIN_DIR}/${agent}" "sudo|tail")"; then
+#          toLogWarning "[${agent}] Not find process grep '${procPath}'"
+          return 1
+        fi
+        cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
+        if ! [[ ${cmdline} =~ ${procPath} || ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]]; then
+#            toLogWarning "[${agent}] Find process success. But process not myself. [cmdline:${cmdline}]"
+            return 1
+        fi
+#        toLogInfo "[${agent}] Find pid by process name [${procPath}|${AGENT_BIN_DIR}/${agent}]"
+      fi
+    else
+      #== 进程绝对路径查询
+#      toLogWarning "[${agent}] Pidfile [${pidFilePath}] not find. Use abs path queries."
+      if ! pid="$(listProcesses "${agent} pid" "${procPath}|${AGENT_BIN_DIR}/${agent}" "sudo|tail")"; then
+#        toLogWarning "[${agent}] Not find process by grep '${procPath}'"
+        return 1
+      fi
+      cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
+      if ! [[ ${cmdline} =~ ${procPath} || ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]]; then
+#          toLogWarning "[${agent}] Find process success. But process not myself. [cmdline:${cmdline}]"
+          return 1
+      fi
+#      toLogInfo "[${agent}] Find pid by process name [${procPath}|${AGENT_BIN_DIR}/${agent}]."
+    fi
+
+    printf '%s' ${pid}
+    return 0
+}
+
+listProcesses() {
+  local errorMessage="${1}"
+  local includeRegex="${2}"
+
+  local excludeRegex=" grep"
+  if [ "${3}" ]; then
+    excludeRegex="grep|${3}"
+  fi
+
+#  toLogInfo "#DEBUG== listProcesses command: ps -e -o \"pid,args\" 2>&1 | grep -E "${includeRegex}" | awk '{{ print \$1,\$2 }}' | grep -vE \"${excludeRegex}\""
+  local output
+  if ! output="$(ps -e -o "pid,args" 2>&1 | grep -E "${includeRegex}" | awk '{{ print $1,$2 }}')"; then
+#    toLogError "Failed to get ${errorMessage}, output: ${output}"
+    return 1
+  fi
+
+  local foundProcesses="$(printf '%s' "${output}" | grep -vE "${excludeRegex}")"
+  if [ ! "${foundProcesses}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${foundProcesses}" | awk '{{ print $1 }}'
+  return 0
+}
+
+getAgentPid() {
+  local DAEMONPID="$(getDaemonPid "${AGENT_PROC}")"
+  if [ -z ${DAEMONPID} ]; then
+      return 1
+  fi
+  printf '%s' "${DAEMONPID}"
+
+}
+
+startAgent() {
+  local pid
+  if [ -f "${AGENT_BIN_DIR}/${AGENT_PROC}" ]; then
+    export DISABLE_E2E_TRACING=false
+    export DISABLE_STACK_TRACING=true
+    export SEND=1
+    local params="--listen=0.0.0.0:8123"
+#    if [ -f "/etc/chaosd/pki/ca.crt" ] && [ -f "/etc/chaosd/pki/chaosd.crt" ] && [ -f "/etc/chaosd/pki/chaosd.key" ]; then
+#        params="server  --https-port 31768 --CA=/etc/chaosd/pki/ca.crt --cert=/etc/chaosd/pki/chaosd.crt --key=/etc/chaosd/pki/chaosd.key"
+#    fi
+    pid=$(nohup ${AGENT_BIN_DIR}/${AGENT_PROC} ${params}>>"${AGENT_LOG_DIR}/service.log" 2>&1 & echo $!)
+    echo ${pid} > "${AGENT_PID_FILE}"
+  else
+    echo "${AGENT_BIN_DIR}/${AGENT_PROC} not exist."
+    exit "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+}
+
+agentStart() {
+  local agentPid
+  if agentPid="$(getAgentPid)"; then
+    echo "${BRAND_AGENT_PRODUCT_NAME} is running. Agent pid: ${agentPid}."
+    return
+  fi
+
+  startAgent
+	local exitCode=$?
+	if [ "${exitCode}" -ne 0 ]; then
+		echo "Failed to start ${BRAND_AGENT_PRODUCT_NAME} service."
+		exit "${EXIT_CODE_GENERIC_ERROR}"
+	fi
+
+  if agentPid="$(getAgentPid)"; then
+    echo "${BRAND_AGENT_PRODUCT_NAME} service started. Agent pid: ${agentPid}."
+  else
+    echo "${BRAND_AGENT_PRODUCT_NAME} not start!"
+    exit "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+agentStop() {
+  local agentPid
+  if agentPid="$(getAgentPid)"; then
+#    ${AGENT_BIN_DIR}/stop.sh ${agentPid}
+    kill ${agentPid}
+    echo "${BRAND_AGENT_PRODUCT_NAME} service stopped success."
+    cat /dev/null > "${AGENT_PID_FILE}"
+  else
+      echo "${BRAND_AGENT_PRODUCT_NAME} is stopped. service stopped success."
+  fi
+}
+
+agentRestart(){
+  agentStop
+  sleep 1
+  agentStart
+}
+
+agentStatus() {
+  local agentPid
+	local statusOutput
+  if agentPid="$(getAgentPid)"; then
+    statusOutput="${BRAND_AGENT_PRODUCT_NAME} is running. ${BRAND_AGENT_PRODUCT_NAME} pid: ${agentPid}"
+  else
+    statusOutput="${BRAND_AGENT_PRODUCT_NAME} is not running. ${BRAND_AGENT_PRODUCT_NAME} process not found or stop."
+  fi
+
+  echo "${statusOutput}"
+}
+
+info() {
+  local agentPid="$(getAgentPid)"
+  local version=$(cat "${INSTALL_DIR}/installer.version" | tr -d '\n')
+  printf '{"pid":%d,"version":"%s","agent_id":"%s","config":"%s","pipe": true}' "${agentPid}" "${version}" "${BRAND_PRODUCT_NAME_LOWER}" "${AGENT_CONFIG_PATH}"
+}
+
+################################################################################
+#
+# Script start
+#
+################################################################################
+
+main() {
+  case "$1" in
+  start)
+    agentStart
+    ;;
+  stop)
+    agentStop
+    ;;
+  restart)
+    agentRestart
+    ;;
+  status)
+    agentStatus
+    ;;
+  info)
+    info
+    ;;
+  *)
+    toConsoleInfo "usage: $0 {start|stop|restart|status}"
+    ;;
+  esac
+
+  exit "${EXIT_CODE_OK}"
+}
+
+main "$@"

+ 0 - 0
dist/x86_64/package_dir/conf/.gitkeep


BIN
dist/x86_64/package_dir/libs/amd64/jvm/cwlibnet.so


BIN
dist/x86_64/package_dir/libs/arm64/jvm/cwlibnet.so


+ 0 - 0
dist/x86_64/package_dir/logs/.gitkeep


+ 0 - 0
dist/x86_64/package_dir/runtime/.gitkeep


BIN
dist/x86_64/package_dir/scripts/cwjattach


+ 2954 - 0
dist/x86_64/scripts/install_temp.sh

@@ -0,0 +1,2954 @@
+#!/bin/bash
+#== AIX(Advanced Interactive eXecutive)是IBM基于AT&T Unix System V开发的一套类UNIX操作系统,运行在IBM专有的Power系列芯片设计的小型机硬件系统之上
+#== 以【#== 】开头的注释会在打包时删除
+#DEBUG== 以【#DEBUG== 】开头的注释会在调试打包时保留,正式打包时删除
+
+
+#==脚本执行中遇到不存在的变量就报错
+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="cloudwise"
+
+readonly AIX_DF_SPECIFIC_FLAG=
+readonly CONF_LD_PRELOAD=
+
+PARAM_DISABLE_SYSTEM_LOGS_ACCESS=
+
+#== 安装包版本项
+readonly AGENT_BUILD_DATE=25.09.2020
+readonly AGENT_INSTALLER_VERSION=1.2.0
+readonly AGENT_BUILD_DATE_INFO=""
+readonly AGENT_BUILD_TAG=""
+readonly AGENT_BUILD_UPLOADER=""
+#== 安装包版本项
+
+#== **********************************************************
+#==  配置重要文件名称
+#== **********************************************************
+#== CW-ServerAgent
+readonly AGENT_PROC="euspace"
+#== **********************************************************
+#==  配置目录
+#== **********************************************************
+readonly INSTALL_BASE=/opt
+#== /opt/cloudwise/oneagent/agents 目录
+readonly BASE_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents
+#== cloudwise/oneagent/agents/chaosd
+readonly INSTALL_FOLDER=${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents/${BRAND_PRODUCT_NAME_LOWER}
+#== cloudwise/oneagent/agents/chaosd/version
+readonly INSTALL_VERSION_FOLDER=${INSTALL_FOLDER}/${AGENT_INSTALLER_VERSION}
+#== /opt/cloudwise/oneagent/agents/chaosd/version
+readonly INSTALL_DIR=${INSTALL_BASE}/${INSTALL_VERSION_FOLDER}
+#== /opt/cloudwise/oneagent/agents/chaosd
+readonly AGENT_BASE_DIR=${INSTALL_BASE}/${INSTALL_FOLDER}
+
+#== /opt/cloudwise/cwserveragent/conf
+readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/scripts
+readonly AGENT_SCRIPTS_DIR="${INSTALL_DIR}/scripts"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/runtime
+readonly AGENT_RUNTIME_DIR="${INSTALL_DIR}/runtime"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/bin
+readonly AGENT_BIN_DIR="${INSTALL_DIR}/bin"
+#== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/lib
+#== readonly AGENT_LIB_DIR="${INSTALL_DIR}/lib"
+
+
+readonly AGENTS_BASE_DIR="${INSTALL_DIR}/agents"
+
+readonly META_BASE_DIR="${INSTALL_DIR}/meta"
+
+readonly LOG_DIR_NAME="logs"
+#== /opt/cloudwise/cwserveragent/logs
+readonly LOG_DIR=${INSTALL_DIR}/${LOG_DIR_NAME}
+
+#== /var/log/cloudwise/cwserveragent/
+readonly INSTALLER_LOG_DIR="/var/log/${INSTALL_FOLDER}"
+
+
+#== server-agent.ini
+#== hostId文件
+readonly INSTALLER_CONF_FILE_NAME="installation.conf"
+#== 部署在容器内的状态信息
+readonly INSTALLER_CONF_FILE="${AGENT_CONF_DIR}/${INSTALLER_CONF_FILE_NAME}"
+
+#== 【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/"
+
+#== 【0】=【退出码】执行成功
+readonly EXIT_CODE_OK=0
+readonly EXIT_CODE_GENERIC_ERROR=1
+readonly EXIT_CODE_NOT_ENOUGH_SPACE=6
+readonly EXIT_CODE_NOT_ENOUGH_MEMORY=7
+#== 【0】=无效参数
+readonly EXIT_CODE_INVALID_PARAM=8
+readonly EXIT_CODE_INSUFFICIENT_PERMISSIONS=9
+
+#== 【退出码】接收信号
+readonly EXIT_CODE_SIGNAL_RECEIVED=12
+readonly EXIT_CODE_ANOTHER_INSTALLER_RUNNING=13
+readonly EXIT_CODE_CORRUPTED_PACKAGE=16
+#== 【退出码】管理系统环境变量配置
+readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
+readonly EXIT_CODE_UNSUPPORTED_DOWNGRADE=18
+readonly EXIT_CODE_OS_NOT_SUPPORTED=19
+
+readonly EXTERNAL_TAR_SIZE=233820160
+readonly ARTIFACTS_SIZE=953271934
+#**********************************************************
+# Logs
+#**********************************************************
+toLogFile() {
+  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() {
+  toLogFile "[INFO]" "$@"
+}
+
+toLogWarn() {
+  toLogFile "[WARN]" "$@"
+}
+
+toLogError() {
+  toLogFile "[ERROR]" "$@"
+}
+
+toLogAdaptive() {
+  local success="${1}"
+  shift
+  if [ "${success}" -eq 0 ]; then
+    toLogInfo "$@"
+  else
+    toLogError "$@"
+  fi
+}
+
+toConsoleInfo() {
+  toConsoleOnly "$@"
+  toLogInfo "$@"
+}
+
+toConsoleWarn() {
+  toConsoleOnly "Warn:" "$@"
+  toLogWarn "$@"
+} >&2
+
+toConsoleError() {
+  toConsoleOnly "Error:" "$@"
+  toLogError "$@"
+} >&2
+
+#== 【0】【3】【4】=创建不存在的目录,并设置权限
+createDirIfNotExistAndSetRights() {
+  local dir="${1}"
+  local rights="${2}"
+
+  toConsoleInfo "#DEBUG== createDirIfNotExistAndSetRights --- ${rights} --- ${dir}"
+  if [ ! -d "${dir}" ]; then
+    toLogInfo "Creating directory ${dir} with rights ${rights}"
+    local message
+    if ! message="$(mkdir -p "${dir}" 2>&1)"; then
+      toConsoleWarn "Cannot create ${dir} directory."
+      toLogWarn "Error message: ${message}"
+      return 1
+    fi
+  fi
+
+  if ! message="$(chmod "${rights}" "${dir}" 2>&1)"; then
+    toConsoleWarn "Cannot change permisions of ${dir} directory to ${rights}."
+    toLogWarn "Error message: ${message}"
+    return 1
+  fi
+
+  return 0
+}
+
+createCurrentVersionSymlink() {
+	toLogInfo "Creating symlink to current version..."
+
+	local currentVersionLink="${AGENT_BASE_DIR}/current"
+	local tempLink="${currentVersionLink}.tmp"
+
+	if ! commandErrorWrapper ln -s "${AGENT_INSTALLER_VERSION}" "${tempLink}"; then
+		toLogError "Failed to create current version link"
+		return
+	fi
+
+	if ! commandErrorWrapper arch_moveReplaceTarget "${tempLink}" "${currentVersionLink}"; then
+		toLogError "Failed to set up current version link"
+		commandErrorWrapper rm -f "${tempLink}"
+		return
+	fi
+
+	toLogInfo "Current version link created: ${currentVersionLink} -> ${AGENT_INSTALLER_VERSION}"
+}
+
+#== 【0】=创建日志目录及日志文件installation_$$.log
+createLogDirsIfMissing() {
+  createDirIfNotExistAndSetRights "${INSTALL_BASE}" u+rwx,g+rx,o+rx
+  createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" u+rwx,g+rx,o+rx
+  #== agents根目录
+  createDirIfNotExistAndSetRights "${AGENT_BASE_DIR}" 1775
+  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
+#**********************************************************
+
+#== 【5】=获取系统发型版本
+getOsReleasePath() {
+	local osReleasePath="/etc/os-release"
+	if [ ! -f "${osReleasePath}" ]; then
+		osReleasePath="/usr/lib/os-release"
+	fi
+
+	printf '%s' "${osReleasePath}"
+}
+
+parseOsReleaseFile() {
+	local osReleasePath="$(getOsReleasePath)"
+
+	#shellcheck disable=SC1090
+	. "${osReleasePath}"
+	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)"
+	elif printf '%s' "${distrib}" | grep -iq "fedora" && [ "${VARIANT_ID-}" = "coreos" ]; then
+		distrib="${distrib} CoreOS"
+	fi
+
+	printf '%s %s' "${distrib}" "${version}"
+}
+
+#== 【5】=获取系统发型版本
+detectLinuxDistribution() {
+	if [ -f /etc/oracle-release ]; then
+		cat /etc/oracle-release
+	elif [ -f /etc/fedora-release ]; then
+		if [ -f "$(getOsReleasePath)" ]; then
+			(
+				parseOsReleaseFile
+			)
+		else
+			cat /etc/fedora-release
+		fi
+	elif [ -f /etc/redhat-release ]; then
+		cat /etc/redhat-release
+	elif [ -f "$(getOsReleasePath)" ]; then
+		(
+			parseOsReleaseFile
+		)
+	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
+}
+
+#== 【3】=检查系统init (INIT_SYSTEM、INIT_SYSTEM_VERSION)
+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}
+      toLogWarn "${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)"
+}
+
+#== 【3】=设置系统初始化脚本目录
+setLocationOfScripts() {
+  toLogInfo "Determining location of scripts..."
+
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSTEMD}"x ] || [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    #== /opt/cloudwise/cwserveragent/scripts
+    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 scripts ${INIT_DIR}"
+  return 0
+}
+
+#== 【0】=检查系统结构(X86_64\IA64\X86)
+detectArchitecture() {
+  local detected_arch=
+  if isAvailable arch; then
+    #== arch指令主要用于显示当前主机的硬件结构类型,查询结果与uname一致,我们可以看到它输出的结果有:i386、i486、mips、alpha等
+    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
+#**********************************************************
+
+#== 【1】【4】【5】【6】=获取 agent (64\32)位数lib目录(""或lib64)
+getBinariesFolderByBitness() {
+  local bitness="${1}"
+  if [ "${bitness}" -eq 32 ]; then
+    bitness=""
+  fi
+  printf 'lib%s' "${bitness}"
+}
+
+#== 【1】【2】【5】【6】=获取 agent tools/lib64/smartagentctl 路径
+#== getAgentCtlBinPath
+
+#== 【1】【4】【5】【6】=获取 agent 64位数lib路径(lib64/installaction)
+#== getAgentInstallActionPath
+
+#== 【5】【6】=获取OS bin配置路径 /opt/cloudwise/cwserveragent/lib64/cloudwiseosconfig
+getOsConfigBinPath() {
+  printf "%s" "${INSTALL_DIR}/lib64/${AGENT_OS_CONFIG_BIN}"
+}
+
+#== 【5】=设置agent进程可用
+setProcessAgentEnabled() {
+  local enabled="${1}"
+  toLogInfo "Setting process agent enabled: ${enabled}..."
+  local changeStatus=
+  #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --set-process-agent-enabled
+  changeStatus=$("$(getAgentInstallActionPath)" --set-process-agent-enabled "${enabled}" 2>&1)
+  toLogAdaptive $? "Process agent enable(${enabled}) status: ${changeStatus}"
+}
+
+#== 【1】【4】【5】【6】=获取命令执行错误信息,并写日志
+commandErrorWrapper() {
+  local command="${*}"
+  local errorFile="/tmp/smartagent_commanderror_$$"
+
+  ${command} 2>"${errorFile}"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 0 ]; then
+    toLogWarn "Command '${command}' failed, return code: ${returnCode}, message: $(cat "${errorFile}")"
+  fi
+
+  rm -f "${errorFile}"
+
+  return ${returnCode}
+}
+
+#== 【3】=是否独立的namespace
+isNamespaceIsolated() {
+  local pid="${1}"
+  local namespace="${2}"
+  local initNamespaceId
+  local processNamespaceId
+  initNamespaceId="$(readlink "/proc/1/ns/${namespace}" 2>/dev/null | tr -dc '0-9')"
+  processNamespaceId="$(readlink "/proc/${pid}/ns/${namespace}" 2>/dev/null | tr -dc '0-9')"
+
+  if [ ! "${initNamespaceId}" ] || [ ! "${processNamespaceId}" ]; then
+    toLogInfo "Link to /proc/*/ns/${namespace} does not exist"
+    printf 'error'
+    return
+  fi
+
+  if [ "${initNamespaceId}"x != "${processNamespaceId}"x ]; then
+    printf 'true'
+  else
+    printf 'false'
+  fi
+}
+
+#== 【0】=检查是否root
+checkRootAccess() {
+  toConsoleInfo "Checking root privileges..."
+
+  if [ "$(id -u)"x != "0"x ]; then
+    toConsoleError "NOT OK"
+    return 1
+  fi
+
+  toConsoleInfo "OK"
+  return 0
+}
+
+#== 【3】=删除存在的路径
+removeIfExists() {
+  local pathToRemove="${1}"
+  if [ ! -e "${pathToRemove}" ]; then
+    toLogInfo "${pathToRemove} does not exist, skipping removal"
+    return
+  fi
+
+  local output
+  if ! output="$(rm -rf "${pathToRemove}" 2>&1)"; then
+    toLogWarn "Failed to remove ${pathToRemove}: ${output}"
+  fi
+}
+
+#**********************************************************
+# SELinux related functions
+#**********************************************************
+
+#== 【5】【6】=执行 systemctl 命令
+executeSystemctlCommand() {
+  local command="${1}"
+  local unit="${2}"
+
+  if [ "$(id -u)" != 0 ]; then
+    #== 执行使用 os config bin
+    executeUsingOsConfigBin "${command}" "${unit}"
+    return $?
+  fi
+
+  local output=
+  #== shellcheck disable=SC2086
+  #== 执行 systemctl 命令
+  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}"
+
+#== 【6】=运行初始化命令(通过 service 方式 或 直接运行可执行命令)
+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
+  output="$("${command}" "${parameters}" 2>&1)"
+  exitCode=$?
+  toLogAdaptive ${exitCode} "Executed ${command} ${parameters}, exitCode = ${exitCode}, output: ${output}"
+  return ${exitCode}
+}
+
+#== 【0】=信号捕获,并执行回调函数
+signalHandler() {
+  local signal="${1}"
+  local callback="${2}"
+  toLogWarn "process received signal: ${signal}"
+  ${callback}
+  exit ${EXIT_CODE_SIGNAL_RECEIVED}
+}
+
+#== 【0】=配置信号捕获和回调
+configureSignalHandling() {
+  local callback="${1}"
+  for signal in HUP INT QUIT ABRT ALRM TERM; do
+    # shellcheck disable=SC2064
+    trap "signalHandler '${signal}' '${callback}'" ${signal}
+  done
+
+  trap "" PIPE
+}
+
+#== 【0】删除权限
+removeSecretsFromString() {
+  printf "%s" "$*" | sed 's#\(LICENSE=\)[[:alnum:]]\{16\}#\1***#'
+}
+
+#== 【3】【5】=检查目录写权限
+testWriteAccessToDir() {
+  local errorFile="/tmp/smartagent_commandError_$$"
+  local dir="${1}"
+  local tmpfilename
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; 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}")"
+    rm -f "${errorFile}"
+    return 1
+  fi
+
+  rm -f "${tmpfilename}" "${errorFile}"
+  return 0
+}
+
+#== 【0】=设置PATH
+setPATH() {
+  local prependToPATH="/usr/sbin:/usr/bin:/sbin:/bin"
+  if [ "${PATH}" ]; then
+    PATH=${prependToPATH}:${PATH}
+  else
+    PATH=${prependToPATH}
+  fi
+}
+
+#== 【5】【6】=是否非root权限
+isNonRootModeEnabled() {
+  #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-drop-root-privileges
+  local output
+  output="$(getValueFromConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "${LEGACY_AGENT_CONF_FILE}" "${PARAM_NON_ROOT_MODE}")"
+  printf '%s' "${output}" | grep -qE "(true|no_ambient)"
+}
+
+#== 【5】=自动启动工具
+runAutostartAddingTool() {
+  local prefix="${1}"
+  local file="${2}"
+  local suffix="${3}"
+  local output
+
+  local command="${prefix} ${file} ${suffix}"
+  toLogInfo "Executing ${command}"
+  output="$(${command} 2>&1)"
+  local status=$?
+  if [ "${output}" ]; then
+    toLogAdaptive ${status} "${output}"
+  fi
+
+  return ${status}
+}
+
+#== 【0】【5】=查找软链接真实地址(通过ls命令)
+readLinkFromLs() {
+  local path="${1}"
+  local result="${path}"
+  local lsOutput
+  local parsedLinkTarget
+  lsOutput="$(ls -dl "${path}" 2>/dev/null)"
+  if printf '%s' "${lsOutput}" | grep -q " -> "; then
+    parsedLinkTarget="$(printf '%s' "${lsOutput}" | sed 's|^.* -> ||')"
+    if [ "${parsedLinkTarget}" ]; then
+      result="${parsedLinkTarget}"
+    else
+      toLogWarn "Failed to parse ls output '${lsOutput}'"
+    fi
+  fi
+  printf '%s' "${result}"
+}
+
+#== 【0】【5】=查找软链接真实地址(通过readlink 或 ls 命令)
+readLink() {
+  local args=-e
+  local path="${1}"
+  if [ "${2}" ]; then
+    args="${1}"
+    path="${2}"
+  fi
+
+  (
+    if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+      path="${PATH}:/opt/freeware/bin"
+    fi
+
+    #== 通过 readlink 命令查找地址
+    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
+  )
+}
+
+#== 【0】【3】【4】【5】【6】=检查命令是否有效/是否存在
+isAvailable() {
+  command -v "${1}" >/dev/null 2>&1
+}
+
+#== 【0】【1】【3】【5】=读取配置文件配置参数信息
+getValueFromConfigFile() {
+  local key="${1}"
+  local configFile="${2}"
+  local defaultValue="${3}"
+  local value
+  value="$(sed -n "s|^${key}=||p" "${configFile}" 2>/dev/null)"
+
+  if [ "${value}" ]; then
+    printf '%s' "${value}"
+  else
+    printf '%s' "${defaultValue}"
+  fi
+}
+
+#== 【1】【5】=删除配置文件中配置
+removeValueFromConfigFile() {
+  local key="${1}"
+  local configFile="${2}"
+  local output
+  if ! output="$(cp -p "${configFile}" "${configFile}.tmp" 2>&1)"; then
+    toLogWarn "Unable to initialize ${configFile}.tmp file using source file, privileges and ownership will not be preserved: ${output}"
+  fi
+
+  if sed "/^${key}/d" "${configFile}" >"${configFile}.tmp"; then
+    mv -f "${configFile}.tmp" "${configFile}"
+  else
+    toLogWarn "Failed to remove ${key} from ${configFile}"
+    rm -f "${configFile}.tmp"
+  fi
+}
+
+#== 写配置到配置文件信息
+writeParamToConfigFile() {
+  local key="${1}"
+  local newValue="${2}"
+  local configFile="${3}"
+  local value
+  value="$(sed -n "s|^${key}=||p" "${configFile}" 2>/dev/null)"
+  toConsoleInfo "#DEBUG== writeParamToConfigFile --> edit ${key}=${value} to ${key}=${newValue}, configFile: ${configFile}"
+  if [ "${value}" ]; then
+    sed -i "s|^${key}=.*|${key}=${newValue}|" "${configFile}" 2>/dev/null
+  else
+    echo "${key}=${newValue}" >>"${configFile}" 2>/dev/null
+  fi
+}
+
+writeContentToConfigFile() {
+  local newValue="${1}"
+  local configFile="${2}"
+  toConsoleInfo "#DEBUG== writeContentToConfigFile --> edit ${newValue}, configFile: ${configFile}"
+
+  echo "${newValue}" > "${configFile}" 2>/dev/null
+}
+
+#== 修改scripts/smartagent脚本配置信息
+editScriptFileParam() {
+  local key="${1}"
+  local newValue="${2}"
+  local file="${3}"
+  local value
+  value="$(sed -n "s|^${key}=||p" "${file}" 2>/dev/null)"
+  toConsoleInfo "#DEBUG== editScriptFileParam --> edit ${key}=${value} to ${key}=${newValue}, configFile: ${file}"
+  if [ "${value}" ]; then
+    sed -i "s|^${key}=.*|${key}=${newValue}|" "${file}" 2>/dev/null
+  fi
+}
+
+#== 【0】=是否存在多个同时安装操作【通过判断 INSTALLER_LOCK_FILE 】
+isAnotherInstallationRunning() {
+  if [ ! -f "${INSTALLER_LOCK_FILE}" ]; then
+    return 1
+  fi
+  local pidFromLockFile
+  local nameFromLockFile
+  pidFromLockFile="$(head -n 1 "${INSTALLER_LOCK_FILE}")"
+  nameFromLockFile="$(tail -n 1 "${INSTALLER_LOCK_FILE}")"
+  if [ "$(wc -l <"${INSTALLER_LOCK_FILE}")" -ne 2 ] || [ -z "${pidFromLockFile}" ] || [ -z "${nameFromLockFile}" ]; then
+    toConsoleWarn "Installation lock file ${INSTALLER_LOCK_FILE} is damaged, skipping uniqueness check."
+    toConsoleWarn "Lock file contents: '$(cat ${INSTALLER_LOCK_FILE})'"
+    return 1
+  fi
+
+  #== shellcheck disable=SC2009
+  #== 获取正在执行安装的进程信息
+  local foundProcesses
+  foundProcesses="$(pgrep -f "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_DIR}"; then
+      errorMessage="${errorMessage} (AutoUpdate is in progress)"
+    fi
+
+    toConsoleError "${errorMessage}, PID ${pidFromLockFile}. Exiting."
+    return 0
+  fi
+
+  toConsoleInfo "Lock file exists but corresponding installation process does not run, contents of lock file: ${pidFromLockFile}, ${nameFromLockFile}."
+  return 1
+}
+
+#== 【0】=创建安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+createInstallationLockFile() {
+  printf '%s\n%s\n' "$$" "$0" >"${INSTALLER_LOCK_FILE}" 2>/dev/null
+}
+
+#== 【0】【6】删除安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+removeInstallationLockFile() {
+  toLogInfo "Removing installation lock file."
+  rm -f "${INSTALLER_LOCK_FILE}"
+}
+
+#== 【0】基础启动日志信息
+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)"
+}
+
+#== 解压文件编码
+readonly UNPACK_BINARY=base64
+#== 解压文件编码参数
+readonly UNPACK_BINARY_ARGS="-di"
+
+readonly ARCH_ARCH="X86"
+
+#== 【0】=检查系统指令集(X86_64\IA64\X86)
+arch_checkArchitectureCompatibility() {
+  #== 【0】=检查系统结构(X86_64)
+  local arch
+  arch="$(detectArchitecture)"
+  if [ "${arch}"x = "X86_64"x ] || [ "${arch}"x = "IA64"x ]; 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}"x = "X86_64"x ] || [ "${arch}"x = "AARCH64"x ]
+}
+
+#== 【5】=获取 lib 目录
+arch_getLibMacro() {
+  local libMacro=""
+  if [ "${SYSTEM_LIB32}" ]; then
+    #== shellcheck disable=SC2016
+    libMacro="/${LIB}"
+  fi
+  printf "%s" "${libMacro}"
+}
+#== 'timeout' requires gnu-coreutils8, i.e. it is not available on RHEL5, that's why we need this utility function
+#== 【3】【5】=执行命令超时配置
+
+#== 【0】【3】=获取文件权限信息
+arch_getAccessRights() {
+  stat --format='%A' "${1}"
+}
+
+#== 【4】=替换目录
+arch_moveReplaceTarget() {
+  local source="${1}"
+  local target="${2}"
+  mv -fT "${source}" "${target}"
+}
+
+
+#== xz 压缩包文件名 Cloudwise-SmartAgent
+readonly INTERNAL_TAR_FILE_NAME=${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}.tar.xz
+
+#== -安装日志: installation-{timestamp}.log,如,installation-20220601110912.log
+readonly LOG_FILE="${INSTALLER_LOG_DIR}/installation-$(date -u +"%Y%m%d%H%M%S").log"
+#readonly LOG_FILE="${INSTALLER_LOG_DIR}/installation_$$.log"
+
+
+
+#== 【临时目录】安装临时目录
+readonly TMP_DIR=${INSTALL_DIR}_install_$$
+#== 【临时目录】解压缓存目录
+readonly UNPACK_CACHE=${BASE_INSTALL_DIR}/unpack_cache
+#== 【临时目录】从sh文件读取压缩文件 tarfile_$$.base64
+readonly EXTERNAL_TAR_FILE=${BASE_INSTALL_DIR}/tarfile_$$.base64
+#== 【临时目录】xz 压缩包文件
+readonly INTERNAL_TAR_FILE=${INSTALL_DIR}/${INTERNAL_TAR_FILE_NAME}
+
+#== 【0】=
+readonly INSTALLER_FILE=${0}
+#== 旧配置文件
+readonly LEGACY_AGENT_CONF_FILE="${AGENT_CONF_DIR}/${BRAND_PRODUCT_NAME_LOWER}.conf"
+
+#== 【0】=
+readonly LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS=50
+
+#== 【0】=
+readonly HELP_URL=""
+
+readonly CONF_FIELD_NM_DATA_SERVER="DataServer"
+readonly CONF_FIELD_NM_CONFIG_SERVER="ConfigServer"
+readonly CONF_FIELD_NM_LICENSE="License"
+readonly CONF_FIELD_NM_JSON_CONF="JSON_CONF"
+readonly CONF_FIELD_NM_USER="User"
+readonly CONF_FIELD_NM_GROUP="Group"
+readonly CONF_FIELD_NM_DATA_STORAGE="DataStorage"
+readonly CONF_FIELD_NM_NON_ROOT_MODE="NonRootMode"
+
+
+#== 配置默认用户权限
+readonly BASE_OMNI_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}
+readonly BASE_OMNI_INSTALL_CONF_DIR=${BASE_OMNI_INSTALL_DIR}/conf/installation.conf
+BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${BASE_OMNI_INSTALL_CONF_DIR}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME_CLOUDWISE}")"
+
+#== Those are read from params section appended to installer by the server
+#== 【0】=【参数】数据服务地址
+PARAM_DATA_SERVER=
+#== 【0】=【参数】配置服务地址
+PARAM_CONFIG_SERVER=
+#== 【0】=【参数】license
+PARAM_LICENSE=
+
+PARAM_JSON_CONF=
+
+#== 【0】=【参数】安装路径
+PARAM_INSTALL_DIR=${INSTALL_DIR}
+#== 【0】=【参数】用户
+PARAM_USER=
+#== 【0】=【参数】用户组
+PARAM_GROUP=
+#== 【0】=【参数】非root模式
+PARAM_NON_ROOT_MODE=true
+
+PARAM_USER_LOGIN=false
+
+#== 【0】=【参数】不允许root回退
+PARAM_DISABLE_ROOT_FALLBACK=false
+#== 【0】=【参数】数据存储目录
+PARAM_DATA_STORAGE=
+#== 【0】=【参数】通过容器部署
+#== PARAM_INTERNAL_DEPLOYED_VIA_CONTAINER=false
+#== 【0】=【参数】跳过SELinux策略安装
+#== PARAM_INTERNAL_SKIP_SELINUX_POLICY_INSTALLER=false
+#== 【0】=【参数】是否使用解压缓存
+PARAM_INTERNAL_USE_UNPACK_CACHE=false
+#== 【0】=【参数】是否不使用 dump
+#== PARAM_INTERNAL_DISABLE_DUMPPROC=
+#== 【0】=【参数】是否跳过非root检查
+PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK=false
+#== 【0】【1】=【参数】额外的配置
+#== PARAM_INTERNAL_PASS_THROUGH_SETTERS=
+#== 【0】=检查是否降级安装
+SKIP_DOWNGRADE_CHECK=false
+
+SKIP_PRIVILEGES_CHECK=false
+
+#== 自定义字符串参数
+PARAM_TEST=
+#== 自定义字BOOL参数
+PARAM_BOOL=
+
+#== 【0】=常规日志
+initializeLog() {
+  toConsoleInfo "Installation started, version ${AGENT_INSTALLER_VERSION}, build date: ${AGENT_BUILD_DATE}, PID $$."
+  toLogInfo "Started from: ${INSTALLER_FILE}"
+
+  if [ -f /proc/version ]; then
+    toLogInfo "System version: $(cat /proc/version)"
+  else
+    toLogInfo "System version: $(uname -a)"
+  fi
+
+  toLogInfo "Path: ${PATH}"
+  toLogInfo "INSTALL_DIR: ${INSTALL_DIR}"
+  toLogInfo "Resolved installation path: $(readLink -e "${INSTALL_DIR}" 2>/dev/null)"
+  logBasicStartupInformation "${@}"
+}
+
+#**********************************************************
+# Signing related stuff
+#**********************************************************
+#== 【0】【4】=通过占位分割读取位置
+locateDelimiter() {
+  #== 占位符
+  local delimiter="${1}"
+  #== 从文件结尾读取行数
+  local linesToReadFromEnd="${2}"
+  local linesCount
+  local offset
+  if [ "${linesToReadFromEnd}" ]; then
+    #== 文件总行数n(实际行数=n+1)
+    linesCount="$(wc -l "${INSTALLER_FILE}" | awk '{print $1}')"
+    #== 从后往前读取【linesToReadFromEnd】行
+    offset="$(tail -n"${linesToReadFromEnd}" "${INSTALLER_FILE}" 2>/dev/null | awk '/^'"${delimiter}"'/ { print NR; exit }')"
+    if [ -n "${offset}" ]; then
+      printf "%d" "$((linesCount - linesToReadFromEnd + offset))"
+    fi
+  else
+    #== 读取占位符所在行(实际行数=n+1)
+    awk '/^'"${delimiter}"'/ { print NR; exit }' "${INSTALLER_FILE}"
+  fi
+}
+
+#== 【0】=从指定行范围读取配置参数
+readParam() {
+  local paramName="${1}"
+  local paramsSectionBeggining="${2}"
+  local paramsSectionEnd="${3}"
+
+  sed -n "${paramsSectionBeggining},${paramsSectionEnd} s/^${paramName}=//p" "${INSTALLER_FILE}"
+}
+
+#== 【0】=读取以【----PARAMETERS】开始到 【----PARAMETERS--】之间的参数
+readParamsSection() {
+  local sectionName="----PARAMETERS"
+  local begin
+  local end
+  begin=$(locateDelimiter "${sectionName}" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})
+  end=$(locateDelimiter "${sectionName}--" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})
+
+  if [ -z "${begin}" ] || [ -z "${end}" ]; then
+    return
+  fi
+  #== 从指定行范围读取配置参数
+  local value
+  if value="$(readParam PARAM_DATA_SERVER "${begin}" "${end}")"; then
+    PARAM_DATA_SERVER="${value}"
+  fi
+  if value="$(readParam PARAM_CONFIG_SERVER "${begin}" "${end}")"; then
+    PARAM_CONFIG_SERVER="${value}"
+  fi
+  if value="$(readParam PARAM_LICENSE "${begin}" "${end}")"; then
+    PARAM_LICENSE="${value}"
+  fi
+
+  if value="$(readParam PARAM_JSON_CONF "${begin}" "${end}")"; then
+    PARAM_JSON_CONF="${value}"
+  fi
+
+  if value="$(readParam PARAM_USER "${begin}" "${end}")"; then
+    PARAM_USER="${value}"
+  fi
+  if value="$(readParam PARAM_GROUP "${begin}" "${end}")"; then
+    PARAM_GROUP="${value}"
+  fi
+  if value="$(readParam PARAM_NON_ROOT_MODE "${begin}" "${end}")"; then
+    if value="$(getBoolParam "${value}")"; then
+      PARAM_NON_ROOT_MODE="${value}"
+    fi
+  fi
+
+  if value="$(readParam PARAM_USER_LOGIN "${begin}" "${end}")"; then
+    if value="$(getBoolParam "${value}")"; then
+      PARAM_USER_LOGIN="${value}"
+    fi
+  fi
+  toConsoleInfo "#DEBUG== install sh params, DATA_SERVER: ${PARAM_DATA_SERVER}, PARAM_CONFIG_SERVER: ${PARAM_CONFIG_SERVER}, PARAM_LICENSE:${PARAM_LICENSE}"
+  toConsoleInfo "#DEBUG== install sh params, PARAM_USER: ${PARAM_USER}, PARAM_GROUP: ${PARAM_GROUP}, PARAM_USER_LOGIN: ${PARAM_USER_LOGIN}, PARAM_NON_ROOT_MODE:${PARAM_NON_ROOT_MODE}"
+}
+
+#== 【0】【6】=清空安装临时文件
+#== ${INSTALL_DIR}_install_$$
+#== EXTERNAL_TAR_FILE=${INSTALL_DIR}/tarfile_$$.base64
+#== ${INSTALL_DIR}/Dynatrace-OneAgent.tar.xz
+#== ${INSTALL_DIR}/xzdec
+#== /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+cleanInstallationTemporaryFiles() {
+  toLogInfo "Cleaning installation temporary files"
+
+  rm -f "${EXTERNAL_TAR_FILE}" "${INTERNAL_TAR_FILE}" "${INSTALL_DIR}/xzdec"
+  rm -Rf "${TMP_DIR}"
+
+  local keepInstallationLockFile="${1}"
+  if [ -z "${keepInstallationLockFile}" ]; then
+    removeInstallationLockFile
+  fi
+}
+
+#== 完成安装后清理临时目录
+finishInstallation() {
+  if [ $# -eq 2 ]; then
+    cleanInstallationTemporaryFiles "${2}"
+  else
+    cleanInstallationTemporaryFiles ""
+  fi
+  toLogInfo "Installation finished, PID $$, exit code: ${1}."
+  changeWorkingDir "${CURR_PATH}"
+  if [ "${CONF_LD_PRELOAD}"x = "true"x ]; then
+    exec /bin/bash && exit 0
+  fi
+  exit "${1}"
+}
+
+#**********************************************************
+# Create folders, copy files, set rights
+#**********************************************************
+
+#== 【3】=创建临时目录
+prepareTempFolder() {
+  #== 删除存在的路径
+  removeIfExists "${TMP_DIR}"
+
+  toLogInfo "Creating temporary folder $TMP_DIR"
+  createDirIfNotExistAndSetRights "${TMP_DIR}" 755
+}
+
+#== 【4】=设置文件可执行权限
+setRightsForFiles() {
+  local file="${1}"
+  local perms="${2}"
+
+  if [ -e "${file}" ]; then
+    chmod "${perms}" "${file}"
+  fi
+}
+
+setRightsForDir() {
+  local dir="${1}"
+  local perms="${2}"
+
+  if [ -d "${dir}" ]; then
+    chmod -R "${perms}" "${dir}"
+  fi
+}
+
+#== 【4】=安装类型(f:文件,d:目录)递归设置权限
+chmod4FilesRecursively() {
+  local dir="${1}"
+  local type="${2}"
+  local mask="${3}"
+  find "${dir}" -type "${type}" -exec chmod "${mask}" {} \;
+}
+
+#== 【4】=移动目录到指定位置
+moveFolderToDestination() {
+  local source="${1}"
+  local destination="${2}"
+  local fullDestination
+  fullDestination="${destination}/$(basename "${source}")"
+  local output
+
+  toLogInfo "Moving ${source} to ${destination}"
+  if [ ! -e "${fullDestination}" ]; then
+    if output="$(mv -f "${source}" "${destination}" 2>&1)"; then
+      toLogInfo "Moving Successfully."
+      return
+    fi
+    toLogWarn "Failed to move ${source} to ${destination}: ${output}, attempting to copy"
+  else
+    toLogInfo "${fullDestination} already exists, attempting to copy"
+  fi
+
+  if ! output="$(cp -Rfp "${source}" "${destination}" 2>&1)"; then
+    toLogError "Failed to copy ${source} to ${destination}: ${output}"
+  fi
+}
+
+#== 【4】=将 bin 下版本内容移动到安装目录
+installVersionedContent() {
+  toLogInfo "Installing versioned content..."
+  createDirIfNotExistAndSetRights "${AGENT_BIN_DIR}" 755
+
+  local sourceDir="${TMP_DIR}/bin"
+  if [ ! -d "${AGENT_BIN_DIR}" ]; then
+    moveFolderToDestination "${sourceDir}" "${AGENT_BIN_DIR}"
+    return
+  fi
+
+  toLogInfo "Directory ${AGENT_BIN_DIR} already exist, repairing the directory"
+  rm -rf "${AGENT_BIN_DIR}"
+  moveFolderToDestination "${sourceDir}" "${AGENT_BIN_DIR}"
+}
+
+#== 【4】=创建当前版本软连接
+
+#== 【4】=删除存在的目录
+listAndRemoveDirectoryIfExists() {
+  local directory="${1}"
+  if [ -d "${directory}" ]; then
+    toLogInfo "${directory} exists, removing it."
+    toLogInfo "Contents: $(ls -lR "${directory}")"
+    rm -rf "${directory}"
+  fi
+}
+
+#== 【4】=临时目录中conf 移动到 agent 安装目录中
+setupConfFolder() {
+  toLogInfo "Setup conf folder..."
+  #== 移动目录到指定位置
+  moveFolderToDestination "${TMP_DIR}/conf" "${INSTALL_DIR}"
+
+  chmod 755 "${AGENT_CONF_DIR}"
+
+  toLogInfo "Setup conf done."
+}
+
+#== 【4】=给距离当前目录至少 ${mindepth} 个子目录的所有文件设置权限
+chmodFilesWithMindepth() {
+  local dir="${1}"
+  local mindepth="${2}"
+  local mask="${3}"
+
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    #== 安装类型(f:文件,d:目录)递归设置权限
+    chmod4FilesRecursively "${1}" f "${3}"
+  else
+    #== 查找深度距离当前目录至少 ${mindepth} 个子目录的所有文件
+    find "${dir}" -mindepth "${mindepth}" -print0 | xargs -r -0 chmod "${mask}"
+  fi
+}
+
+#== 【4】=配置其他文件(cwserveragent.service、installer.version)
+setupMiscFiles() {
+  toLogInfo "Setup misc files..."
+  #== 创建 cwserveragent.service
+  createSystemdUnitFile
+  #== echo "${AGENT_INSTALLER_VERSION}" >"${INSTALL_DIR}/installer.version"
+  mv -f "${TMP_DIR}/installer.version" "${INSTALL_DIR}/"
+  toLogInfo "Setup misc done."
+}
+
+#== 【4】=创建 cwserveragent.service
+createSystemdUnitFile() {
+  toLogInfo "creating init scripts ${AGENT_SCRIPTS_DIR}"
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+    return
+  fi
+  createDirIfNotExistAndSetRights "${AGENT_SCRIPTS_DIR}" 755
+  cat <<EOF >${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}
+[Unit]
+Description=${BRAND_AGENT_PRODUCT_NAME}
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+User=root
+ExecStart=${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} start
+ExecStop=${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} stop
+Type=forking
+#Restart=always
+KillMode=process
+TimeoutSec=240
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+  setRightsForFiles "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" 755
+  if [ "${INIT_DIR}"x != "${AGENT_SCRIPTS_DIR}"x ]; then
+    cp -f "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" ${INIT_DIR}
+    toLogInfo "Copy scripts ${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT} to ${INIT_DIR} done."
+  fi
+  toLogInfo "creating init scripts ${AGENT_SCRIPTS_DIR} done."
+}
+
+setupAll() {
+#  moveFolderToDestination "${TMP_DIR}/package_dir/*" "${INSTALL_DIR}"
+#ls  ${TMP_DIR}/package_dir/*
+
+  #== 移动所有文件到目录
+  cp -Rfp ${TMP_DIR}/package_dir/* "${INSTALL_DIR}"
+  local installVersionFile="${INSTALL_DIR}/installer.version"
+  echo ${AGENT_INSTALLER_VERSION} > ${installVersionFile}
+#  mv ${INSTALL_DIR}/package_dir/* ${INSTALL_DIR}
+#     echo "${TMP_DIR}/*" "${INSTALL_DIR}/"
+}
+
+#== 【4】=配置 lib、conf、bin、cwserveragent.service、installer.version、plugins
+setupOptDir() {
+  createDirIfNotExistAndSetRights "${INSTALL_DIR}" 1775
+  #== 临时目录中conf 移动到 agent 安装目录中
+  setupConfFolder
+  #== 将 bin 下版本内容移动到安装目录
+  installVersionedContent
+  #== 配置其他文件(cwserveragent.service、installer.version)
+  setupMiscFiles
+}
+
+#== 【4】=复制临时目录 scripts/cwserveragent 到指定目录下
+copyScriptsToDirectory() {
+  local scriptLocation="${1}"
+  #== scripts/cwserveragent
+  local scriptFile="${TMP_DIR}/scripts/${SERVICE_SCRIPT_FILE}"
+
+  toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} begin."
+
+  local output
+  if ! output="$(cp "${scriptFile}" "${scriptLocation}/" 2>&1)"; then
+    toLogError "Failed to copy ${scriptFile} to ${scriptLocation}, output: ${output}"
+    return
+  fi
+
+  setRightsForFiles "${scriptLocation}/${SERVICE_SCRIPT_FILE}" 755
+  toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} done."
+
+  #== scripts/uninstall.sh
+#  local scriptLocation="${1}"
+#    #== scripts/cwserveragent
+#    local scriptFile="${TMP_DIR}/scripts/uninstall.sh"
+#
+#    toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} begin."
+#
+#    local output
+#    if ! output="$(cp "${scriptFile}" "${scriptLocation}/" 2>&1)"; then
+#      toLogError "Failed to copy ${scriptFile} to ${scriptLocation}, output: ${output}"
+#      return
+#    fi
+#    setRightsForFiles "${scriptLocation}/uninstall.sh" 755
+#    toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} done."
+}
+
+#== 【4】=复制临时目录 scripts/cwserveragent 到指定目录下
+copyScripts() {
+  toLogInfo "Copy scripts..."
+  #== 创建目录 /opt/cloudwise/cwserveragent/scripts
+  createDirIfNotExistAndSetRights "${AGENT_SCRIPTS_DIR}" 755
+  #== 创建目录 /opt/cloudwise/{product}/agents
+  createDirIfNotExistAndSetRights "${AGENTS_BASE_DIR}" 775
+  #== 创建目录 /opt/cloudwise/{product}/meta
+  createDirIfNotExistAndSetRights "${META_BASE_DIR}" 775
+  #== 创建目录 /opt/cloudwise/{product}/runtime
+  createDirIfNotExistAndSetRights "${AGENT_RUNTIME_DIR}" 775
+
+  #== scripts/uninstall.sh
+  local uninstallScript="${TMP_DIR}/scripts/uninstall.sh"
+  toLogInfo "Copy scripts ${uninstallScript} to ${INSTALL_DIR} begin."
+  local output
+  if ! output="$(cp "${uninstallScript}" "${INSTALL_DIR}/uninstall.sh" 2>&1)"; then
+    toLogError "Failed to copy ${uninstallScript} to ${INSTALL_DIR}/uninstall.sh, output: ${output}"
+  else
+    setRightsForFiles "${INSTALL_DIR}/uninstall.sh" 755
+  fi
+  toLogInfo "Copy scripts ${uninstallScript} to ${INSTALL_DIR} done."
+
+  #== 复制临时目录 scripts/ 到安装目录 /opt/cloudwise/cwserveragent/scripts
+  copyScriptsToDirectory "${AGENT_SCRIPTS_DIR}"
+  if [ "${INIT_DIR}"x != "${AGENT_SCRIPTS_DIR}"x ]; then
+    copyScriptsToDirectory "${INIT_DIR}"
+  fi
+  toLogInfo "Copy scripts done."
+}
+
+#== 【4】=调用 agent 64位数lib路径(lib64/installaction)执行指令 --create-cluster-timestamp-file
+createFirstClusterTimestampFile() {
+  toLogInfo "Creating firstClusterTimestamp file"
+  #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --create-cluster-timestamp-file
+  "$(getAgentInstallActionPath)" "--create-cluster-timestamp-file" >>"${LOG_FILE}" 2>&1
+}
+
+#== 【4】=配置数据存储目录
+setupDataStorageDir() {
+  toLogInfo "Setup datastorage dir..."
+  local dataStorage
+  dataStorage="$(getValueFromConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${LEGACY_AGENT_CONF_FILE}" "${DATA_STORAGE_DIR}")"
+  if [ "${dataStorage}"x = "${LOG_DIR}"x ]; then
+    toLogInfo "Detected legacy data storage setting, changing it to the new default location"
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${DATA_STORAGE_DIR}" "${LEGACY_AGENT_CONF_FILE}"
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${DATA_STORAGE_DIR}" "${INSTALLER_CONF_FILE}"
+  fi
+
+  if [ "${PARAM_DATA_STORAGE}" ]; then
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${PARAM_DATA_STORAGE}" "${LEGACY_AGENT_CONF_FILE}"
+    writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${PARAM_DATA_STORAGE}" "${INSTALLER_CONF_FILE}"
+  fi
+
+  toLogInfo "Setup datastorage dir done."
+}
+
+#**********************************************************
+# Processing command line parameters
+#**********************************************************
+#== 【0】=help
+displayHelp() {
+  printf '%s\n' "Usage: $(basename "${INSTALLER_FILE}") [-h] [-v] "
+  #== printf '%s\n' "Usage: $(basename "${INSTALLER_FILE}") [-h] [-v] [DATA_SERVER=https://server_address:server_port] [CONFIG_SERVER=configService] [LICENSE=license] [INSTALL_DIR=install_path]"
+  local beginStr="Usage: "
+  local pad="${#beginStr}"
+
+  printf "\n\n"
+
+  pad=25
+  printf "%-${pad}s%s\n" "-h, --help" "Display this help and exit."
+  printf "%-${pad}s%s\n" "-v, --version" "Print version and exit."
+
+}
+
+printParamMessage() {
+  local paramNm="${1}"
+  local paramValue="${2}"
+  toConsoleInfo "---> Parameter ${paramNm}=${paramValue}."
+}
+
+printOtherParamMessage() {
+  local param="${1}"
+  toConsoleInfo "---> Parameter ${param}"
+}
+
+#== 【0】=大小写转化,并返回判断结果
+istrcmp() {
+  local s1
+  local s2
+  s1="$(printf '%s' "${1}" | tr '[:upper:]' '[:lower:]')"
+  s2="$(printf '%s' "${2}" | tr '[:upper:]' '[:lower:]')"
+  [ "${s1}"x = "${s2}"x ]
+}
+
+#== 【0】=
+isParamTrue() {
+  [ "${1}"x = "1"x ] || [ "${1}"x = "true"x ] || [ "${1}"x = "enable"x ] || [ "${1}"x = "yes"x ]
+}
+#== 【1】【5】=
+isParamFalse() {
+  [ "${1}"x = "0"x ] || [ "${1}"x = "false"x ] || [ "${1}"x = "disable"x ] || [ "${1}"x = "no"x ]
+}
+
+#== 【1】【5】=
+invertBoolValue() {
+  local valueToInvert="${1}"
+  if isParamFalse "${valueToInvert}"; then
+    printf '%s' "true"
+  else
+    printf '%s' "false"
+  fi
+}
+
+#== shellcheck disable=SC2003
+#== 【0】=获取参数值
+getParamValue() {
+  local paramName="${1}"
+  local input="${2}"
+  local paramNameLength="${#paramName}"
+  paramNameLength=$((paramNameLength + 1))
+  local partParam
+  partParam="$(expr substr "${input}" 1 ${paramNameLength})"
+#  partParam=$(substr "${input}" 1 ${paramNameLength})
+  if ! istrcmp "${partParam}" "${paramName}="; then
+    return 1
+  fi
+
+  local valueSeparator=$((paramNameLength + 1))
+  local value
+  value="$(expr substr "${input}" ${valueSeparator} 1000)"
+#  value=$(substr "${input}" ${valueSeparator} 1000)
+  if [ -z "${value}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${value}"
+  return 0
+}
+
+#== 【0】=获取bool参数
+readBoolParam() {
+  local value
+  value="$(getParamValue "${1}" "${2}")"
+
+  if value="$(getBoolParam "${value}")"; then
+    printf "%s" "${value}"
+    return 0
+  fi
+
+  return 1
+}
+
+#== 【0】=获取bool参数
+getBoolParam() {
+  local value="${1}"
+  if [ "${value}" ]; then
+    if isParamFalse "${value}"; then
+      printf "false"
+      return 0
+    fi
+    if isParamTrue "${value}"; then
+      printf "true"
+      return 0
+    fi
+  fi
+
+  return 1
+}
+
+#== 【0】=校验格式是否规范[1、大于4个字符且不能"cw."开头,2、不能超过100字符,3、只能包含字母数字字符,连字符,下划线和点。]
+validateParameter() {
+  local name="${1}"
+  local value="${2}"
+  if [ "$(printf '%s' "${value}" | cut -c -3)"x = "cw."x ]; then
+    toConsoleError "${name} must not begin with 'cw.'"
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "${#value}" -gt 100 ]; then
+    toConsoleError "Maximum allowed length of ${name} is 100."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if printf '%s' "${value}" | grep -q "[^[:alnum:]._-]"; then
+    toConsoleError "${name} can only contain alphanumeric characters, hyphen, underscore and dot."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】=验证用户和用户组是否匹配
+validateUserAndGroupParameters() {
+  local user="${1}"
+  local group="${2}"
+  local permittedNameRegex='^[[:alnum:]._][[:alnum:]._-]{2,31}$'
+
+  if [ ! "${group}" ]; then
+    group="${user}"
+  fi
+
+  if ! printf '%s' "${user}" | grep -qE "${permittedNameRegex}"; then
+    toConsoleError "USER can only contain alphanumeric characters, hyphen, underscore and dot, and must have length from 3 to 32 characters."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if ! printf '%s' "${group}" | grep -qE "${permittedNameRegex}"; then
+    toConsoleError "GROUP can only contain alphanumeric characters, hyphen, underscore and dot, and must have length from 3 to 32 characters."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  #== 校验用户/用户组信息
+  validateUserPrimaryGroup "${user}" "${group}"
+}
+
+#== 【0】【3】【5】=获取系统权限信息
+getSystemEntityInfo() {
+  local database="${1}"
+  local valueToCheck="${2}"
+
+  #== 校验命令getent是否存在
+  if ! isAvailable "getent"; then
+    toLogInfo "Command getent is not available"
+    return 2
+  fi
+
+  #== 查看系统权限
+  local output
+  output="$(getent "${database}" "${valueToCheck}" 2>&1)"
+  local returnCode=$?
+
+  if [ "${returnCode}" != 0 ]; then
+    if [ "${returnCode}" != 2 ]; then
+      toLogWarn "Failed to check ${valueToCheck} in ${database} database, message: ${output}, code: ${returnCode}"
+    fi
+    return 1
+  elif [ ! "${output}" ]; then
+    toLogWarn "Failed to get user information: getent returned no output"
+  fi
+
+  printf '%s' "${output}"
+  return 0
+}
+
+#== 【0】【3】=查看用户/用户组信息
+isEntityPassedById() {
+  local database="${1}"
+  local name="${2}"
+
+  local output
+  output="$(getSystemEntityInfo "${database}" "${name}")"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 0 ]; then
+    if [ ${returnCode} -eq 2 ]; then
+      toLogInfo "Installer will not be able to verify whether entity was passed by name or by ID"
+    fi
+    return 1
+  fi
+
+  local nameFromDatabase
+  nameFromDatabase="$(printf '%s' "${output}" | cut -d: -f1)"
+
+  if [ "${nameFromDatabase}"x = "${name}"x ]; then
+    return 1
+  fi
+
+  toLogWarn "Name from config and from ${database} system database do not match"
+  toLogWarn "Config: ${name}, database: ${nameFromDatabase}"
+  return 0
+}
+
+#== 【0】【3】【5】=用户是否存在
+userExistsInSystem() {
+  local user="${1}"
+
+  getSystemEntityInfo "passwd" "${user}" >/dev/null
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    return ${returnCode}
+  fi
+
+  toLogInfo "Trying to determine user existence using 'id' command"
+  id "${user}" >/dev/null 2>&1
+}
+
+#== 【5】= 查看group
+groupExistsInSystem() {
+  local group="${1}"
+
+  getSystemEntityInfo "group" "${group}" >/dev/null
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    return ${returnCode}
+  fi
+
+  toLogInfo "Installer will not be able to determine group existence"
+  return 1
+}
+
+#== 【3】=用户是否存在
+validateUserExistence() {
+  local user="${1}"
+  if ! userExistsInSystem "${user}"; then
+    toConsoleError "User named '${user}' configured for ${BRAND_PRODUCT_NAME} does not exist. Installation aborted."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】【3】=检查用户/用户组信息
+checkIfEntityWasNotPassedById() {
+  local database="${1}"
+  local valueToCheck="${2}"
+  local valueTypeToLog="user"
+
+  if [ "${database}"x = "group"x ]; then
+    valueTypeToLog="group"
+  fi
+
+  if isEntityPassedById "${database}" "${valueToCheck}"; then
+    toConsoleError "\"${valueToCheck}\" is not a ${valueTypeToLog} name but its ID. Installation aborted."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】【3】=用户权限下用户组ID
+getUserPrimaryGroupIdForComparison() {
+  local user="${1}"
+
+  local userPrimaryGroupId
+  userPrimaryGroupId="$(getSystemEntityInfo "passwd" "${user}")"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    printf '%s' "${userPrimaryGroupId}" | cut -d: -f4
+    return ${returnCode}
+  fi
+
+  toLogInfo "Returning user primary group name instead of its id"
+  id -gn "${user}"
+}
+
+#== 【0】【3】=获取用户组信息
+getGroupIdForComparison() {
+  local group="${1}"
+
+  local groupId
+  groupId="$(getSystemEntityInfo "group" "${group}")"
+  local returnCode=$?
+
+  if [ ${returnCode} -ne 2 ]; then
+    printf '%s' "${groupId}" | cut -d: -f3
+    return ${returnCode}
+  fi
+
+  toLogInfo "Returning group name instead of its id"
+  printf '%s' "${group}"
+}
+
+#== 【0】【3】=校验用户/用户组信息
+validateUserPrimaryGroup() {
+  local user="${1}"
+  local group="${2}"
+
+  if ! userExistsInSystem "${user}"; then
+    return
+  fi
+
+  checkIfEntityWasNotPassedById "passwd" "${user}"
+  checkIfEntityWasNotPassedById "group" "${group}"
+
+  #== 获取用户组ID
+  local groupId
+  groupId="$(getGroupIdForComparison "${group}")"
+  #== 获取用户下用户组ID
+  local userPrimaryGroupId
+  userPrimaryGroupId="$(getUserPrimaryGroupIdForComparison "${user}")"
+
+  toConsoleInfo "#DEBUG== group \"${group}\" id: \"${groupId}\", user \"${user}\" primaryGroupId: \"${userPrimaryGroupId}\""
+  if [ "${userPrimaryGroupId}"x != "${groupId}"x ]; then
+    toConsoleError "User named \"${user}\" does not have group named \"${group}\" as its primary group. Installation aborted."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【3】=检查用户/用户组是否存在和匹配
+checkUserAndGroupFromConfig() {
+  local configUser
+  local configGroup
+  configUser="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  configGroup="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+
+  toLogInfo "Checking validity of user account '${configUser}:${configGroup}'"
+
+  if [ "${PARAM_UPGRADE}"x = "yes"x ]; then
+    validateUserExistence "${configUser}"
+  fi
+
+  #== 校验用户/用户组信息
+  validateUserPrimaryGroup "${configUser}" "${configGroup}"
+}
+
+#== 【0】=解析命令行中参数
+parseCommandLineParameters() {
+  local dataServerIsEmpty=true
+  local configServerIsEmpty=true
+  while [ $# -gt 0 ]; do
+    local param="${1}"
+    local value=
+
+    if value=$(getParamValue DATA_SERVER "${param}"); then
+      PARAM_DATA_SERVER="${value}"
+      dataServerIsEmpty=false
+      printParamMessage "DATA_SERVER" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue CONFIG_SERVER "${param}"); then
+      PARAM_CONFIG_SERVER="${value}"
+      configServerIsEmpty=false
+      printParamMessage "CONFIG_SERVER" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue LICENSE "${param}"); then
+      PARAM_LICENSE="${value}"
+      printParamMessage "LICENSE" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue JSON_CONF "${param}"); then
+      PARAM_JSON_CONF="${value}"
+      printParamMessage "JSON_CONF" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue INSTALL_DIR "${param}"); then
+      PARAM_INSTALL_DIR="${value}"
+      printParamMessage "INSTALL_DIR" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue DATA_STORAGE "${param}"); then
+      PARAM_DATA_STORAGE="${value}"
+      printParamMessage "DATA_STORAGE" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(readBoolParam DISABLE_SYSTEM_LOGS_ACCESS "${param}"); then
+      PARAM_DISABLE_SYSTEM_LOGS_ACCESS="${value}"
+      printParamMessage "DISABLE_SYSTEM_LOGS_ACCESS" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue INTERNAL_OVERRIDE_CHECKS "${param}"); then
+      if printf '%s' "${value}" | grep -wq "privileges"; then
+        PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK=true
+      fi
+
+      if printf '%s' "${value}" | grep -wq "downgrade"; then
+        SKIP_DOWNGRADE_CHECK=true
+      fi
+      printParamMessage "INTERNAL_OVERRIDE_CHECKS" "${value}"
+
+      shift
+      continue
+    fi
+
+    if value=$(readBoolParam INTERNAL_USE_UNPACK_CACHE "${param}"); then
+      PARAM_INTERNAL_USE_UNPACK_CACHE="${value}"
+      printParamMessage "INTERNAL_USE_UNPACK_CACHE" "${value}"
+      shift
+      continue
+    fi
+
+    if [ "${ARCH_ARCH}"x != "AIX"x ]; then
+      if value=$(getParamValue USER "${param}"); then
+        PARAM_USER="${value}"
+        printParamMessage "USER" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(getParamValue GROUP "${param}"); then
+        PARAM_GROUP="${value}"
+        printParamMessage "GROUP" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam NON_ROOT_MODE "${param}"); then
+        PARAM_NON_ROOT_MODE="${value}"
+        printParamMessage "NON_ROOT_MODE" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam USER_LOGIN "${param}"); then
+        PARAM_USER_LOGIN="${value}"
+        printParamMessage "USER_LOGIN" "${value}"
+        shift
+        continue
+      fi
+
+      #== 自定义参数获取
+      if value=$(getParamValue TEST "${param}"); then
+        PARAM_TEST="${value}"
+        printParamMessage "TEST" "${value}"
+        shift
+        continue
+      fi
+
+      #== 自定义bool参数
+      if value=$(readBoolParam BOOL "${param}"); then
+        PARAM_BOOL="${value}"
+        printParamMessage "BOOL" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam DISABLE_ROOT_FALLBACK "${param}"); then
+        PARAM_DISABLE_ROOT_FALLBACK="${value}"
+        printParamMessage "DISABLE_ROOT_FALLBACK" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK "${param}"); then
+        PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK="${value}"
+        printParamMessage "NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam INTERNAL_SKIP_SELINUX_POLICY_INSTALLER "${param}"); then
+        #== PARAM_INTERNAL_SKIP_SELINUX_POLICY_INSTALLER="${value}"
+        printParamMessage "INTERNAL_SKIP_SELINUX_POLICY_INSTALLER" "${value}"
+        shift
+        continue
+      fi
+
+      if value=$(readBoolParam DOCKER_ENABLED "${param}"); then
+        #== PARAM_INTERNAL_DEPLOYED_VIA_CONTAINER="${value}"
+        printParamMessage "DOCKER_ENABLED" "${value}"
+        shift
+        continue
+      fi
+    fi
+
+    if [ "${ARCH_ARCH}"x != "AIX"x ] && [ "${ARCH_ARCH}"x != "S390"x ]; then
+      if value=$(readBoolParam INTERNAL_DISABLE_DUMPPROC "${param}"); then
+        #== PARAM_INTERNAL_DISABLE_DUMPPROC="${value}"
+        printParamMessage "INTERNAL_DISABLE_DUMPPROC" "${value}"
+        shift
+        continue
+      fi
+    fi
+
+    if [ "${param}"x = "-h"x ] || [ "${param}"x = "--help"x ]; then
+      displayHelp
+      finishInstallation "${EXIT_CODE_OK}"
+    fi
+
+    if [ "${param}"x = "-v"x ] || [ "${param}"x = "--version"x ]; then
+      printf "%s\n" "${AGENT_INSTALLER_VERSION}"
+      finishInstallation "${EXIT_CODE_OK}"
+    fi
+    
+    printOtherParamMessage ${param}
+    shift
+  done
+
+  if [ "${configServerIsEmpty}"x = "true"x ] && [ "${dataServerIsEmpty}"x != "true"x ]; then
+    PARAM_CONFIG_SERVER="${PARAM_DATA_SERVER}"
+  fi
+}
+
+#== 【0】=校验PARAM_INSTALL_DIR是否规范【1、不能包含空格,2、不能在根目录,3、安装路径必须是绝对的】
+validateInstallPathParameter() {
+  if printf '%s' "${PARAM_INSTALL_DIR}" | grep -q "[[:space:]]"; then
+    toConsoleError "Installation path must not contain spaces."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "${PARAM_INSTALL_DIR}"x = "/"x ]; then
+    toConsoleError "Installation path must not point to the filesystem root directory."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "$(printf '%s' "${PARAM_INSTALL_DIR}" | cut -c 1)"x != "/"x ]; then
+    toConsoleError "Installation path must be absolute."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+#== 【0】=校验PARAM_DATA_STORAGE是否规范【1、不能包含空格,2、不能在根目录,3、安装路径必须是绝对的,4、数据目录不能放在安装目录下】
+validateDataStorageParameter() {
+  if printf '%s' "${PARAM_DATA_STORAGE}" | grep -q "[[:space:]]"; then
+    toConsoleError "Data storage path must not contain spaces."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "${PARAM_DATA_STORAGE}"x = "/"x ]; then
+    toConsoleError "Data storage path must not point to the filesystem root directory."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if [ "$(printf '%s' "${PARAM_DATA_STORAGE}" | cut -c 1)"x != "/"x ]; then
+    toConsoleError "Data storage path must be absolute."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+
+  if printf '%s' "${PARAM_DATA_STORAGE}" | grep -q "^${INSTALL_DIR}"; then
+    toConsoleError "Data storage path must not be located within ${INSTALL_DIR}."
+    finishInstallation "${EXIT_CODE_INVALID_PARAM}"
+  fi
+}
+
+
+#**********************************************************
+# Config files
+#**********************************************************
+
+#== 【3】【5】=格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
+formatSize() {
+  local sizeInKiB="${1}"
+  local formattedSize
+
+  for symbol in "KiB" "MiB" "GiB" "TiB"; do
+    if printf '%s' "${sizeInKiB}" | awk '$1 >= 1024 { exit 1; }'; then
+      formattedSize="${sizeInKiB} ${symbol}"
+      break
+    fi
+    sizeInKiB="$(printf '%s' "${sizeInKiB}" | awk '{ print $1 / 1024 }')"
+  done
+
+  printf '%s' "${formattedSize}"
+}
+
+#== 【3】【5】=
+cropSizeValue() {
+  local size="${1}"
+  local value
+  local unit
+  value="$(printf '%s' "${size}" | cut -d' ' -f1)"
+  unit="$(printf '%s' "${size}" | cut -d' ' -f2)"
+  printf '%.2f %s' "${value}" "${unit}"
+}
+
+#== 【3】【5】=检查目录可用空间(单位:k)
+checkFreeSpace() {
+  local path="${1}"
+  local requiredSpaceInKiB="${2}"
+  local dfOutput
+  local baseFilesystem
+  local freeSpace
+  local formattedRequiredSpace
+  local formattedFreeSpace
+
+  #== shellcheck disable=SC2086
+  dfOutput="$(df -P ${AIX_DF_SPECIFIC_FLAG} "${path}" | tail -n +2)"
+  #== 文件系统目录
+  baseFilesystem="$(printf "%s" "${dfOutput}" | awk '{ print $NF }')"
+  #== 剩余空间(单位:k)
+  freeSpace="$(printf "%s" "${dfOutput}" | awk '{ print $4 }')"
+
+  #== 格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
+  formattedRequiredSpace="$(formatSize "${requiredSpaceInKiB}")"
+  toLogInfo "Filesystem with ${path} is mounted under ${baseFilesystem}. Space required: ${formattedRequiredSpace}."
+
+  if [ ! "${freeSpace}" ]; then
+    printf 'Cannot determine amount of free space on %s (filesystem mounted under %s)' "${path}" "${baseFilesystem}"
+    return 1
+  fi
+
+  #== 格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
+  formattedFreeSpace="$(formatSize "${freeSpace}")"
+  toLogInfo "Available free space: ${formattedFreeSpace}"
+
+  if [ "${freeSpace}" -lt "${requiredSpaceInKiB}" ]; then
+    printf 'Not enough free space on %s (filesystem mounted under %s). ' "${path}" "${baseFilesystem}"
+    printf 'Required: %s, available: %s' "$(cropSizeValue "${formattedRequiredSpace}")" "$(cropSizeValue "${formattedFreeSpace}")"
+    return 2
+  fi
+
+  printf 'Free space is sufficient'
+  return 0
+}
+
+#== 【3】=检查文件系统类型
+
+#== 【3】=检查安装目录空间
+checkInstallPathFreeSpace() {
+  local externalTarSize=${EXTERNAL_TAR_SIZE}
+  local artifactsSize=${ARTIFACTS_SIZE}
+  #== use 10% additional margin
+  local requiredSpace=$((externalTarSize + artifactsSize * 11 / 10))
+  #== convert to kibibytes
+  requiredSpace=$((requiredSpace / 1024))
+
+  toConsoleInfo "Checking free space in ${INSTALL_DIR}"
+
+  local message
+  #== 检查目录可用空间(单位:k)
+  message="$(checkFreeSpace "${INSTALL_DIR}" "${requiredSpace}")"
+  case $? in
+  0) toLogInfo "${message}" ;;
+  1) toConsoleWarn "${message}. Installation may be incomplete." ;;
+  2)
+    toConsoleError "${message}"
+    finishInstallation "${EXIT_CODE_NOT_ENOUGH_SPACE}"
+    ;;
+  esac
+}
+
+#== 【3】=获取指定路径的文件系统信息
+getFilesystemInfo() {
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    mount | grep " ${1} "
+  else
+    grep " ${1} " /proc/self/mounts
+  fi
+}
+
+#== 【3】=检查目录指定权限信息
+checkAccessRightsTo() {
+  local dir="${1}"
+  toLogInfo "Checking access to ${dir}..."
+  #== 获取文件权限信息
+  local accessRights
+  accessRights="$(arch_getAccessRights "${dir}" | cut -c 2-4)"
+  if ! printf '%s' "${accessRights}" | grep -q rwx; then
+    toConsoleError "Insufficient permissions on ${dir}: '${accessRights}'."
+    toLogInfo "$(ls -dl "${dir}" 2>&1)"
+    finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
+  fi
+
+  local dfResult
+  local filesystem
+  local filesystemInfo
+  dfResult="$(df -P "${dir}")"
+  #== 获取目录文件系统路径
+  filesystem="$(printf '%s' "${dfResult}" | tail -1 | awk '{ print $NF }')"
+  #== 获取指定路径的文件系统信息
+  filesystemInfo="$(getFilesystemInfo "${filesystem}")"
+  if ! printf '%s' "${filesystemInfo}" | grep -qw rw; then
+    toLogWarn "df-based check determined filesystem mounted under ${filesystem} as readonly, trying fallback."
+    toLogWarn "Filesystem access rights: '${filesystemInfo}'"
+    toLogWarn "df returned: ${dfResult}"
+
+    if ! testWriteAccessToDir "${dir}"; then
+      toConsoleError "readonly filesystem mounted under ${filesystem}"
+      finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
+    fi
+  fi
+
+  toLogInfo "Rights on directory ${dir} are sufficient"
+} 2>>"${LOG_FILE}"
+
+#== 【3】=目录是否写权限
+checkIfInstallationPathIsWriteable() {
+  for dir in "${@}"; do
+    if [ -d "${dir}" ]; then
+      checkAccessRightsTo "${dir}"
+      break
+    fi
+  done
+}
+
+#== 【3】=检查目录权限
+checkAccessRightsToDirs() {
+  checkIfInstallationPathIsWriteable "${INSTALL_DIR}" "${BASE_INSTALL_DIR}" "${INSTALL_BASE}" /
+
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+    checkAccessRightsTo "${INIT_DIR}"
+  fi
+}
+
+
+#== 【0】=检查系统是 LINUX、AIX及指令集(X86_64\IA64\X86)
+checkSystemCompatibility() {
+  local expectedPlatform="LINUX"
+  if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+    expectedPlatform="AIX"
+  fi
+
+  #== 获取系统名称
+  local platform
+  platform="$(uname | sed -e 's/_.*//' | sed -e 's/\///' | tr '[:lower:]' '[:upper:]')"
+  if [ "${platform}"x != "${expectedPlatform}"x ]; then
+    printf "Cannot determine platform or platform not supported: <%s>" "${platform}"
+    return 1
+  fi
+
+  #== 检查系统指令集(X86_64\IA64\X86)
+  local detectedArchitecture
+  if ! detectedArchitecture="$(arch_checkArchitectureCompatibility)"; then
+    printf "Cannot determine architecture or architecture not supported: <%s>" "${detectedArchitecture}"
+    return 1
+  fi
+
+  printf 'Detected platform: %s' "${platform}"
+  if [ "${detectedArchitecture}" ]; then
+    printf ' arch: %s' "${detectedArchitecture}"
+  fi
+
+  return 0
+}
+
+#== 【4】=从sh文件读取压缩文件 tarfile_$$.base64
+separateExternalTar() {
+  toLogInfo "Determining begin of tar archive..."
+  local tarBegin
+  local tarEnd
+  #== 压缩文件开始行数,占位符为【#################ENDOFSCRIPTMARK############】
+  tarBegin="$(locateDelimiter "#################ENDOFSCRIPTMARK############" "")"
+  tarBegin=$((tarBegin + 1))
+  #== 压缩文件结束行数,占位符为【----SIGNED-INSTALLER】
+  tarEnd="$(locateDelimiter "----SIGNED-INSTALLER" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})"
+  toLogInfo "tarBegin=${tarBegin} tarEnd=${tarEnd}"
+
+  if [ ! "${tarEnd}" ]; then
+    toConsoleError "S/MIME signature is missing, installation package is corrupted."
+    finishInstallation "${EXIT_CODE_CORRUPTED_PACKAGE}"
+  fi
+
+  local tarLength=$((tarEnd - tarBegin))
+  toLogInfo "tarLength=${tarLength}"
+  #== 从sh文件读取压缩文件 tarfile_$$.base64
+  tail -n +"${tarBegin}" "${INSTALLER_FILE}" 2>/dev/null | head -${tarLength} >"${EXTERNAL_TAR_FILE}"
+}
+
+#== 【4】【5】=进入目录
+changeWorkingDir() {
+  if ! cd "${1}"; then
+    toLogError "Failed to change working directory to ${1}"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== shellcheck disable=SC2181
+#== 【4】=解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+unpackArchiveWithoutCache() {
+  #== 解压文件编码
+  local base64Binary="${UNPACK_BINARY}"
+  #== 解压文件编码参数
+  local base64BinaryArgs="${UNPACK_BINARY_ARGS}"
+  #== 使用xzdec命令可以进行liblzma为基础的xz文件解压缩
+  local xzBinary="${INSTALL_DIR}/xzdec"
+  #== 进入目录
+  changeWorkingDir "${INSTALL_DIR}"
+
+  if ! isAvailable tar; then
+    toConsoleError "tar binary not found. Setup can't continue"
+    finishInstallation "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
+  fi
+
+  local totalLines
+  if ! isAvailable "${base64Binary}"; then
+    toLogInfo "${base64Binary} not found. Falling back to openssl decode"
+    if ! isAvailable openssl; then
+      toConsoleError "Neither ${base64Binary} nor openssl can be found. Setup can't continue"
+      finishInstallation "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
+    fi
+    #== 如果没有 base64 命令,则使用 openssl 解压文件
+    base64Binary="openssl"
+    base64BinaryArgs="enc -base64 -d -in"
+
+    if [ "${ARCH_ARCH}"x = "AIX"x ]; then
+      #truncate the first and the last one line due to specific format of uuencode on aix
+      totalLines="$(wc -l "${EXTERNAL_TAR_FILE}" | awk '{print $1}')"
+      head -$((totalLines - 1)) "${EXTERNAL_TAR_FILE}" 2>/dev/null | tail +2 >"${EXTERNAL_TAR_FILE}.$$"
+      mv -f "${EXTERNAL_TAR_FILE}.$$" "${EXTERNAL_TAR_FILE}"
+    fi
+  fi
+
+  {
+    #== base64 转编码后,执行 tar 解压
+    "${base64Binary}" "${base64BinaryArgs}" "${EXTERNAL_TAR_FILE}" | tar -x -p -f -
+  } 2>>"${LOG_FILE}"
+
+  #== base64 转编码 或 tar解压失败
+  if [ $? -gt 0 ]; then
+    toConsoleError "Archive is corrupted or memory allocation failed. Installation aborted."
+    finishInstallation "${EXIT_CODE_NOT_ENOUGH_MEMORY}"
+  fi
+
+  #== 进入目录
+  changeWorkingDir "${TMP_DIR}"
+  {
+    #== 使用xzdec命令解压后,执行 tar 解压
+    "${xzBinary}" "${INTERNAL_TAR_FILE}" | tar -x -p -f -
+  } 2>>"${LOG_FILE}"
+
+  if [ $? -gt 0 ]; then
+    toConsoleError "XZ compressed archive is corrupted or memory allocation failed. Installation aborted."
+    finishInstallation "${EXIT_CODE_NOT_ENOUGH_MEMORY}"
+  fi
+  #== 进入目录
+  changeWorkingDir "${INSTALL_DIR}"
+}
+
+#== 【4】=解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+unpackArchive() {
+  toConsoleInfo "Unpacking. This may take a while..."
+
+  #== 【参数】是否使用解压缓存
+  if [ "${PARAM_INTERNAL_USE_UNPACK_CACHE}"x = "true"x ]; then
+    if [ -d "${UNPACK_CACHE}" ]; then
+      toLogInfo "Unpack cache will be used."
+      cp -Rp "${UNPACK_CACHE}"/* "${TMP_DIR}"
+    else
+      toLogInfo "Unpack cache does not exist."
+      mkdir -p "${UNPACK_CACHE}"
+      #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+      unpackArchiveWithoutCache
+      cp -Rp "${TMP_DIR}"/* "${UNPACK_CACHE}"
+    fi
+  else
+    toLogInfo "Unpacking without cache"
+    #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+    unpackArchiveWithoutCache
+  fi
+
+  toConsoleInfo "Unpacking complete."
+}
+
+#== 【3】=检查容器部署、运行情况、配置参数
+#isDeployedInsideOpenVZContainer
+#isProcessRunningInContainer
+#isDeployedViaContainer
+
+
+#== Checking if libc is new enough
+#== 【3】=格式化version
+format_version() {
+  printf '%s' "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }'
+}
+
+#== 【3】=格式化路径
+format_patch() {
+  printf '%s' "$@" | tail -n 1 | awk -F- '{ printf("%d\n", $3); }'
+}
+
+#== 【3】=检查是否降级安装
+checkIfDowngrade() {
+  if [ "${SKIP_DOWNGRADE_CHECK}"x = "true"x ]; then
+    toConsoleInfo "Skipped downgrade check"
+    return
+  fi
+
+  local installVersionFile="${INSTALL_DIR}/installer.version"
+  if [ ! -f "${installVersionFile}" ]; then
+    toLogWarn "Could not perform downgrade check, ${installVersionFile} file is missing"
+    return
+  fi
+
+  local oldVersion
+  oldVersion="$(cat "${installVersionFile}")"
+  if [ "$(format_version "${AGENT_INSTALLER_VERSION}")" -eq "$(format_version "${oldVersion}")" ]; then
+    toConsoleError "${BRAND_PRODUCT_NAME} is already installed, please uninstall the old version using [${INSTALL_DIR}/uninstall.sh]."
+#    toLogError "Attempted downgrade from ${oldVersion} to ${AGENT_INSTALLER_VERSION}"
+    finishInstallation "${EXIT_CODE_UNSUPPORTED_DOWNGRADE}"
+  fi
+}
+
+#== 【3】=检查是否已经安装
+checkIfAlreadyInstalled() {
+  if [ -f "${INSTALL_DIR}/uninstall.sh" ] && [ -f "${AGENT_BIN_DIR}/${AGENT_PROC}" ] ; then
+#    toConsoleError "Agent already installed. Uninstalling previous version."
+#    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+
+    checkIfDowngrade
+    PARAM_UPGRADE="yes"
+  else
+#  		if [ -f "${SIF_AGENT_INSTALL_PATH}/lib64/${AGENT_BIN}" ]; then
+#  			sif_toConsoleError "Upgrade is not possible because uninstall script is missing"
+#  			finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+#  		fi
+      local fileNum
+      fileNum=`ls ${INSTALL_DIR} | wc -l`
+      if [ "${fileNum}" -gt 1 ];then
+         toConsoleError "${INSTALL_DIR} is not empty. Please clean or change the installation directory manually."
+         finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+      fi
+  fi
+
+
+
+}
+
+#**********************************************************
+# Init related functions
+#**********************************************************
+
+#== clears dependencies in LSB init script
+#== 【5】=清除LSB init脚本中的依赖项
+clearDependenciesInLSBInit() {
+  local file="${1}"
+  toConsoleInfo "Clearing dependencies in file ${file}"
+  awk '
+		BEGIN {
+			req_start_found=0;
+			req_stop_found=0;
+			REQ_START="# Required-Start:";
+			REQ_STOP="# Required-Stop:";
+			PATTERN_REQ_START="^" REQ_START;
+			PATTERN_REQ_STOP="^" REQ_STOP;
+		}
+		{
+			if ($0 ~ PATTERN_REQ_START && req_start_found == 0) {
+				print REQ_START;
+				req_start_found++;
+			} else if ($0 ~ PATTERN_REQ_STOP && req_stop_found == 0) {
+				print REQ_STOP;
+				req_stop_found++;
+			} else
+				print $0
+		}' "${file}" >"${file}.tmp" && mv -f "${file}.tmp" "${file}"
+
+  chmod +x "${file}"
+}
+
+#== 【5】=指定目录添加自动启动脚本
+addScriptToSystemvAutostart() {
+  local prefix="${1}"
+  local file="${2}"
+  local suffix="${3}"
+
+  toLogInfo "Adding ${file} to autostart"
+  #== 自动启动工具
+  if ! runAutostartAddingTool "${prefix}" "${file}" "${suffix}"; then
+    toLogWarn "Failed to add ${file} script to autostart. Trying without dependencies..."
+    #== 清除LSB init脚本中的依赖项
+    clearDependenciesInLSBInit "${INIT_DIR}/${file}"
+    if ! runAutostartAddingTool "${prefix}" "${file}" "${suffix}"; then
+      toConsoleError "Cannot add ${file} to autostart. For details, see: ${LOG_FILE}"
+    fi
+  fi
+}
+
+#== 【5】=指定目录添加自动启动脚本
+addScriptsToAutostart() {
+  local prefix="${1}"
+  local suffix="${2}"
+  #== 指定目录添加自动启动脚本
+  addScriptToSystemvAutostart "${prefix}" "${SERVICE_SCRIPT_FILE}" "${suffix}"
+}
+
+#== 【5】=设置自动启动
+#setupSystemvAutostart() {
+#  toLogInfo "Adding ${BRAND_AGENT_PRODUCT_NAME} to autostart..."
+#
+#  if [ -x /usr/bin/update-rc.d ]; then #Ubuntu
+#    #== 指定目录添加自动启动脚本
+#    addScriptsToAutostart "/usr/bin/update-rc.d " "defaults"
+#  elif [ -x /usr/sbin/update-rc.d ]; then #Ubuntu
+#    addScriptsToAutostart "/usr/sbin/update-rc.d " "defaults"
+#  elif [ -x /sbin/chkconfig ]; then #RedHat
+#    addScriptsToAutostart "/sbin/chkconfig --add "
+#  elif [ -x /usr/lib/lsb/install_initd ]; then #Suse
+#    addScriptsToAutostart "/usr/lib/lsb/install_initd ${INIT_DIR}/"
+#  elif [ "${ARCH_ARCH}"x = "AIX"x ]; then
+#    #== 【不存在】
+#    arch_setAutostart
+#  else
+#    toConsoleError "Couldn't add ${BRAND_AGENT_PRODUCT_NAME} to autostart. Please adjust and add it manually."
+#  fi
+#}
+
+#== 【5】=设置 cwserveragent.service 中用户
+setServiceScriptUser() {
+  if ! isNonRootModeEnabled; then
+    return
+  fi
+  #== 读取用户名(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-user)
+  local user
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 修改 cwserveragent.service 中用户信息
+  sed -i "s/User=.*/User=${user}/g" "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}"
+}
+
+#== 【5】=配置自动启动 cwserveragent.service
+setupSystemdAutostart() {
+  mv -f "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" "${SYSTEMD_UNIT_FILES_DIR}/"
+  setRightsForFiles "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" 644
+
+  #== 设置 cwserveragent.service 中用户
+  setServiceScriptUser
+
+  if isAvailable restorecon; then
+    restorecon "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}"
+  fi
+
+  #== 执行 systemctl 命令配置允许开机启动 cwserveragent.service
+  executeSystemctlCommand enable "${SYSTEMD_UNIT_FILE_AGENT}"
+  #== 执行 systemctl 命令重新加载模块
+  executeSystemctlCommand daemon-reload ""
+}
+
+#== 【6】=运行service 脚本
+execIntoServiceScript() {
+  toConsoleInfo "${SERVICE_SCRIPT_FILE} will be started via exec()"
+  #== 清除安装临时文件
+  cleanInstallationTemporaryFiles
+  toLogInfo "Installation finished, PID $$."
+
+  local command="exec ${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} exec"
+  toLogInfo "Executing: ${command}"
+  #== 执行 cwserveragent exec
+  ${command}
+
+  toLogError "Could not execute: ${command}"
+  finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+}
+
+#== 【6】=运行agent
+runAgents() {
+  toConsoleInfo "Starting agents..."
+
+  toLogInfo "Using ${INIT_SYSTEM} to start the agent"
+  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+    #== 运行初始化命令(通过 service start 方式 或 直接运行可执行命令)
+    executeInitScriptCommand start "true"
+  else
+    #== 执行 systemctl start 命令
+    executeSystemctlCommand start "${SYSTEMD_UNIT_FILE_AGENT}"
+  fi
+
+  if [ $? -eq 0 ]; then
+    toConsoleInfo "${SERVICE_SCRIPT_FILE} service started"
+  else
+    toConsoleError "Failed to start service: ${SERVICE_SCRIPT_FILE}, it is possible that your init system is not functioning properly. For details, see: ${LOG_FILE}"
+  fi
+}
+
+#== 【5】=配置自动启动
+#setupAutostart() {
+#  if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
+#    #== 设置自动启动
+#    setupSystemvAutostart
+#  else
+#    #== 配置自动启动 cwserveragent.service
+#    setupSystemdAutostart
+#  fi
+#}
+
+#**********************************************************
+# Process agent related functions
+#**********************************************************
+
+#== 【5】=创建 agent 状态文件
+createAgentStateFile() {
+  local path="${1}"
+  local agentStateContents="RUNNING"
+
+  toLogInfo "Writing ${agentStateContents} to ${path} file"
+  {
+    printf "%s" "${agentStateContents}" >"${path}.tmp"
+    mv -f "${path}.tmp" "${path}"
+  } 2>>"${LOG_FILE}"
+}
+
+#== 【0】=检查全路径是否可读权限(目录最深100层)
+checkIfPathIsGloballyReadable() {
+  local path="${1}"
+  local sourcePath="${path}"
+  local maxDepth=100
+  while [ "${path}"x != "/"x ]; do
+    #== 【0】=获取文件权限信息
+    local accessRights
+    accessRights="$(arch_getAccessRights "${path}")"
+    if ! printf '%s' "${accessRights}" | cut -c 8-10 | grep -qE "r.[xt]"; then
+      toConsoleError "Insufficient access rights (${accessRights}) on: ${path}"
+      toConsoleError "${sourcePath} path must be globally readable (r-x permissions for others)."
+      toConsoleError "Please adjust the permissions and then retry the installation."
+      finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
+    fi
+
+    path="$(dirname "${path}")"
+
+    maxDepth=$((maxDepth - 1))
+    if [ "${maxDepth}" -eq 0 ]; then
+      toLogWarn "Unable to verify access rights on ${path}"
+      return
+    fi
+  done
+}
+
+#== 【0】=创建 PARAM_INSTALL_DIR -> INSTALL_DIR 软连接
+createSymlinkToInstallLocation() {
+  #== INSTALL_DIR 不能是软链接地址
+  if [ -L "${INSTALL_DIR}" ] && [ ! -e "${INSTALL_DIR}" ]; then
+    toConsoleError "Detected that ${INSTALL_DIR} is a dangling symlink, please remove it and then retry the installation"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== PARAM_INSTALL_DIR 和 INSTALL_DIR 都不能是空地址
+  if [ "${PARAM_INSTALL_DIR}"x = "${INSTALL_DIR}"x ] || [ -z "${PARAM_INSTALL_DIR}" ]; then
+    return
+  fi
+
+  #== INSTALL_DIR 是软连接,并获取 PARAM_INSTALL_DIR 和 INSTALL_DIR 的真实地址
+  if [ -L "${INSTALL_DIR}" ] && [ "$(readLink -m "${PARAM_INSTALL_DIR}")"x = "$(readLink -m "${INSTALL_DIR}")"x ]; then
+    return
+  fi
+
+  #== 目录存在,表示未卸载
+  if [ -e "${INSTALL_DIR}" ]; then
+    toConsoleError "Leftovers from previous agent installation detected"
+    toConsoleError "If you wish to use INSTALL_DIR parameter then perform a cleanup by following these steps:"
+    toConsoleError "1. Uninstall the agent"
+    toConsoleError "2. Restart all applications that have Deep Monitoring enabled (host restart is fine as well)"
+    toConsoleError "3. Remove ${INSTALL_DIR}"
+    toConsoleError "and then retry the installation."
+    toConsoleError "#DEBUG==For further information please visit ${HELP_URL}/command-line-install"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 创建不存在的目录
+  createDirIfNotExistAndSetRights "${PARAM_INSTALL_DIR}" 1775
+  #== 检查全路径是否可读权限(目录最深100层)
+  checkIfPathIsGloballyReadable "${PARAM_INSTALL_DIR}"
+  #== 创建不存在的目录 /opt/cloudwise
+  createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" 755
+
+  #== 创建 PARAM_INSTALL_DIR -> INSTALL_DIR
+  local lnOutput
+  if lnOutput="$(ln -fs "${PARAM_INSTALL_DIR}" "${INSTALL_DIR}" 2>&1)"; then
+    toConsoleInfo "Symlink ${INSTALL_DIR} -> ${PARAM_INSTALL_DIR} created"
+  else
+    toConsoleError "Failed to create symlink ${INSTALL_DIR} -> ${PARAM_INSTALL_DIR}, aborting installation: ${lnOutput}"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== 【5】=修改文件系统用户和用户组
+changeFilesOwnership() {
+  local user
+  local group
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  group="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+
+  toLogInfo "Changing ownership of files to root:${group}"
+  #== /opt/cloudwise/cwserveragent 目录下用户和用户组
+  commandErrorWrapper chown "${user}:${group}" "${AGENT_BASE_DIR}"
+  commandErrorWrapper chown -R "${user}:${group}" "${INSTALL_DIR}"
+  toLogInfo "Recursively changing group ownership of ${AGENT_CONF_DIR} to ${group}"
+
+}
+
+#== 【5】=文件用户权限检查
+fileCapabilitiesCompatibilityCheck() {
+  #== 获取配置用户
+  local user
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 获取OS bin配置路径 /opt/cloudwise/cwserveragent/lib64/cloudwiseosconfig
+  if output="$("$(getOsConfigBinPath)" file-capabilities-compatibility-check "${user}" 2>&1)"; then
+    return 0
+  fi
+
+  if [ "${PARAM_NON_ROOT_MODE}" ]; then
+    toConsoleWarn "Failed to enable non-privileged mode, kernel does not support file capabilities. For details, see: ${LOG_FILE}"
+    toLogWarn "Capabilities test output: ${output}"
+  else
+    toConsoleInfo "Non-privileged mode was not enabled, kernel does not support file capabilities. For details, see: ${LOG_FILE}"
+    toLogInfo "Capabilities test output: ${output}"
+  fi
+  #== 设置删除root权限
+  "$(getAgentInstallActionPath)" "--set-drop-root-privileges" "false" >>"${LOG_FILE}" 2>&1
+  return 1
+}
+
+
+#**********************************************************
+# User and group related functions
+#**********************************************************
+
+#== 【5】=添加用户组
+addGroup() {
+  local group="${1}"
+
+  if groupExistsInSystem "${group}"; then
+    toLogInfo "Group '${group}' already exists"
+    return 0
+  fi
+
+  local errorMessage
+  errorMessage="$(groupadd "${group}" 2>&1)"
+  local returnCode=$?
+
+  case ${returnCode} in
+  0) toLogInfo "Group '${group}' successfully created" ;;
+  9) toLogInfo "Group '${group}' already exists" ;;
+  *)
+    toLogError "Error occured while adding '${group}' group, return code: ${returnCode}, message ${errorMessage}"
+    return 1
+    ;;
+  esac
+  return 0
+}
+
+#== 【5】=添加用户
+addUser() {
+  local user="${1}"
+  local group="${2}"
+  local groupCreated="${3}"
+  local errorMessage
+  local mod="/bin/false"
+  if [ "${PARAM_USER_LOGIN}"x == "true"x ]; then
+    mod="/bin/bash"
+  fi
+  if userExistsInSystem "${user}"; then
+    toLogInfo "User '${user}' already exists."
+    #-- 权限更新
+#    errorMessage="$(usermod -s "${mod}" "${user}" 2>&1)"
+    return 0
+  fi
+
+  if [ "${groupCreated}" -eq 0 ]; then
+    errorMessage="$(useradd -r --shell "${mod}" -g "${group}" "${user}" 2>&1)"
+  else
+    errorMessage="$(useradd -r --shell "${mod}" "${user}" 2>&1)"
+  fi
+
+  local returnCode=$?
+  if [ ${returnCode} -ne 0 ]; then
+    toConsoleError "Failed to create user '${user}'"
+    toLogError "Error occured while adding '${user}' user, return value: ${returnCode}, error message: ${errorMessage}."
+    return 1
+  fi
+
+  toConsoleInfo "User '${user}' added successfully."
+  return 0
+}
+
+#== 【5】=添加用户和用户组信息
+addUserAndGroup() {
+  local user="${1}"
+  local group="${2}"
+  #== 添加用户组
+  addGroup "${group}"
+  #== 添加用户
+  addUser "${user}" "${group}" $?
+}
+
+#== 【5】=配置用户和用户组
+handleUser() {
+  toLogInfo "Processing user and group..."
+  local user
+  local group
+  #== 读取用户名(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-user)
+  user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 读取用户组(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-group)
+  group="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
+  #== 添加用户和用户组信息
+  addUserAndGroup "${user}" "${group}"
+}
+
+#== 【4】=获取agent preLoad 安装路径,并校验是否可执行
+checkCompatibilityWithInstallActionBinary() {
+  local output
+  #== 获取agent preLoad 安装路径,并校验是否可执行
+  output="$("$(getAgentInstallActionPathPreInstallation)" "--sanity-check" 2>&1)"
+  local exitCode=$?
+  toLogAdaptive ${exitCode} "Compatibility check exit code = ${exitCode}, output = ${output}"
+  if [ ${exitCode} -ne 0 ] || [ "${output}"x != "SUCCESS"x ]; then
+    toConsoleError "System compatibility check failed, this may be caused by a problem with glibc, dynamic loader or incompatible operating system version."
+    toConsoleError "Detected version: $(detectLinuxDistribution)"
+    toConsoleError "For a list of supported distributions and versions, see: ${HELP_URL}"
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== 【4】=【部署】解压文件
+extractFiles() {
+  umask 000
+  toConsoleInfo "Extracting..."
+  #== 从sh文件读取压缩文件 tarfile_$$.base64
+  separateExternalTar
+  #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
+  unpackArchive
+  umask 022
+}
+
+#== 【3】=检查发现初始化系统信息(INIT_SYSTEM、INIT_SYSTEM_VERSION、INIT_DIR)
+detectInitSystem() {
+  #== 获取初始化系统信息 (INIT_SYSTEM、INIT_SYSTEM_VERSION)
+  checkInitSystem
+  toLogInfo "Detected init system: ${INIT_SYSTEM}, version: ${INIT_SYSTEM_VERSION}"
+  #== 设置系统初始化脚本目录
+  if ! setLocationOfScripts; then
+    toConsoleError "Cannot determine location of init scripts."
+    finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+}
+
+#== 【4】=【旧配置】读取旧配置参数
+readLegacySetting() {
+  local paramName="${1}"
+  local value
+  value="$(sed -n "s|^${paramName}=||p" "${LEGACY_AGENT_CONF_FILE}" | tr -d '\r' 2>/dev/null)"
+  if [ "${value}" ]; then
+    local valueToPrint="${value}"
+    if [ "${paramName}"x = "${CONF_FIELD_NM_LICENSE}"x ]; then
+      valueToPrint="***"
+    fi
+    toLogInfo "Read legacy value: ${paramName} = ${valueToPrint}"
+  fi
+
+  printf '%s' "${value}"
+}
+
+#== 【4】=【旧配置】迁移旧配置文件
+migrateLegacySettingsFromAgentConf() {
+  toLogInfo "Looking for legacy config to migrate."
+  #== 旧配置文件
+  if [ ! -f "${LEGACY_AGENT_CONF_FILE}" ]; then
+    toLogInfo "Unable to read agent config file, skipping legacy config migration"
+    return
+  fi
+
+  if [ ! "${PARAM_CONFIG_SERVER}" ]; then
+    local configServerValue
+    configServerValue="$(readLegacySetting ${CONF_FIELD_NM_CONFIG_SERVER})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_CONFIG_SERVER}: ${PARAM_CONFIG_SERVER}"
+    if [ "${configServerValue}"x = "http://localhost:8020"x ]; then
+      toLogInfo "Param 'server' has default value set, skipping it"
+    else
+      PARAM_CONFIG_SERVER="${configServerValue}"
+    fi
+  fi
+
+  if [ ! "${PARAM_DATA_SERVER}" ]; then
+    PARAM_DATA_SERVER="$(readLegacySetting ${CONF_FIELD_NM_DATA_SERVER})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_DATA_SERVER}: ${PARAM_DATA_SERVER}"
+  fi
+
+  if [ ! "${PARAM_LICENSE}" ]; then
+    PARAM_LICENSE="$(readLegacySetting ${CONF_FIELD_NM_LICENSE})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_LICENSE}: ${PARAM_LICENSE}"
+  fi
+
+  if [ ! "${PARAM_JSON_CONF}" ]; then
+    PARAM_JSON_CONF="$(readLegacySetting ${CONF_FIELD_NM_JSON_CONF})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_JSON_CONF}: ${PARAM_JSON_CONF}"
+  fi
+
+  if [ ! "${PARAM_USER}" ]; then
+    PARAM_USER="$(readLegacySetting ${CONF_FIELD_NM_USER})"
+    toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_USER}: ${PARAM_USER}"
+
+    if [ ! "${PARAM_GROUP}" ]; then
+      PARAM_GROUP="$(readLegacySetting ${CONF_FIELD_NM_GROUP})"
+      toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_GROUP}: ${PARAM_GROUP}"
+    fi
+  fi
+}
+listProcesses() {
+  local errorMessage="${1}"
+  local includeRegex="${2}"
+
+  local excludeRegex=" grep"
+  if [ "${3}" ]; then
+    excludeRegex="grep|${3}"
+  fi
+
+  toLogInfo "#DEBUG== listProcesses command: ps -e -o \"pid,args\" 2>&1 | grep -E \"${includeRegex}\" | awk '{{ print \$1,\$2 }}' | grep -vE \"${excludeRegex}\""
+  local output
+  if ! output="$(pgrep -f "pid,args" 2>&1 | grep -E "${includeRegex}" | awk '{{ print $1,$2 }}')"; then
+    toLogError "Failed to get ${errorMessage}, output: ${output}"
+    return 1
+  fi
+
+  local foundProcesses
+  foundProcesses="$(printf '%s' "${output}" | grep -vE "${excludeRegex}")"
+  if [ ! "${foundProcesses}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${foundProcesses}" | awk '{{ print $1 }}'
+  return 0
+}
+
+#== 版本&帮助信息
+preParams() {
+  if [ $# -gt 0 ]; then
+    if [ "${1}"x = "-h"x ] || [ "${1}"x = "--help"x ]; then
+        displayHelp
+        exit "${EXIT_CODE_OK}"
+    fi
+
+    if [ "${1}"x = "-v"x ] || [ "${1}"x = "--version"x ]; then
+       pad=20
+       printf "%-${pad}s%s\n" "Version:" "${AGENT_INSTALLER_VERSION}"
+       printf "%-${pad}s%s\n" "Commit:" "${AGENT_BUILD_TAG}"
+       printf "%-${pad}s%s\n" "Build At(UTC):" "${AGENT_BUILD_DATE_INFO}"
+       printf "%-${pad}s%s\n" "Uploader:" "${AGENT_BUILD_UPLOADER}"
+       exit "${EXIT_CODE_OK}"
+    fi
+  fi
+}
+#**********************************************************
+# Main script functions
+#**********************************************************
+
+#== 【0】=初始化安装环境
+initializeInstallation() {
+  preParams "$@"
+  #== 设置PATH
+  setPATH
+  #== 配置umask权限
+  local initialUmask
+  initialUmask="$(umask)"
+  umask 022
+
+  #== 读取配置参数
+#  readParamsSection
+  #== 解析命令行参数
+  parseCommandLineParameters "$@"
+  #== 校验配置参数
+
+  #== 是否存在多个同时安装操作【通过判断 INSTALLER_LOCK_FILE 】
+  if isAnotherInstallationRunning; then
+    #== 结束安装操作
+    finishInstallation "${EXIT_CODE_ANOTHER_INSTALLER_RUNNING}" "keep_lock_file"
+  fi
+
+  #== 创建安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
+  createInstallationLockFile
+  #== 配置是否更新
+  PARAM_UPGRADE="no"
+
+  #== 获取并校验系统兼容性【LINUX/AIX  X86_64/IA64】
+  local platformDetectionString
+  if ! platformDetectionString="$(checkSystemCompatibility)"; then
+    toConsoleError "${platformDetectionString}"
+    finishInstallation "${EXIT_CODE_OS_NOT_SUPPORTED}"
+  fi
+
+  #== 创建 PARAM_INSTALL_DIR -> INSTALL_DIR 软连接
+  createSymlinkToInstallLocation
+  #== 创建日志目录及日志文件installation_$$.log
+  createLogDirsIfMissing
+  #== 配置信号捕获,执行清空安装临时目录
+  configureSignalHandling "cleanInstallationTemporaryFiles"
+  #== 常规日志
+  initializeLog "${@}"
+
+  toLogInfo "Initial umask: ${initialUmask}"
+  toConsoleInfo "${platformDetectionString}"
+  toLogInfo "Distribution: $(detectLinuxDistribution)"
+}
+
+#== 【3】=安装前检查
+preInstallationChecks() {
+  #== 检查发现初始化系统信息(INIT_SYSTEM、INIT_SYSTEM_VERSION、INIT_DIR)
+  detectInitSystem
+
+  #== 检查目录权限
+  checkAccessRightsToDirs
+  #== 创建临时目录
+  prepareTempFolder
+  #== 检查是否已经安装
+  checkIfAlreadyInstalled
+
+  if [ ! "${PARAM_USER}" ] && [ "${ARCH_ARCH}"x != "AIX"x ] ; then
+    #== 配置文件中配置用户和用户组是否存在
+    checkUserAndGroupFromConfig
+  fi
+
+  #== 检查安装目录空间
+  checkInstallPathFreeSpace
+
+}
+
+uninstallAgent() {
+	toConsoleInfo "Agent already installed. Uninstalling previous version."
+#	printf '%s' "upgrade" >"${UNINSTALL_INFO_FILE_LEGACY_PATH}"
+
+	#shellcheck disable=SC2086
+	"${INSTALL_DIR}/uninstall.sh" $$ ${SKIP_PRIVILEGES_CHECK} 2>>"${LOG_FILE}"
+
+	local uninstallExitCode=$?
+	if [ ${uninstallExitCode} -gt 0 ]; then
+		toConsoleError "Error during uninstalling, code: ${uninstallExitCode}. Installation aborted."
+		finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
+	fi
+
+	toConsoleInfo "Agent uninstalled."
+}
+
+#== 【4】=部署文件
+deployFiles() {
+  if [ "${PARAM_UPGRADE}" = "yes" ]; then
+    uninstallAgent
+  fi
+  #== 【部署】解压文件
+  extractFiles
+  setupAll
+  createCurrentVersionSymlink
+}
+enableRootDropping() {
+  local output=
+  if ! isAvailable setcap; then
+    toConsoleWarn "Failed to enable non-privileged mode, kernel does not support file capabilities. Set NON_ROOT_MODE=false."
+    #== writeParamToConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "false" "${LEGACY_AGENT_CONF_FILE}"
+    #== writeParamToConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "false" "${INSTALLER_CONF_FILE}"
+    #== editScriptFileParam "readonly PARAM_NON_ROOT_MODE" "false" "${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE}"
+    return
+  fi
+
+  #== 设置文件权限 (https://www.cnblogs.com/xzongblogs/p/14106481.html)
+  #== CAP_DAC_OVERRIDE:绕过文件的读,写,和执行权限检查。
+  #== CAP_FOWNER:对于通常要求进程的文件系统 UID 与文件的 UID 匹配的操作,绕过权限检查 (比如,chmod(2),utime(2)),除了那些包含在 CAP_DAC_OVERRIDE 和 CAP_DAC_READ_SEARCH 中的操作
+  #== CAP_IPC_LOCK:允许锁定共享内存片段
+  #== CAP_SYS_PTRACE:允许跟踪任何进程
+  #== CAP_SYS_ADMIN:访问特权 perf 事件信息
+  #== CAP_SYS_RESOURCE:忽略资源限制
+  #== CAP_NET_ADMIN:允许执行多种网络有关的操作
+  commandErrorWrapper setcap cap_setgid,cap_setuid,cap_dac_override,cap_fowner,cap_chown,cap_ipc_lock,cap_sys_ptrace,cap_sys_admin,cap_sys_resource,cap_net_admin+ep "${AGENT_BIN_DIR}/${AGENT_PROC}"
+  local setCapCwServerAgentExitCode=$?
+  if [ ${setCapCwServerAgentExitCode} -eq 0 ] ; then
+    toConsoleInfo "Set file capabilities [${AGENT_PROC}]"
+  else
+    toConsoleWarn "Failed to enable non-privileged mode. Exit Code : ${setCapCwServerAgentExitCode} . For details, see: ${LOG_FILE}"
+    toLogWarn "Set file capabilities output: ${output}"
+  fi
+}
+
+#== 【5】=配置安装
+configureInstallation() {
+  #== 配置参数(param、installation.conf)
+  #== 自定义修改配置, sed ,echo ...  参考 applyAgentSettings
+  if [ "${PARAM_TEST}" ]; then
+    toConsoleOnly "Applying test value is: ${PARAM_TEST}"
+  fi
+  #== 获取bool值参数
+  if [ "${PARAM_BOOL}" ]; then
+    toConsoleOnly "Applying bool value is: ${PARAM_BOOL}"
+  fi
+
+
+  if [ "${ARCH_ARCH}"x != "AIX"x ]; then
+    #== 配置用户和用户组
+    if handleUser; then
+      #== 修改文件系统用户和用户组
+      changeFilesOwnership
+    fi
+    #== 设置root权限
+    enableRootDropping
+  fi
+  #== 系统配置(策略配置、dump proc、agent 进程配置、自动启动)
+#  setupAutostart
+}
+
+#== 【6】=验证安装状态、运行启动脚本
+postInstallationSteps() {
+  #== 运行agent
+#  runAgents
+  finishInstallation "${EXIT_CODE_OK}"
+}
+
+readonly CURR_PATH="$(pwd)"
+main() {
+  #== 【0】=初始化安装环境
+  initializeInstallation "$@"
+  #== 【3】=安装前检查
+  preInstallationChecks
+  #== 【4】=部署文件
+  deployFiles
+  #== 【5】=配置安装
+  configureInstallation
+  #== 【6】=验证安装状态、运行启动脚本
+  postInstallationSteps
+
+}
+
+#**********************************************************
+# Script start
+#**********************************************************
+main "$@"
+
+################################################
+############# DO NOT REMOVE THIS ###############
+#### DO NOT ADD ANYTHING BELOW THIS COMMENT ####
+################################################
+#################ENDOFSCRIPTMARK################
+
+----SIGNED-INSTALLER

+ 611 - 0
dist/x86_64/scripts/package.sh

@@ -0,0 +1,611 @@
+#!/bin/bash
+
+AGENT_INSTALLER_VERSION=1.0.0
+
+#== 当前脚本必须放在 smartagent/scripts 目录下
+readonly SCRIPT_PATH=$(dirname $0)
+readonly SCRIPT_DIR=$(cd $SCRIPT_PATH && pwd)
+readonly CURR_FILE_NAME="$(basename "$0")"
+readonly SMARTAGENT_DIR=$(cd $SCRIPT_DIR/../ && pwd)
+readonly SMARTAGENT_PARENT_DIR=$(cd $SCRIPT_DIR/../../ && pwd)
+
+readonly BRAND_FORMAL_NAME="Cloudwise"
+BRAND_PRODUCT_NAME="euspace"
+BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}"
+readonly BRAND_FORMAL_NAME_LOWER="cloudwise"
+readonly BRAND_PRODUCT_NAME_LOWER="cwserveragent"
+readonly BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="ucloudwise"
+
+
+readonly BAK_EXT_NAME=".bak"
+#== cw-serveragent
+readonly SERVICE_SCRIPT_FILE="cw-oneagent"
+readonly XZDEC_NAME="xzdec"
+readonly INSTALL_TEMP_FILE_NAME="install_temp.sh"
+readonly INSTALL_VERSION_FILE_NAME="installer.version"
+#== {productName}-installer-{version}.sh 即 cwserveragent-installer-1.1.0.sh
+ARCH=$(uname -m)
+TARGET_INSTALL_FILE_NAME="${BRAND_AGENT_PRODUCT_NAME}-installer-Linux-${ARCH}-${AGENT_INSTALLER_VERSION}.sh"
+#TARGET_INSTALL_FILE_NAME="${BRAND_PRODUCT_NAME_LOWER}-installer-${AGENT_INSTALLER_VERSION}.sh"
+
+TARGET_INSTALL_TMP_FILE="${SMARTAGENT_PARENT_DIR}/${TARGET_INSTALL_FILE_NAME}.tmp"
+
+readonly LOG_DIR="${SMARTAGENT_PARENT_DIR}/logs"
+readonly LOG_FILE_NAME="release.log"
+readonly LOG_FILE="${LOG_DIR}/${LOG_FILE_NAME}"
+
+#== 【0】=【退出码】执行成功
+readonly EXIT_CODE_OK=0
+readonly EXIT_CODE_GENERIC_ERROR=1
+readonly EXIT_CODE_NOT_ENOUGH_SPACE=6
+readonly EXIT_CODE_NOT_ENOUGH_MEMORY=7
+#== 【0】=无效参数
+readonly EXIT_CODE_INVALID_PARAM=8
+readonly EXIT_CODE_INSUFFICIENT_PERMISSIONS=9
+readonly EXIT_CODE_SEMANAGE_NOT_FOUND=10
+readonly EXIT_CODE_WATCHDOG_ALREADY_RUNNING=11
+#== 【退出码】接收信号
+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_CORRUPTED_PACKAGE=16
+#== 【退出码】管理系统环境变量配置
+readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
+readonly EXIT_CODE_UNSUPPORTED_DOWNGRADE=18
+readonly EXIT_CODE_OS_NOT_SUPPORTED=19
+readonly EXIT_CODE_DEL_DEFAULT_PARAMS=20
+
+readonly LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS=50
+#**********************************************************
+# Logs
+#**********************************************************
+toLogFile() {
+  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() {
+  toLogFile "[INFO]" "$@"
+}
+
+toLogWarn() {
+  toLogFile "[WARN]" "$@"
+}
+
+toLogError() {
+  toLogFile "[ERROR]" "$@"
+}
+
+toLogAdaptive() {
+  local success="${1}"
+  shift
+  if [ "${success}" -eq 0 ]; then
+    toLogInfo "$@"
+  else
+    toLogError "$@"
+  fi
+}
+
+toConsoleInfo() {
+  toConsoleOnly "$@"
+  toLogInfo "$@"
+}
+
+toConsoleWarn() {
+  toConsoleOnly "Warn:" "$@"
+  toLogWarn "$@"
+} >&2
+
+toConsoleError() {
+  toConsoleOnly "Error:" "$@"
+  toLogError "$@"
+} >&2
+
+#**********************************************************
+# compress
+#**********************************************************
+tarSmartAgent() {
+  toConsoleInfo "There are 5 steps to packing, begin package ${BRAND_AGENT_PRODUCT_NAME}...."
+  #== 将打包脚本(package.sh、xzdec、install_temp.sh、smartagent、uninstall.sh)移动到临时目录
+  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
+    mv -f "${SCRIPT_DIR}/${fileNm}" "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" 2>>"${LOG_FILE}"
+  done
+  mv -f "${SCRIPT_DIR}/${XZDEC_NAME}" "${SMARTAGENT_PARENT_DIR}/" 2>>"${LOG_FILE}"
+  cp -f "${SMARTAGENT_PARENT_DIR}/${INSTALL_TEMP_FILE_NAME}${BAK_EXT_NAME}" "${TARGET_INSTALL_TMP_FILE}" 2>>"${LOG_FILE}"
+
+  for fileNm in "uninstall.sh"; do
+    cp -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" "${SCRIPT_DIR}/${fileNm}" 2>>"${LOG_FILE}"
+  done
+
+  #== 删除安装脚本中注释
+  if [ "${PARAM_DEBUG}"x != "true"x ]; then
+    toConsoleInfo "Delete the type [#==] comment ..."
+    sed -i '/#==/d' "${TARGET_INSTALL_TMP_FILE}"
+#    sed -i '/#==/d' "${SCRIPT_DIR}/${SERVICE_SCRIPT_FILE}"
+    sed -i '/#==/d' "${SCRIPT_DIR}/uninstall.sh"
+    toConsoleInfo "Delete the type [#DEBUG==] comment ..."
+    sed -i '/#DEBUG==/d' "${TARGET_INSTALL_TMP_FILE}"
+#    sed -i '/#DEBUG==/d' "${SCRIPT_DIR}/${SERVICE_SCRIPT_FILE}"
+    sed -i '/#DEBUG==/d' "${SCRIPT_DIR}/uninstall.sh"
+  fi
+
+  if [ "${PARAM_RELEASE}"x = "true"x ]; then
+    deleteDefaultParams "${TARGET_INSTALL_TMP_FILE}"
+  fi
+
+  #== 进入 smartagent 目录下
+  cd "${SMARTAGENT_DIR}"
+  cp -f "${SCRIPT_DIR}/uninstall.sh" ./package_dir
+  #== 执行第一阶段压缩(源码压缩)Cloudwise-SmartAgent.tar
+  toConsoleInfo "step【1】start【tar -cpf "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar" ./package_dir/*】to ${BRAND_AGENT_PRODUCT_NAME}.tar"
+  tar -cpf "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar" --exclude="*.gitkeep" --exclude="*.log" ./package_dir/* >>"${LOG_FILE}" 2>&1
+  rm -f "./package_dir/uninstall.sh"
+
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+  local agentTarSize="$(getStorageSize "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar")"
+
+  cd "${SMARTAGENT_PARENT_DIR}"
+  #== 执行第二阶段压缩(源码压缩 Cloudwise-SmartAgent.tar.xz
+  toConsoleInfo "step【2】start【xz -T0 -z ${BRAND_AGENT_PRODUCT_NAME}.tar】to ${BRAND_AGENT_PRODUCT_NAME}.tar.zx"
+  xz -T0 -1 -z "${BRAND_AGENT_PRODUCT_NAME}.tar" -vv
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 执行第三阶段压缩 Cloudwise-SmartAgent.tar.xz xzdec to Cloudwise-SmartAgent.tar
+  toConsoleInfo "step【3】start【tar -cpf ${BRAND_AGENT_PRODUCT_NAME}.tar ${BRAND_AGENT_PRODUCT_NAME}.tar.xz xzdec】 to ${BRAND_AGENT_PRODUCT_NAME}.tar"
+  tar -cpf "${BRAND_AGENT_PRODUCT_NAME}.tar" "${BRAND_AGENT_PRODUCT_NAME}.tar.xz" xzdec >>"${LOG_FILE}" 2>&1
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 执行第四阶段压缩 Cloudwise-SmartAgent.tar to Cloudwise-SmartAgent.tar.base64
+  toConsoleInfo "step【4】start【base64 ${BRAND_AGENT_PRODUCT_NAME}.tar > ${BRAND_AGENT_PRODUCT_NAME}.tar.base64】 to ${BRAND_AGENT_PRODUCT_NAME}.tar.base64"
+  base64 "${BRAND_AGENT_PRODUCT_NAME}.tar" >"${BRAND_AGENT_PRODUCT_NAME}.tar.base64" 2>>"${LOG_FILE}"
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  #== 执行第五阶段将 base64 文件写入安装脚本
+  toConsoleInfo "step【5】start write 【${BRAND_AGENT_PRODUCT_NAME}.tar.base64】 to ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}"
+  #== 设置脚本中版本、创建时间、占用空间信息
+  editInstallScriptParam "${TARGET_INSTALL_TMP_FILE}" ${agentTarSize}
+
+  sed -i "/#################ENDOFSCRIPTMARK################/r ${BRAND_AGENT_PRODUCT_NAME}.tar.base64" "${TARGET_INSTALL_TMP_FILE}"
+  if [ $? -ne 0 ]; then
+    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
+  fi
+
+  toConsoleInfo "${BRAND_AGENT_PRODUCT_NAME} packaging success."
+  finishPackage "${EXIT_CODE_OK}"
+}
+
+buildVersion() {
+  local oldVersion
+  if oldVersion="$(getOldVersion)"; then
+    setInstallVersion "${oldVersion}"
+    removeIfExist "${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}"
+		toConsoleInfo "Delete file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}."
+  fi
+
+  if [ "${PARAM_VERSION}" ]; then
+    setInstallVersion "${PARAM_VERSION}"
+    return
+  fi
+}
+
+setInstallVersion() {
+  local version="${1}"
+  if [ ! "${version}" ]; then
+    toConsoleWarn "Set install version failed,not found version version."
+    return
+  fi
+
+  AGENT_INSTALLER_VERSION="${version}"
+  BRAND_PRODUCT_NAME="${PARAM_NAME}"
+  BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}"
+  TARGET_INSTALL_FILE_NAME="${BRAND_AGENT_PRODUCT_NAME}-installer-Linux-${ARCH}-${AGENT_INSTALLER_VERSION}.sh"
+  #== {productName}-installer-{version}.sh 即 cwserveragent-installer-1.1.0.sh
+#  TARGET_INSTALL_FILE_NAME="${BRAND_PRODUCT_NAME_LOWER}-installer-${AGENT_INSTALLER_VERSION}.sh"
+  TARGET_INSTALL_TMP_FILE="${SMARTAGENT_PARENT_DIR}/${TARGET_INSTALL_FILE_NAME}.tmp"
+}
+
+getOldVersion() {
+	local installVersionFile="${SMARTAGENT_DIR}/installer.version"
+	if [ ! -f "${installVersionFile}" ]; then
+		toLogWarn "Could not find ${installVersionFile} file."
+		return 1
+	fi
+
+	local oldVersion="$(cat "${installVersionFile}")"
+	if [ ! "${oldVersion}" ]; then
+		toLogWarn "Could not read install version from ${installVersionFile} file."
+	  return 1
+  fi
+
+  printf '%s' "${oldVersion}"
+  return 0
+}
+
+#== 通过占位分割读取位置
+locateDelimiter() {
+  #== 占位符
+  local delimiter="${1}"
+  #== 从文件结尾读取行数
+  local linesToReadFromEnd="${2}"
+  local filePath="${3}"
+
+  if [ "${linesToReadFromEnd}" ]; then
+    #== 文件总行数n(实际行数=n+1)
+    local linesCount="$(wc -l "${filePath}" | awk '{print $1}')"
+    #== 从后往前读取【linesToReadFromEnd】行
+    local offset="$(tail -n"${linesToReadFromEnd}" "${filePath}" 2>/dev/null | awk '/^'"${delimiter}"'/ { print NR; exit }')"
+    if [ -n "${offset}" ]; then
+      printf "%d" "$((linesCount - linesToReadFromEnd + offset))"
+    fi
+  else
+    #== 读取占位符所在行(实际行数=n+1)
+    awk '/^'"${delimiter}"'/ { print NR; exit }' "${filePath}"
+  fi
+}
+
+#== 删除安装脚本中默认参数
+deleteDefaultParams() {
+  local filePath="${1}"
+  local sectionName="----PARAMETERS"
+  local begin=$(locateDelimiter "${sectionName}" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS} ${filePath})
+  local end=$(locateDelimiter "${sectionName}--" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS} ${filePath})
+
+  if [ -z "${begin}" ] || [ -z "${end}" ]; then
+    return
+  fi
+
+  toConsoleInfo "Begin delete default params from line ${begin} to ${end}..."
+  local output="$(sed -i "${begin},${end}d" "${filePath}") 2>&1"
+  if [ ! "${output}" ]; then
+    toConsoleError "Delete install script file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME} default params error:${output}"
+    finishPackage "${EXIT_CODE_DEL_DEFAULT_PARAMS}"
+  fi
+  toConsoleInfo "Delete install script file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME} default params success."
+}
+
+#== 设置脚本中版本、创建时间、占用空间信息
+editInstallScriptParam() {
+  local targetFile="${1}"
+  local agentTarSize="${2}"
+  #== 设置版本信息
+  local buildDate="$(date +"%Y-%m-%d")"
+  local buildTag="$(git rev-parse --short HEAD)"
+  local buildDateInfo="$(date +"%Y-%m-%d %H:%M:%S")"
+  local buildUploader="$(hostname)/${USER}"
+  #== 构建日期
+  editScriptFileParam "readonly AGENT_BUILD_DATE" "${buildDate}" "${targetFile}"
+  #== 构建版本
+  editScriptFileParam "readonly AGENT_INSTALLER_VERSION" "${AGENT_INSTALLER_VERSION}" "${targetFile}"
+  #== commitid
+  editScriptFileParam "readonly AGENT_BUILD_TAG" "'${buildTag}'" "${targetFile}"
+  #== 构建日期
+  editScriptFileParam "readonly AGENT_BUILD_DATE_INFO" "'${buildDateInfo}'" "${targetFile}"
+  #== 构建环境信息
+  editScriptFileParam "readonly AGENT_BUILD_UPLOADER" "'${buildUploader}'" "${targetFile}"
+
+  #== 设置占用空间信息
+  local agentDirSize="$(getStorageSize "${SMARTAGENT_DIR}")"
+  local agentBase64FileSize="$(getStorageSize "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar.base64")"
+  local agentInstallFileSize="$(getStorageSize "${TARGET_INSTALL_TMP_FILE}")"
+  local artifactsSize="$((agentBase64FileSize + agentInstallFileSize + agentDirSize))";
+  editScriptFileParam "readonly EXTERNAL_TAR_SIZE" "${agentTarSize}" "${targetFile}"
+  editScriptFileParam "readonly ARTIFACTS_SIZE" "${artifactsSize}" "${targetFile}"
+}
+
+getStorageSize() {
+  local dirName="${1}"
+  if [ ! -e "${dirName}" ]; then
+    printf '%s' "0"
+    return 0
+  fi
+  printf '%s' "$(du -sb "${dirName}" | awk '{print $1}')"
+}
+
+finishFinally() {
+  #== 将打包脚本文件移动到当前目录下
+  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
+    if [ -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" ]; then
+      mv -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" "${SCRIPT_DIR}/${fileNm}" 2>>"${LOG_FILE}"
+    fi
+  done
+  removeIfExist "${SMARTAGENT_DIR}/uninstall.sh"
+  if [ -f "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}" ]; then
+    mv -f "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}" "${SCRIPT_DIR}/" 2>>"${LOG_FILE}"
+  fi
+
+  if [ -f "${TARGET_INSTALL_TMP_FILE}" ]; then
+    mv -f "${TARGET_INSTALL_TMP_FILE}" "${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}" 2>>"${LOG_FILE}"
+  fi
+
+  if [ "${PARAM_DEBUG}"x != "true"x ]; then
+    for fileNmExt in "tar" "tar.xz" "tar.base64"; do
+      removeIfExist "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.${fileNmExt}"
+    done
+  fi
+
+
+}
+
+removeIfExist() {
+  local filePath="${1}"
+  if [ ! -e "${filePath}" ]; then
+    return
+  fi
+  rm -rf "${filePath}" 2>>"${LOG_FILE}"
+}
+
+deleteParentTmpFile() {
+  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
+    removeIfExist "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}"
+  done
+  removeIfExist "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}"
+  removeIfExist "${TARGET_INSTALL_TMP_FILE}"
+
+  for fileNmExt in "tar" "tar.xz" "tar.base64"; do
+    removeIfExist "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.${fileNmExt}"
+  done
+}
+
+#**********************************************************
+# Param
+#**********************************************************
+PARAM_DEBUG=false
+PARAM_RELEASE=false
+#PARAM_VERSION=1.1.0
+PARAM_NAME=euspace
+PARAM_AGENT_PROC=$PARAM_NAME
+PARAM_CONFIG_PATH=
+
+#== 大小写转化,并返回判断结果
+istrcmp() {
+  local s1="$(printf '%s' "${1}" | tr '[:upper:]' '[:lower:]')"
+  local s2="$(printf '%s' "${2}" | tr '[:upper:]' '[:lower:]')"
+  [ "${s1}"x = "${s2}"x ]
+}
+
+isParamTrue() {
+  [ "${1}"x = "1"x ] || [ "${1}"x = "true"x ] || [ "${1}"x = "enable"x ] || [ "${1}"x = "yes"x ]
+}
+
+isParamFalse() {
+  [ "${1}"x = "0"x ] || [ "${1}"x = "false"x ] || [ "${1}"x = "disable"x ] || [ "${1}"x = "no"x ]
+}
+
+#== 获取参数值
+getParamValue() {
+  local paramName="${1}"
+  local input="${2}"
+  local paramNameLength="${#paramName}"
+  paramNameLength=$((paramNameLength + 1))
+
+  local partParam="$(expr substr "${input}" 1 ${paramNameLength})"
+  if ! istrcmp "${partParam}" "${paramName}="; then
+    return 1
+  fi
+
+  local valueSeparator=$((paramNameLength + 1))
+  local value="$(expr substr "${input}" ${valueSeparator} 1000)"
+  if [ -z "${value}" ]; then
+    return 1
+  fi
+
+  printf '%s' "${value}"
+  return 0
+}
+
+#== 获取bool参数
+readBoolParam() {
+  local value=
+  if value="$(getParamValue "${1}" "${2}")"; then
+    if isParamFalse "${value}"; then
+      printf "false"
+      return 0
+    fi
+    if isParamTrue "${value}"; then
+      printf "true"
+      return 0
+    fi
+  fi
+
+  return 1
+}
+
+#== 解析命令行中参数
+parseCommandLineParameters() {
+  while [ $# -gt 0 ]; do
+    local param="${1}"
+    local value=
+
+    if value=$(getParamValue RELEASE "${param}"); then
+      PARAM_RELEASE="${value}"
+      printParamMessage "RELEASE" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue VERSION "${param}"); then
+      PARAM_VERSION="${value}"
+      printParamMessage "VERSION" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue NAME "${param}"); then
+      PARAM_NAME="${value}"
+      printParamMessage "NAME" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue CONFIG "${param}"); then
+      PARAM_CONFIG_PATH="${value}"
+      printParamMessage "CONFIG" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(getParamValue PROC "${param}"); then
+      PARAM_AGENT_PROC="${value}"
+      printParamMessage "PROC" "${value}"
+      shift
+      continue
+    fi
+
+    if value=$(readBoolParam DEBUG "${param}"); then
+      PARAM_DEBUG="${value}"
+      printParamMessage "DEBUG" "${value}"
+      shift
+      continue
+    fi
+
+    if [ "${param}"x = "-h"x ] || [ "${param}"x = "--help"x ]; then
+      displayHelp
+      finishPackage "${EXIT_CODE_OK}"
+    fi
+
+    if [ "${param}"x = "-v"x ] || [ "${param}"x = "--version"x ]; then
+      printf "%s\n" "${AGENT_INSTALLER_VERSION}"
+      finishPackage "${EXIT_CODE_OK}"
+    fi
+
+    toConsoleError "Unrecognized parameter: ${param}"
+
+    displayHelp
+    finishPackage "${EXIT_CODE_INVALID_PARAM}"
+  done
+}
+
+displayHelp() {
+  printf '\n'
+  printf '%s\n' "Usage: "${CURR_FILE_NAME}" [-h] [-v] [NAME=pluginName] [PROC=mainProcess] [RELEASE=true|false] [DEBUG=true|false] [VERSION=1.0]"
+  printf '\n\n'
+
+  local pad=15
+  printf "%-${pad}s%s\n" "-h, --help" "Display this help and exit."
+  printf "%-${pad}s%s\n" "-v, --version" "Print version and exit."
+  printf '\n'
+  printf "%-${pad}s%s\n" "RELEASE" "Default true; Whether to delete the publish parameter in the script."
+  printf "%-${pad}s%s\n" "VERSION" "Configure the ${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME} version."
+  printf "%-${pad}s%s\n" "NAME" "Setting agent name like 'bash ./scripts/package.sh NAME=pluginName PROC=mainProcess'"
+  printf "%-${pad}s%s\n" "PROC" "Setting agent main process name."
+  printf "%-${pad}s%s\n" "DEBUG" "Default false; 1、Debug mode executed script ${CURR_FILE_NAME};"
+  printf "%-${pad}s%s\n" "" "2、Remove the debug log from the scripts (${TARGET_INSTALL_FILE_NAME}、${SERVICE_SCRIPT_FILE}、uninstall.sh)."
+}
+
+#== 完成安装后清理临时目录
+finishPackage() {
+  finishFinally
+  toLogInfo "Installation finished, PID $$, exit code: ${1}."
+  exit "${1}"
+}
+
+printParamMessage() {
+  local paramNm="${1}"
+  local paramValue="${2}"
+  toConsoleInfo "---> Parameter ${paramNm}=${paramValue}."
+}
+
+#**********************************************************
+# SELinux related functions
+#**********************************************************
+#== 修改scripts/smartagent脚本配置信息
+editScriptFileParam() {
+  local key="${1}"
+  local newValue="${2}"
+  local file="${3}"
+
+  local value="$(sed -n "s|^${key}=||p" "${file}" 2>/dev/null)"
+  toConsoleInfo "---> edit ${key}=${value} to ${key}=${newValue}, configFile: ${file}"
+  if [ "${value}" ]; then
+    sed -i "s|^${key}=.*|${key}=${newValue}|" "${file}" 2>/dev/null
+  fi
+}
+
+#== 信号捕获,并执行回调函数
+signalHandler() {
+  local signal="${1}"
+  local callback="${2}"
+  toLogWarn "process received signal: ${signal}"
+  ${callback} "${signal}"
+  exit ${EXIT_CODE_SIGNAL_RECEIVED}
+}
+
+#== 配置信号捕获和回调
+configureSignalHandling() {
+  local callback="${1}"
+  for signal in HUP INT QUIT ABRT ALRM TERM; do
+    #== shellcheck disable=SC2064
+    trap "signalHandler ${signal} ${callback}" ${signal}
+  done
+
+  trap "" PIPE
+}
+
+#**********************************************************
+# main
+#**********************************************************
+main() {
+  mkdir -p "${LOG_DIR}"
+  echo "" >"${LOG_FILE}"
+
+  toConsoleInfo "package script run path: ${SCRIPT_DIR}"
+  toConsoleInfo "package logs path: ${LOG_DIR}"
+
+  chmod +x ${SCRIPT_DIR}/*
+
+  #== 解析命令行参数
+  parseCommandLineParameters "$@"
+  toConsoleInfo "-----params PARAM_RELEASE: ${PARAM_RELEASE}, PARAM_DEBUG: ${PARAM_DEBUG}, PARAM_VERSION: ${PARAM_VERSION}"
+
+  configureSignalHandling "finishFinally"
+
+  #== 设置 package 插件名
+  editScriptFileParam "BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/package.sh"
+  #== 设置 install 插件名
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/install_temp.sh"
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/install_temp.sh"
+  #== 设置 agentctl 插件名(存在时)
+  if [ -f "${SMARTAGENT_DIR}/package_dir/bin/agentctl" ];then
+    editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+    editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+  #== 设置 agentctl 配置文件路径(存在时)
+    editScriptFileParam "readonly AGENT_CONFIG_PATH" "\"${PARAM_CONFIG_PATH}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+  fi
+
+  #== 设置 uninstall 插件名
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/uninstall.sh"
+  editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/uninstall.sh"
+  #== 设置主进程名
+  if [ -n "${PARAM_AGENT_PROC}" ]; then
+    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SCRIPT_DIR}/install_temp.sh"
+    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SCRIPT_DIR}/uninstall.sh"
+    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
+  fi
+  buildVersion
+  toConsoleInfo "-----Write release version ${AGENT_INSTALLER_VERSION} to ${SMARTAGENT_DIR}/${INSTALL_VERSION_FILE_NAME} file."
+  echo "${AGENT_INSTALLER_VERSION}">"${SMARTAGENT_DIR}/${INSTALL_VERSION_FILE_NAME}"
+
+  #== 修改uninstall.sh 版本
+  editScriptFileParam "readonly AGENT_INSTALLER_VERSION" "${AGENT_INSTALLER_VERSION}" "${SCRIPT_DIR}/uninstall.sh"
+
+  deleteParentTmpFile
+
+  #== 压缩 并生成安装脚本
+  tarSmartAgent
+}
+
+main "$@"

+ 1116 - 0
dist/x86_64/scripts/uninstall.sh

@@ -0,0 +1,1116 @@
+#!/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 heartbeat"
+  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 "$@"

BIN
dist/x86_64/scripts/xzdec