uninstall.sh 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. #!/bin/bash
  2. #==脚本执行中遇到不存在的变量就报错
  3. set -o nounset
  4. #==脚本执行中报错即刻退出
  5. set -o errexit
  6. #==脚本执行只要一个子命令失
  7. set -o pipefail
  8. readonly BRAND_FORMAL_NAME="Cloudwise"
  9. readonly BRAND_PRODUCT_NAME="euspace"
  10. #== 根路径
  11. readonly BRAND_PARENT_PRODUCT_NAME="omniagent"
  12. readonly BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME}"
  13. readonly BRAND_FORMAL_NAME_LOWER="cloudwise"
  14. readonly BRAND_PRODUCT_NAME_LOWER="euspace"
  15. readonly BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="cloudwise"
  16. #== **********************************************************
  17. #== 配置重要文件名称
  18. #== **********************************************************
  19. #== smartagentd
  20. readonly AGENT_PROC="euspace"
  21. readonly AGENT_INSTALLER_VERSION=1.0.0
  22. #== **********************************************************
  23. #== 配置目录
  24. #== **********************************************************
  25. readonly INSTALL_BASE=/opt
  26. #== /opt/cloudwise/omniagent/agents 目录
  27. readonly BASE_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents
  28. #== cloudwise/omniagent/agents/agent
  29. readonly INSTALL_FOLDER=${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents/${BRAND_PRODUCT_NAME_LOWER}
  30. #== cloudwise/omniagent/agents/agent/version
  31. readonly INSTALL_VERSION_FOLDER=${INSTALL_FOLDER}/${AGENT_INSTALLER_VERSION}
  32. #== /opt/cloudwise/omniagent/agents/agent/version
  33. readonly INSTALL_DIR=${INSTALL_BASE}/${INSTALL_VERSION_FOLDER}
  34. #== /opt/cloudwise/omniagent/agents/agent
  35. readonly AGENT_BASE_DIR=${INSTALL_BASE}/${INSTALL_FOLDER}
  36. readonly CURRENT_VERSION_LINK=${AGENT_BASE_DIR}/current
  37. #== /opt/cloudwise/omniagent/conf
  38. readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
  39. readonly AGENT_LIBS_DIR="${INSTALL_DIR}/libs"
  40. #== agent 初始化脚本目录 /opt/cloudwise/omniagent/scripts
  41. readonly AGENT_SCRIPTS_DIR="${INSTALL_DIR}/scripts"
  42. #== agent 初始化脚本目录 /opt/cloudwise/omniagent/bin
  43. readonly AGENT_BIN_DIR="${INSTALL_DIR}/bin"
  44. readonly AGENT_AGENTS_DIR="${INSTALL_DIR}/agents"
  45. readonly AGENT_RUNTIME_DIR="${INSTALL_DIR}/runtime"
  46. readonly PERL_FILE="/usr/bin/perl"
  47. readonly SAFE_RM_FILE="safe-rm"
  48. readonly SAFE_RM_BIN="${AGENT_BIN_DIR}/${SAFE_RM_FILE}"
  49. if [ -f ${PERL_FILE} ] && [ -f "${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/bin/${SAFE_RM_FILE}" ]; then
  50. readonly SAFE_RM_EXEC="${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/bin/${SAFE_RM_FILE}"
  51. else
  52. readonly SAFE_RM_EXEC="rm"
  53. fi
  54. readonly LOG_DIR_NAME=logs
  55. #== /opt/cloudwise/omniagent/logs
  56. readonly LOG_DIR=${INSTALL_DIR}/${LOG_DIR_NAME}
  57. #== /var/log/cloudwise/omniagent/
  58. readonly INSTALLER_LOG_DIR="/var/log/${INSTALL_FOLDER}"
  59. #readonly INSTALLER_LOG_SUBDIR="installer"
  60. ##== /opt/cloudwise/smartagent/log/installer
  61. #readonly INSTALLER_LOG_DIR=${LOG_DIR}/${INSTALLER_LOG_SUBDIR}
  62. readonly AGENT_PID_FILE="${INSTALL_DIR}/bin/${AGENT_PROC}.pid"
  63. #== 【0】=
  64. readonly INSTALLER_LOCK_FILE="/tmp/${BRAND_FORMAL_NAME_LOWER}_${BRAND_PRODUCT_NAME_LOWER}.lock"
  65. readonly INIT_SYSTEM_SYSV="SysV"
  66. #== 系统 systemd
  67. readonly INIT_SYSTEM_SYSTEMD="systemd"
  68. #== cw-serveragent
  69. readonly SERVICE_SCRIPT_FILE="cw-oneagent"
  70. #== cw-serveragent.service
  71. readonly SYSTEMD_UNIT_FILE_AGENT="${SERVICE_SCRIPT_FILE}.service"
  72. #== 系统文件目录
  73. readonly SYSTEMD_UNIT_FILES_DIR="/etc/systemd/system/"
  74. readonly EXIT_CODE_OK=0
  75. readonly EXIT_CODE_GENERIC_ERROR=1
  76. readonly EXIT_CODE_SIGNAL_RECEIVED=12
  77. readonly EXIT_CODE_ANOTHER_INSTALLER_RUNNING=13
  78. readonly EXIT_CODE_AGENT_CONTAINER_RUNNING=14
  79. readonly EXIT_CODE_GLIBC_VERSION_TOO_LOW=15
  80. readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
  81. readonly USER="root"
  82. readonly GROUP="root"
  83. #== 非root模式
  84. readonly PARAM_NON_ROOT_MODE=false
  85. readonly CONTAINER_DEPLOYMENT_STATE_ENTRY=false
  86. #== 是否有 SELinux
  87. readonly ARCH_HAS_SELINUX=true
  88. ################################################################################
  89. # Logs
  90. ################################################################################
  91. toLog() {
  92. if [ -e "${LOG_FILE}" ]; then
  93. printf '%s UTC %s\n' "$(date -u +"%Y-%m-%d %H:%M:%S")" "$*" >>"${LOG_FILE}" 2>/dev/null
  94. fi
  95. }
  96. toConsoleOnly() {
  97. printf '%s %s\n' "$(date +"%H:%M:%S")" "$*" 2>/dev/null
  98. }
  99. toLogInfo() {
  100. toLog "[INFO]" "$@"
  101. }
  102. toLogWarning() {
  103. toLog "[WARN]" "$@"
  104. }
  105. toLogError() {
  106. toLog "[ERROR]" "$@"
  107. }
  108. toLogAdaptive() {
  109. local success="${1}"
  110. shift
  111. if [ "${success}" -eq 0 ]; then
  112. toLogInfo "$@"
  113. else
  114. toLogError "$@"
  115. fi
  116. }
  117. toConsoleInfo() {
  118. toConsoleOnly "$@"
  119. toLogInfo "$@"
  120. }
  121. toConsoleWarning() {
  122. toConsoleOnly "Warning:" "$@"
  123. toLogWarning "$@"
  124. } >&2
  125. toConsoleError() {
  126. toConsoleOnly "Error:" "$@"
  127. toLogError "$@"
  128. } >&2
  129. createDirIfNotExistAndSetRights() {
  130. local dir="${1}"
  131. local rights="${2}"
  132. if [ ! -d "${dir}" ]; then
  133. toLogInfo "Creating directory ${dir} with rights ${rights}"
  134. local message
  135. if ! message="$(mkdir -p "${dir}" 2>&1)"; then
  136. toConsoleWarning "Cannot create ${dir} directory."
  137. toLogWarning "Error message: ${message}"
  138. return 1
  139. fi
  140. fi
  141. if ! message="$(chmod "${rights}" "${dir}" 2>&1)"; then
  142. toConsoleWarning "Cannot change permisions of ${dir} directory to ${rights}."
  143. toLogWarning "Error message: ${message}"
  144. return 1
  145. fi
  146. return 0
  147. }
  148. #== 创建日志目录及日志文件installation_$$.log
  149. createLogDirsIfMissing() {
  150. createDirIfNotExistAndSetRights "${INSTALL_BASE}" u+rwx,g+rx,o+rx
  151. createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" u+rwx,g+rx,o+rx
  152. createDirIfNotExistAndSetRights "${INSTALL_DIR}" 1775
  153. createDirIfNotExistAndSetRights "${LOG_DIR}" 1777
  154. createDirIfNotExistAndSetRights "${INSTALLER_LOG_DIR}" 1777
  155. # for agentLog in ${PLUGIN_LOG_NAMES}; do
  156. # createDirIfNotExistAndSetRights "${LOG_DIR}/${agentLog}" 1777
  157. # done
  158. touch "${LOG_FILE}"
  159. setRightsForFiles "${LOG_FILE}" 766
  160. }
  161. ################################################################################
  162. # Platform characteristics detection
  163. ################################################################################
  164. #== 设置文件可执行权限
  165. setRightsForFiles() {
  166. local file="${1}"
  167. local perms="${2}"
  168. if [ -f "${file}" ]; then
  169. chmod "${perms}" "${file}"
  170. elif [ -d "${file}" ]; then
  171. chmod -R "${perms}" "${file}"
  172. fi
  173. }
  174. #== 安装类型(f:文件,d:目录)递归设置权限
  175. chmod4FilesRecursively() {
  176. local dir="${1}"
  177. local type="${2}"
  178. local mask="${3}"
  179. find "${dir}" -type "${type}" -exec chmod "${mask}" {} \;
  180. }
  181. detectLinuxDistribution() {
  182. if [ -f /etc/redhat-release ]; then
  183. cat /etc/redhat-release
  184. elif [ -f /etc/os-release ]; then
  185. (
  186. . /etc/os-release
  187. local distrib="${NAME}"
  188. if [ -z "${distrib}" ]; then
  189. distrib="${ID}"
  190. fi
  191. local version="${VERSION_ID}"
  192. if printf "%s" "${distrib}" | grep -iq "debian"; then
  193. version="$(cat /etc/debian_version)"
  194. fi
  195. printf "%s %s" "${distrib}" "${version}"
  196. )
  197. elif [ -f /etc/SuSE-release ]; then
  198. head -1 /etc/SuSE-release
  199. elif [ -f /etc/lsb-release ]; then
  200. (
  201. . /etc/lsb-release
  202. printf "%s %s" "${DISTRIB_ID}" "${DISTRIB_RELEASE}"
  203. )
  204. elif ls /etc/*release* >/dev/null 2>&1; then
  205. # Generic fallback
  206. cat /etc/*release*
  207. else
  208. printf "AIX %s" "$(oslevel -s 2>&1)"
  209. fi
  210. }
  211. checkInitSystem() {
  212. local version
  213. if version="$(systemctl --version 2>&1)"; then
  214. if [ -d "${SYSTEMD_UNIT_FILES_DIR}" ]; then
  215. readonly INIT_SYSTEM=${INIT_SYSTEM_SYSTEMD}
  216. else
  217. readonly INIT_SYSTEM=${INIT_SYSTEM_SYSV}
  218. toLogWarning "${INIT_SYSTEM_SYSTEMD} was detected but ${SYSTEMD_UNIT_FILES_DIR} does not exist, using ${INIT_SYSTEM_SYSV} handling as a fallback"
  219. fi
  220. else
  221. readonly INIT_SYSTEM=${INIT_SYSTEM_SYSV}
  222. if ! version="$(init --version 2>&1)"; then
  223. if ! version="$(chkconfig --version 2>&1)"; then
  224. version="$(head -n1 /etc/inittab 2>&1)"
  225. fi
  226. fi
  227. fi
  228. readonly INIT_SYSTEM_VERSION="$(printf '%s' "${version}" 2>/dev/null | head -n1)"
  229. }
  230. setLocationOfInitScripts() {
  231. toLogInfo "Determining location of init scripts..."
  232. if [ "${INIT_SYSTEM}" = "${INIT_SYSTEM_SYSTEMD}" ] || [ "${ARCH_ARCH}" = "AIX" ]; then
  233. readonly INIT_DIR="${AGENT_SCRIPTS_DIR}"
  234. else
  235. if [ -d "/etc/init.d" ]; then
  236. readonly INIT_DIR="/etc/init.d"
  237. elif [ -d "/sbin/init.d" ]; then
  238. readonly INIT_DIR="/sbin/init.d"
  239. elif [ -d "/etc/rc.d" ]; then
  240. readonly INIT_DIR="/etc/rc.d"
  241. else
  242. return 1
  243. fi
  244. fi
  245. toLogInfo "Location of init scripts ${INIT_DIR}"
  246. return 0
  247. }
  248. detectArchitecture() {
  249. local detected_arch=
  250. if isAvailable arch; then
  251. detected_arch="$(arch | tr '[:lower:]' '[:upper:]')"
  252. fi
  253. if [ -z "${detected_arch}" ]; then
  254. detected_arch="$(uname -m | tr '[:lower:]' '[:upper:]')"
  255. fi
  256. printf '%s' "${detected_arch}"
  257. }
  258. ################################################################################
  259. # Misc functions
  260. ################################################################################
  261. getAgentCtlBinPath() {
  262. printf "%s" "${AGENT_TOOLS_DIR}/lib64/${AGENT_CTL_BIN}"
  263. }
  264. getOsConfigBinPath() {
  265. printf "%s" "${AGENT_INSTALL_DIR}/lib64/${AGENT_OS_CONFIG_BIN}"
  266. }
  267. commandErrorWrapper() {
  268. set +e
  269. local command="${*}"
  270. local errorFile="/tmp/smartagent_commanderror_$$"
  271. ${command} 2>"${errorFile}"
  272. local returnCode=$?
  273. if [ ${returnCode} -ne 0 ]; then
  274. toLogWarning "Command '${command}' failed, return code: ${returnCode}, message: $(cat "${errorFile}")"
  275. fi
  276. ${SAFE_RM_EXEC} -f "${errorFile}"
  277. set -e
  278. return ${returnCode}
  279. }
  280. checkRootAccess() {
  281. toConsoleInfo "Checking root privileges..."
  282. if [ "$(id -u)" != "0" ]; then
  283. toConsoleError "NOT OK"
  284. return 1
  285. fi
  286. toConsoleInfo "OK"
  287. return 0
  288. }
  289. removeIfExists() {
  290. local pathToRemove="${1}"
  291. toLogInfo "${SAFE_RM_EXEC} -rf ${pathToRemove}"
  292. if [ ! -e "${pathToRemove}" ]; then
  293. toLogInfo "${pathToRemove} does not exist, skipping removal"
  294. return
  295. fi
  296. local output
  297. if ! output="$(${SAFE_RM_EXEC} -rf "${pathToRemove}" 2>&1)"; then
  298. toLogWarning "Failed to remove ${pathToRemove}: ${output}"
  299. fi
  300. }
  301. ################################################################################
  302. # SELinux related functions
  303. ################################################################################
  304. executeUsingOsConfigBin() {
  305. local command="${1}"
  306. local unit="${2}"
  307. if [ "${unit}" ]; then
  308. command="${command}-${unit}"
  309. unit=""
  310. fi
  311. local output=
  312. output="$("$(getOsConfigBinPath)" "${command}" 2>&1)"
  313. local exitCode=$?
  314. toLogAdaptive ${exitCode} "Executed $(getOsConfigBinPath) ${command} ${unit}, exitCode = ${exitCode}, output: ${output}"
  315. return ${exitCode}
  316. }
  317. executeSystemctlCommand() {
  318. local command="${1}"
  319. local unit="${2}"
  320. if [ "$(id -u)" != 0 ]; then
  321. executeUsingOsConfigBin "${command}" "${unit}"
  322. return $?
  323. fi
  324. local output=
  325. #== shellcheck disable=SC2086
  326. output="$(systemctl "${command}" ${unit} 2>&1)"
  327. local exitCode=$?
  328. if [ ${exitCode} -eq 0 ]; then
  329. toLogInfo "Successfully executed: systemctl ${command} ${unit}"
  330. else
  331. toLogError "Failed to execute: systemctl ${command} ${unit}"
  332. toLogError "Command output: ${output}"
  333. if [ -n "${unit}" ]; then
  334. local reachBackNumSeconds=360
  335. toLogError "journalctl output: $(journalctl -u "${unit}" --since=-${reachBackNumSeconds} 2>&1)"
  336. fi
  337. fi
  338. return ${exitCode}
  339. } 2>>"${LOG_FILE}"
  340. executeInitScriptCommand() {
  341. local command=
  342. local parameters="$*"
  343. local output=
  344. local exitCode=
  345. if isAvailable service; then
  346. command="service"
  347. parameters="${SERVICE_SCRIPT_FILE} ${parameters}"
  348. else
  349. command="${INIT_DIR}/${SERVICE_SCRIPT_FILE}"
  350. fi
  351. #shellcheck disable=SC2086
  352. output="$("${command}" ${parameters} 2>&1)"
  353. exitCode=$?
  354. toLogAdaptive ${exitCode} "Executed ${command} ${parameters}, exitCode = ${exitCode}, output: ${output}"
  355. return ${exitCode}
  356. }
  357. signalHandler() {
  358. end_exit_code=$?
  359. if [ ${end_exit_code} -eq ${EXIT_CODE_SIGNAL_RECEIVED} ]; then
  360. return
  361. fi
  362. local signal="${1}"
  363. local callback="${2}"
  364. if [ ${end_exit_code} -ne 0 ]; then
  365. toLogWarning "Process Received [Signal: ${signal}] [Code : ${end_exit_code}]"
  366. fi
  367. ${callback} ${end_exit_code}
  368. if [ ${end_exit_code} -eq ${EXIT_CODE_OK} ]; then
  369. exit ${EXIT_CODE_OK}
  370. fi
  371. exit ${EXIT_CODE_SIGNAL_RECEIVED}
  372. }
  373. configureSignalHandling() {
  374. local callback="${1}"
  375. for signal in HUP INT QUIT ABRT ALRM TERM EXIT; do
  376. # shellcheck disable=SC2064
  377. trap "signalHandler '${signal}' '${callback}'" ${signal}
  378. done
  379. trap "" PIPE
  380. }
  381. removeSecretsFromString() {
  382. printf "%s" "$*" | sed 's#\(Api-Token=\)[[:alnum:]_-]\{21\}#\1***#' |
  383. sed 's#\(TENANT_TOKEN=\)[[:alnum:]]\{16\}#\1***#' |
  384. sed 's#\(latest/\)[[:alnum:]]\{16\}#\1***#' |
  385. sed 's#\(PROXY=\)[^[:space:]]*#\1***#'
  386. }
  387. #== waitTime must be divisible by 10
  388. sendSignalToProcessAndWaitForStop() {
  389. local pidCheckingFunction="${1}"
  390. local signal="${2}"
  391. local action="${3}"
  392. local waitTime="${4}"
  393. local pidToStop="${5}"
  394. if ! ${pidCheckingFunction} "${pidToStop}"; then
  395. toLogInfo "Process with pid ${pidToStop} doesn't exist"
  396. return
  397. fi
  398. toConsoleInfo "Waiting ${waitTime} seconds for process with pid ${pidToStop} to ${action}."
  399. while [ "${waitTime}" -gt 0 ]; do
  400. if [ "$((waitTime % 10))" -eq 0 ]; then
  401. toLogInfo "Sending signal: ${signal} to ${pidToStop}"
  402. kill -s "${signal}" "${pidToStop}" 2>>"${LOG_FILE}"
  403. fi
  404. if ! ${pidCheckingFunction} "${pidToStop}"; then
  405. return 0
  406. fi
  407. sleep 1
  408. waitTime=$((waitTime - 1))
  409. done
  410. return 1
  411. }
  412. testWriteAccessToDir() {
  413. local errorFile="/tmp/smartagent_commandError_$$"
  414. local dir="${1}"
  415. local tmpfilename
  416. if [ "${ARCH_ARCH}" = "AIX" ]; then
  417. tmpfilename="${dir}/.tmp_${BRAND_PRODUCT_NAME_LOWER}.$$${RANDOM}"
  418. touch "${tmpfilename}" 2>"${errorFile}"
  419. else
  420. tmpfilename="$(mktemp -p "${dir}" ".tmp_${BRAND_PRODUCT_NAME_LOWER}.XXXXXXXXXXXXXX" 2>"${errorFile}")"
  421. fi
  422. #shellcheck disable=SC2181
  423. if [ $? -ne 0 ]; then
  424. toLogInfo "$(cat "${errorFile}")"
  425. ${SAFE_RM_EXEC} -f "${errorFile}"
  426. return 1
  427. fi
  428. ${SAFE_RM_EXEC} -f "${tmpfilename}" "${errorFile}"
  429. return 0
  430. }
  431. setPATH() {
  432. local prependToPATH="/usr/sbin:/usr/bin:/sbin:/bin"
  433. if [ "${PATH}" ]; then
  434. PATH=${prependToPATH}:${PATH}
  435. else
  436. PATH=${prependToPATH}
  437. fi
  438. }
  439. systemLibDirSanityCheck() {
  440. local dir="${1}"
  441. if [ ! -d "${dir}" ]; then
  442. toLogWarning "Directory: ${dir} does not exist"
  443. printf ""
  444. return
  445. fi
  446. if ! testWriteAccessToDir "${dir}"; then
  447. toLogWarning "Detected that ${dir} is not writable"
  448. dir="${PA_FALLBACK_INSTALLATION_DIR}${dir}"
  449. createDirIfNotExistAndSetRights "${dir}" 755
  450. fi
  451. printf "%s" "${dir}"
  452. }
  453. isNonRootModeEnabled() {
  454. printf '%s' "${PARAM_NON_ROOT_MODE}" | grep -qE "(true|no_ambient)"
  455. }
  456. runAutostartAddingTool() {
  457. local prefix="${1}"
  458. local file="${2}"
  459. local suffix="${3}"
  460. local output
  461. if isNonRootModeEnabled && printf '%s' "${prefix}" | grep -q "chkconfig"; then
  462. local action="chkconfig-add"
  463. if printf '%s' "${prefix}" | grep -q -- "--del"; then
  464. action="chkconfig-del"
  465. fi
  466. toLogInfo "Using ${AGENT_OS_CONFIG_BIN} ${action}-${file} to modify autostart"
  467. output="$("$(getOsConfigBinPath)" "${action}-${file}" 2>&1)"
  468. else
  469. local command="${prefix}${file} ${suffix}"
  470. toLogInfo "Executing ${command}"
  471. output="$(${command} 2>&1)"
  472. fi
  473. local status=$?
  474. if [ "${output}" ]; then
  475. toLogAdaptive ${status} "${output}"
  476. fi
  477. return ${status}
  478. }
  479. readLinkFromLs() {
  480. local path="${1}"
  481. local result="${path}"
  482. local lsOutput="$(ls -dl "${path}" 2>/dev/null)"
  483. if printf '%s' "${lsOutput}" | grep -q " -> "; then
  484. local parsedLinkTarget="$(printf '%s' "${lsOutput}" | sed 's|^.* -> ||')"
  485. if [ "${parsedLinkTarget}" ]; then
  486. result="${parsedLinkTarget}"
  487. else
  488. toLogWarning "Failed to parse ls output '${lsOutput}'"
  489. fi
  490. fi
  491. printf '%s' "${result}"
  492. }
  493. readLink() {
  494. local args=-e
  495. local path="${1}"
  496. if [ "${2}" ]; then
  497. args="${1}"
  498. path="${2}"
  499. fi
  500. (
  501. if [ "${ARCH_ARCH}" = "AIX" ]; then
  502. PATH="${PATH}:/opt/freeware/bin"
  503. fi
  504. if isAvailable readlink; then
  505. #shellcheck disable=SC2086
  506. readlink ${args} "${path}"
  507. else
  508. toLogInfo "readlink command not found, falling back to parsing ls output"
  509. readLinkFromLs "${path}"
  510. fi
  511. )
  512. }
  513. isAvailable() {
  514. command -v "${1}" >/dev/null 2>&1
  515. }
  516. getValueFromConfigFile() {
  517. local key="${1}"
  518. local separator="${2}"
  519. local configFile="${3}"
  520. local defaultValue="${4}"
  521. local value="$(sed -n "s|${key}${separator}||p" "${configFile}" 2>/dev/null)"
  522. if [ "${value}" ]; then
  523. printf '%s' "${value}"
  524. else
  525. printf '%s' "${defaultValue}"
  526. fi
  527. }
  528. isAnotherInstallerRunning() {
  529. if [ ! -f "${INSTALLER_LOCK_FILE}" ]; then
  530. return 1
  531. fi
  532. local pidFromLockFile="$(head -n 1 "${INSTALLER_LOCK_FILE}")"
  533. local nameFromLockFile="$(tail -n 1 "${INSTALLER_LOCK_FILE}")"
  534. if [ "$(wc -l <"${INSTALLER_LOCK_FILE}")" -ne 2 ] || [ -z "${pidFromLockFile}" ] || [ -z "${nameFromLockFile}" ]; then
  535. toConsoleWarning "Installer lock file ${INSTALLER_LOCK_FILE} is damaged, skipping uniqueness check."
  536. toConsoleWarning "Lock file contents: '$(cat ${INSTALLER_LOCK_FILE})'"
  537. return 1
  538. fi
  539. #shellcheck disable=SC2009
  540. local foundProcesses="$(ps -e -o "pid,args" 2>&1 | grep -w "${nameFromLockFile}" | grep -v " grep ")"
  541. if printf '%s' "${foundProcesses}" | awk '{ print $1 }' | grep -wq "${pidFromLockFile}"; then
  542. local errorMessage="Another ${BRAND_PRODUCT_NAME} installer or uninstaller is already running"
  543. if printf '%s' "${foundProcesses}" | grep -q "${DOWNLOADS_DIRECTORY}"; then
  544. errorMessage="${errorMessage} (AutoUpdate is in progress)"
  545. fi
  546. toConsoleError "${errorMessage}, PID ${pidFromLockFile}. Exiting."
  547. return 0
  548. fi
  549. toConsoleInfo "Lock file exists but corresponding installer process does not run, contents of lock file: ${pidFromLockFile}, ${nameFromLockFile}."
  550. return 0
  551. }
  552. createInstallerLockFile() {
  553. printf '%s\n%s\n' "$$" "$0" >"${INSTALLER_LOCK_FILE}" 2>/dev/null
  554. }
  555. removeInstallerLockFile() {
  556. toLogInfo "Removing installer lock file."
  557. ${SAFE_RM_EXEC} -f "${INSTALLER_LOCK_FILE}"
  558. }
  559. logBasicStartupInformation() {
  560. toLogInfo "Command line: $(removeSecretsFromString "${@}")"
  561. toLogInfo "Shell options: $-"
  562. toLogInfo "Working dir: $(pwd)"
  563. toLogInfo "PID: $$"
  564. toLogInfo "Parent process: $(
  565. printf '\n'
  566. ps -o user,pid,ppid,comm -p ${PPID} 2>&1
  567. )"
  568. toLogInfo "User id: $(id -u)"
  569. }
  570. mapPidsToName() {
  571. local pids="${1}"
  572. local output
  573. for pid in ${pids}; do
  574. local name="$(grep 'Name:' "/proc/${pid}/status" 2>/dev/null | awk '{print $2}')"
  575. output="${output}, ${pid} (${name})"
  576. done
  577. printf '%s' "${output}" | cut -c 3-
  578. }
  579. readonly ARCH_ARCH="X86"
  580. readonly ARCH_VERSIONED_LIB_DIR_PREFIX="linux-x86"
  581. arch_checkArchitectureCompatibility() {
  582. local arch="$(detectArchitecture)"
  583. if [ "${arch}" = "X86_64" ] || [ "${arch}" = "IA64" ]; then
  584. arch="X86_64"
  585. else
  586. arch="$(uname -m | sed -e 's/i.86/x86/' | sed -e 's/i86pc/x86/' | tr '[:lower:]' '[:upper:]')"
  587. fi
  588. printf '%s' "${arch}"
  589. [ "${arch}" = "X86_64" ]
  590. }
  591. arch_local_getLibraryPathFromLdd() {
  592. local binary="${1}"
  593. ldd "${binary}" 2>/dev/null | grep libc.so | awk '{ print $3 }'
  594. }
  595. arch_local_detectProcessAgentInstallerDirectories() {
  596. local useLddOutput="false"
  597. local systemLib32Prefix
  598. systemLib32Prefix="$(arch_local_getSystemLibraryPath 32)"
  599. local exitCode=$?
  600. if [ ! "${systemLib32Prefix}" ]; then
  601. if [ "${exitCode}" -eq 0 ]; then
  602. toLogWarning "This is a 64-bit platform with 32-bit libraries installed, but ${AGENT_INSTALL_ACTION_BIN} failed to determine their location"
  603. useLddOutput="true"
  604. else
  605. toLogInfo "This is a 64-bit platform and 32-bit libraries were not detected"
  606. fi
  607. else
  608. systemLib32Prefix="$(systemLibDirSanityCheck "/${systemLib32Prefix}")"
  609. if [ ! "${systemLib32Prefix}" ]; then
  610. useLddOutput="true"
  611. fi
  612. fi
  613. local systemLib64Prefix="$(arch_local_getSystemLibraryPath 64)"
  614. if [ ! "${systemLib64Prefix}" ]; then
  615. toLogWarning "This is a 64-bit platform, but ${AGENT_INSTALL_ACTION_BIN} failed to determine location of 64-bit libraries"
  616. useLddOutput="true"
  617. else
  618. systemLib64Prefix="$(systemLibDirSanityCheck "/${systemLib64Prefix}")"
  619. if [ ! "${systemLib64Prefix}" ]; then
  620. useLddOutput="true"
  621. fi
  622. fi
  623. if [ "${useLddOutput}" = "true" ]; then
  624. arch_local_detectProcessAgentDirectoriesBasedOnLdd
  625. else
  626. readonly SYSTEM_LIB32="${systemLib32Prefix}"
  627. readonly SYSTEM_LIB64="${systemLib64Prefix}"
  628. fi
  629. } 2>>"${LOG_FILE}"
  630. arch_detectProcessAgentInstallerDirectories() {
  631. if [ "${CONTAINER_DEPLOYMENT_STATE_ENTRY}"x = "true"x ]; then
  632. readonly SYSTEM_LIB32="${PA_FALLBACK_INSTALLATION_DIR}/lib32"
  633. readonly SYSTEM_LIB64="${PA_FALLBACK_INSTALLATION_DIR}/lib64"
  634. createDirIfNotExistAndSetRights "${SYSTEM_LIB32}" 755
  635. createDirIfNotExistAndSetRights "${SYSTEM_LIB64}" 755
  636. return 0
  637. fi
  638. arch_local_detectProcessAgentInstallerDirectories
  639. }
  640. arch_getLibMacro() {
  641. local libMacro=""
  642. if [ "${SYSTEM_LIB32}" ]; then
  643. #shellcheck disable=SC2016
  644. libMacro='/$LIB'
  645. fi
  646. printf "%s" "${libMacro}"
  647. }
  648. arch_checkGlibc() {
  649. local glibcVersion="$(ldd --version | awk 'NR==1{ print $NF }')"
  650. toLogInfo "Detected glibc version: ${glibcVersion}"
  651. if [ "$(format_version "${glibcVersion}")" -gt "$(format_version "${GLIBC_SUPPORTED_VERSION}")" ]; then
  652. return
  653. elif [ "$(format_version "${glibcVersion}")" -lt "$(format_version "${GLIBC_SUPPORTED_VERSION}")" ]; then
  654. toConsoleError "We can't continue setup. The glibc version: ${glibcVersion} detected on your system isn't supported."
  655. toConsoleError "To install ${BRAND_AGENT_PRODUCT_NAME} you need at least glibc ${GLIBC_SUPPORTED_VERSION}."
  656. toConsoleError "Stopping installer process..."
  657. finishInstaller "${EXIT_CODE_GLIBC_VERSION_TOO_LOW}"
  658. fi
  659. if ! isAvailable rpm; then
  660. toLogInfo "RPM not detected - skipping glibc patch version check."
  661. return
  662. fi
  663. local glibcFullVersion="$(arch_runCommandWithTimeout 60 "rpm" "-q" "glibc" | tail -n 1)"
  664. if [ ! "${glibcFullVersion}" ]; then
  665. toConsoleError "Could not determine exact glibc version using RPM."
  666. finishInstaller "${EXIT_CODE_GLIBC_VERSION_TOO_LOW}"
  667. fi
  668. # fix for RedHat 5.x with unsufficient glibc 2.5 patch version
  669. local glibcPatchVersion="$(format_patch "${glibcFullVersion}")"
  670. if [ "$(format_version "${glibcVersion}")" -eq "$(format_version "${GLIBC_SUPPORTED_VERSION}")" ] && [ "${glibcPatchVersion}" -lt "${GLIBC_SUPPORTED_VERSION_MINIMAL_PATCH}" ]; then
  671. toConsoleError "glibc patch version: ${glibcPatchVersion} detected on your system is not supported, setup won't continue."
  672. toConsoleError "To install ${BRAND_AGENT_PRODUCT_NAME} you need at least glibc ${GLIBC_SUPPORTED_VERSION}-${GLIBC_SUPPORTED_VERSION_MINIMAL_PATCH}."
  673. finishInstaller "${EXIT_CODE_GLIBC_VERSION_TOO_LOW}"
  674. fi
  675. }
  676. # 'timeout' requires gnu-coreutils8, i.e. it is not available on RHEL5, that's why we need this utility function
  677. arch_runCommandWithTimeout() {
  678. local commandTimeout="${1}"
  679. shift
  680. local resultFile="/tmp/smartagent_commandResult_$$"
  681. local errorFile="/tmp/smartagent_commandError_$$"
  682. local loopErrorsFile="/tmp/smartagent_loopErrors_$$"
  683. toLogInfo "Executing $* with timeout ${commandTimeout} seconds"
  684. (
  685. "$@" >${resultFile} 2>${errorFile} &
  686. child=$!
  687. while [ "${commandTimeout}" -gt 0 ]; do
  688. toLogInfo "Time left: ${commandTimeout} s, pid: ${child}"
  689. sleep 1
  690. kill -0 "${child}" 2>/dev/null || exit 0
  691. commandTimeout=$((commandTimeout - 1))
  692. done
  693. # Be nice, post SIGTERM first.
  694. # The 'exit 0' below will be executed if any preceeding command fails.
  695. toLogInfo "Killing ${child} with SIGTERM"
  696. kill -s 15 "${child}" && kill -0 "${child}" || exit 0
  697. sleep 1
  698. toLogWarning "Killing ${child} with SIGKILL"
  699. kill -s 9 "${child}"
  700. ) 2>"${loopErrorsFile}"
  701. local errorOutput="$(cat "${errorFile}")"
  702. local commandOutput="$(cat "${resultFile}")"
  703. local loopErrors="$(cat "${loopErrorsFile}")"
  704. ${SAFE_RM_EXEC} -f "${errorFile}" "${resultFile}" "${loopErrorsFile}"
  705. if [ -n "${errorOutput}" ]; then
  706. toLogInfo "Failed to execute command, error output: ${errorOutput}"
  707. if [ "${loopErrors}" ]; then
  708. toLogInfo "Loop errors: ${loopErrors}"
  709. fi
  710. printf ""
  711. return 1
  712. else
  713. toLogInfo "Command executed successfully, output: ${commandOutput}"
  714. if [ "${loopErrors}" ]; then
  715. toLogInfo "Loop errors: ${loopErrors}"
  716. fi
  717. printf '%s' "${commandOutput}"
  718. return 0
  719. fi
  720. }
  721. arch_getAccessRights() {
  722. stat --format='%A' "${1}"
  723. }
  724. arch_preloadTest() {
  725. if [ "${SYSTEM_LIB32}" ]; then
  726. runSanityCheckCommand "performLdPreloadSanityCheck" "32"
  727. local returnCode=$?
  728. if [ ${returnCode} -ne 0 ]; then
  729. return ${returnCode}
  730. fi
  731. fi
  732. if [ "${SYSTEM_LIB64}" ]; then
  733. runSanityCheckCommand "performLdPreloadSanityCheck" "64"
  734. fi
  735. }
  736. arch_checkEnvironmentConfiguration() {
  737. if ! stat --format='%t,%T' /dev/null | grep -q "1,3"; then
  738. toLogInfo "$(stat /dev/null)"
  739. toConsoleError "Installer detected corruption of '/dev/null': Not a character device"
  740. return "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
  741. fi
  742. return 0
  743. }
  744. arch_moveReplaceTarget() {
  745. local source="${1}"
  746. local target="${2}"
  747. mv -fT "${source}" "${target}"
  748. }
  749. initLog() {
  750. if [ "${CONTAINER_DEPLOYMENT_STATE_ENTRY}"x != "true"x ]; then
  751. createLogDirsIfMissing
  752. fi
  753. toLogInfo "Uninstaller started."
  754. toLogInfo "Distribution: $(detectLinuxDistribution)"
  755. logBasicStartupInformation "${@}"
  756. }
  757. finishUninstaller() {
  758. removeInstallerLockFile
  759. if [ -z "$(ls -A ${INSTALL_DIR})" ];then
  760. ${SAFE_RM_EXEC} -df ${INSTALL_DIR}
  761. ${SAFE_RM_EXEC} -f ${CURRENT_VERSION_LINK}
  762. fi
  763. if [ $1 -eq 0 ]; then
  764. toConsoleInfo "Uninstaller finished successfully"
  765. else
  766. toConsoleInfo "Uninstaller finished failed"
  767. fi
  768. exit "${EXIT_CODE_OK}"
  769. }
  770. setLogFilePath() {
  771. #== - 反安装日志: uninstallation-{timestamp}.log 如: uninstallation-20220601110912.log
  772. readonly LOG_FILE="${INSTALLER_LOG_DIR}/uninstallation-"$(date -u +"%Y%m%d%H%M%S")".log"
  773. }
  774. removeScriptsFromAutostart() {
  775. local prefix="${1}"
  776. local suffix="${2}"
  777. if ! runAutostartAddingTool "${prefix}" "${SERVICE_SCRIPT_FILE}" "${suffix}"; then
  778. toConsoleError "Failed to remove ${SERVICE_SCRIPT_FILE} from autostart. For details, see ${LOG_FILE}"
  779. fi
  780. }
  781. removeUnitFromSystemd() {
  782. local unit=${1}
  783. if [ ! -e "${SYSTEMD_UNIT_FILES_DIR}/${unit}" ]; then
  784. toLogInfo "${unit} does not exist and will not be removed from ${INIT_SYSTEM_SYSTEMD} autostart"
  785. return
  786. fi
  787. executeSystemctlCommand disable "${unit}"
  788. ${SAFE_RM_EXEC} -f "${SYSTEMD_UNIT_FILES_DIR}/${unit}"
  789. }
  790. removeSystemvAutostart() {
  791. toConsoleInfo "Removing ${BRAND_AGENT_PRODUCT_NAME} from autostart"
  792. #Order of checking is important
  793. if [ -x /usr/bin/update-rc.d ]; then #Ubuntu
  794. removeScriptsFromAutostart "/usr/bin/update-rc.d -f " "remove"
  795. elif [ -x /usr/sbin/update-rc.d ]; then #Ubuntu
  796. removeScriptsFromAutostart "/usr/sbin/update-rc.d -f " "remove"
  797. elif [ -x /sbin/chkconfig ]; then #RedHat
  798. removeScriptsFromAutostart "/sbin/chkconfig --del "
  799. elif [ -x /usr/lib/lsb/install_initd ]; then #Suse
  800. removeScriptsFromAutostart "/usr/lib/lsb/install_initd ${INIT_DIR}/"
  801. elif [ "${ARCH_ARCH}" = "AIX" ]; then
  802. #== 不存在
  803. arch_removeAutostart
  804. else
  805. toConsoleError "Couldn't remove ${BRAND_AGENT_PRODUCT_NAME} from autostart."
  806. fi
  807. }
  808. removeSystemdAutostart() {
  809. removeUnitFromSystemd "${SYSTEMD_UNIT_FILE_AGENT}"
  810. executeSystemctlCommand daemon-reload ""
  811. }
  812. stopAgentService() {
  813. toLogInfo "Stopping ${AGENT_PROC} service..."
  814. executeSystemctlCommand stop "${SYSTEMD_UNIT_FILE_AGENT}"
  815. }
  816. removeSystemvInitScripts() {
  817. if [ "${ARCH_ARCH}" = "AIX" ]; then
  818. return
  819. fi
  820. toConsoleInfo "Removing ${SERVICE_SCRIPT_FILE} from ${INIT_DIR}"
  821. ${SAFE_RM_EXEC} -f "${INIT_DIR}/${SERVICE_SCRIPT_FILE}"
  822. }
  823. removeAutostartScripts() {
  824. if [ "${INIT_SYSTEM}" = "${INIT_SYSTEM_SYSV}" ]; then
  825. removeSystemvAutostart
  826. removeSystemvInitScripts
  827. else
  828. removeSystemdAutostart
  829. fi
  830. }
  831. createUninstallInfoFile() {
  832. local reason
  833. if [ "${IS_UPGRADING}"x = "true"x ]; then
  834. reason="upgrade"
  835. else
  836. reason="uninstall"
  837. fi
  838. toLogInfo "Creating uninstall.info file: ${reason}"
  839. }
  840. initializeUninstaller() {
  841. local installerPid=
  842. local skipRootPrivilegesCheck=
  843. if [ $# -eq 1 ]; then
  844. installerPid="${1}"
  845. fi
  846. if [ $# -eq 2 ]; then
  847. installerPid="${1}"
  848. skipRootPrivilegesCheck="${2}"
  849. fi
  850. setPATH
  851. #setLogFilePath "${installerPid}"
  852. setLogFilePath
  853. if [ "${installerPid}" ] && [ "${installerPid}"x != "online"x ]; then
  854. IS_UPGRADING="true"
  855. else
  856. IS_UPGRADING="false"
  857. fi
  858. toConsoleInfo "IS_UPGRADING :${IS_UPGRADING}"
  859. if [ "${skipRootPrivilegesCheck}"x = "true"x ] && [ "${IS_UPGRADING}"x = "true"x ]; then
  860. toConsoleInfo "Skipping root privileges check"
  861. else
  862. if ! checkRootAccess; then
  863. toConsoleError "You must run uninstaller with root privileges"
  864. exit "${EXIT_CODE_GENERIC_ERROR}"
  865. fi
  866. fi
  867. initLog "${@}"
  868. toLogInfo "Launched during upgrade: ${IS_UPGRADING}"
  869. createUninstallInfoFile
  870. configureSignalHandling "finishUninstaller"
  871. if [ "${IS_UPGRADING}"x = "false"x ] && [ "${CONTAINER_DEPLOYMENT_STATE_ENTRY}"x != "true"x ]; then
  872. if isAnotherInstallerRunning; then
  873. exit "${EXIT_CODE_ANOTHER_INSTALLER_RUNNING}"
  874. fi
  875. createInstallerLockFile
  876. fi
  877. if [ ! -f ${PERL_FILE} ]; then
  878. toConsoleInfo "/usr/bin/perl file not found so ${SAFE_RM_EXEC} is used."
  879. fi
  880. toConsoleInfo "Using ${SAFE_RM_EXEC} to uninstall"
  881. }
  882. getVolumeStorageAgentInstallDir() {
  883. readLink "$(dirname "${0}")"
  884. }
  885. cleanUpSELinux() {
  886. if [ ! "${ARCH_HAS_SELINUX}" ] || ! isAvailable semodule; then
  887. return
  888. fi
  889. toConsoleInfo "Removing ${BRAND_FORMAL_NAME} SELinux policies, this may take a while..."
  890. }
  891. cleanUpFilesDuringUninstall() {
  892. toLogInfo "This is a full uninstaller, cleaning up rest of the files"
  893. local fileNames="${AGENT_CONF_DIR} ${AGENT_BIN_DIR} ${LOG_DIR} ${AGENT_SCRIPTS_DIR} ${AGENT_LIBS_DIR} ${AGENT_AGENTS_DIR} ${AGENT_RUNTIME_DIR}"
  894. for fileName in ${fileNames}; do
  895. removeIfExists "${fileName}"
  896. done
  897. fileNames="uninstall.sh installer.version heartbeat"
  898. for fileName in ${fileNames}; do
  899. removeIfExists "${INSTALL_DIR}/${fileName}"
  900. done
  901. }
  902. handleRegularUninstaller() {
  903. checkInitSystem
  904. toLogInfo "Detected init system: ${INIT_SYSTEM}, version: ${INIT_SYSTEM_VERSION}"
  905. if ! setLocationOfInitScripts; then
  906. toLogWarning "Cannot determine location of init scripts."
  907. fi
  908. stopAgentService
  909. cleanUpFilesDuringUninstall
  910. }
  911. main() {
  912. initializeUninstaller "$@"
  913. handleRegularUninstaller "$@"
  914. # finishUninstaller
  915. }
  916. ################################################################################
  917. #
  918. # Script start
  919. #
  920. ################################################################################
  921. main "$@"