uninstall.sh 30 KB

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