install_temp.sh 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954
  1. #!/bin/bash
  2. #== AIX(Advanced Interactive eXecutive)是IBM基于AT&T Unix System V开发的一套类UNIX操作系统,运行在IBM专有的Power系列芯片设计的小型机硬件系统之上
  3. #== 以【#== 】开头的注释会在打包时删除
  4. #DEBUG== 以【#DEBUG== 】开头的注释会在调试打包时保留,正式打包时删除
  5. #==脚本执行中遇到不存在的变量就报错
  6. set -o nounset
  7. #==脚本执行中报错即刻退出
  8. set -o errexit
  9. #==脚本执行只要一个子命令失败,整个管道命令就失败
  10. set -o pipefail
  11. readonly BRAND_FORMAL_NAME="Cloudwise"
  12. readonly BRAND_PRODUCT_NAME="euspace"
  13. readonly BRAND_PARENT_PRODUCT_NAME="omniagent"
  14. readonly BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME}"
  15. readonly BRAND_FORMAL_NAME_LOWER="cloudwise"
  16. readonly BRAND_PRODUCT_NAME_LOWER="euspace"
  17. readonly BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME_CLOUDWISE="cloudwise"
  18. readonly AIX_DF_SPECIFIC_FLAG=
  19. readonly CONF_LD_PRELOAD=
  20. PARAM_DISABLE_SYSTEM_LOGS_ACCESS=
  21. #== 安装包版本项
  22. readonly AGENT_BUILD_DATE=25.09.2020
  23. readonly AGENT_INSTALLER_VERSION=1.2.0
  24. readonly AGENT_BUILD_DATE_INFO=""
  25. readonly AGENT_BUILD_TAG=""
  26. readonly AGENT_BUILD_UPLOADER=""
  27. #== 安装包版本项
  28. #== **********************************************************
  29. #== 配置重要文件名称
  30. #== **********************************************************
  31. #== CW-ServerAgent
  32. readonly AGENT_PROC="euspace"
  33. #== **********************************************************
  34. #== 配置目录
  35. #== **********************************************************
  36. readonly INSTALL_BASE=/opt
  37. #== /opt/cloudwise/oneagent/agents 目录
  38. readonly BASE_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents
  39. #== cloudwise/oneagent/agents/chaosd
  40. readonly INSTALL_FOLDER=${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents/${BRAND_PRODUCT_NAME_LOWER}
  41. #== cloudwise/oneagent/agents/chaosd/version
  42. readonly INSTALL_VERSION_FOLDER=${INSTALL_FOLDER}/${AGENT_INSTALLER_VERSION}
  43. #== /opt/cloudwise/oneagent/agents/chaosd/version
  44. readonly INSTALL_DIR=${INSTALL_BASE}/${INSTALL_VERSION_FOLDER}
  45. #== /opt/cloudwise/oneagent/agents/chaosd
  46. readonly AGENT_BASE_DIR=${INSTALL_BASE}/${INSTALL_FOLDER}
  47. #== /opt/cloudwise/cwserveragent/conf
  48. readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
  49. #== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/scripts
  50. readonly AGENT_SCRIPTS_DIR="${INSTALL_DIR}/scripts"
  51. #== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/runtime
  52. readonly AGENT_RUNTIME_DIR="${INSTALL_DIR}/runtime"
  53. #== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/bin
  54. readonly AGENT_BIN_DIR="${INSTALL_DIR}/bin"
  55. #== agent 初始化脚本目录 /opt/cloudwise/cwserveragent/lib
  56. #== readonly AGENT_LIB_DIR="${INSTALL_DIR}/lib"
  57. readonly AGENTS_BASE_DIR="${INSTALL_DIR}/agents"
  58. readonly META_BASE_DIR="${INSTALL_DIR}/meta"
  59. readonly LOG_DIR_NAME="logs"
  60. #== /opt/cloudwise/cwserveragent/logs
  61. readonly LOG_DIR=${INSTALL_DIR}/${LOG_DIR_NAME}
  62. #== /var/log/cloudwise/cwserveragent/
  63. readonly INSTALLER_LOG_DIR="/var/log/${INSTALL_FOLDER}"
  64. #== server-agent.ini
  65. #== hostId文件
  66. readonly INSTALLER_CONF_FILE_NAME="installation.conf"
  67. #== 部署在容器内的状态信息
  68. readonly INSTALLER_CONF_FILE="${AGENT_CONF_DIR}/${INSTALLER_CONF_FILE_NAME}"
  69. #== 【0】=
  70. readonly INSTALLER_LOCK_FILE="/tmp/${BRAND_FORMAL_NAME_LOWER}_${BRAND_PRODUCT_NAME_LOWER}.lock"
  71. readonly INIT_SYSTEM_SYSV="SysV"
  72. #== 系统 systemd
  73. readonly INIT_SYSTEM_SYSTEMD="systemd"
  74. #== cw-serveragent
  75. readonly SERVICE_SCRIPT_FILE="cw-oneagent"
  76. #== cw-serveragent.service
  77. readonly SYSTEMD_UNIT_FILE_AGENT="${SERVICE_SCRIPT_FILE}.service"
  78. #== 系统文件目录
  79. readonly SYSTEMD_UNIT_FILES_DIR="/etc/systemd/system/"
  80. #== 【0】=【退出码】执行成功
  81. readonly EXIT_CODE_OK=0
  82. readonly EXIT_CODE_GENERIC_ERROR=1
  83. readonly EXIT_CODE_NOT_ENOUGH_SPACE=6
  84. readonly EXIT_CODE_NOT_ENOUGH_MEMORY=7
  85. #== 【0】=无效参数
  86. readonly EXIT_CODE_INVALID_PARAM=8
  87. readonly EXIT_CODE_INSUFFICIENT_PERMISSIONS=9
  88. #== 【退出码】接收信号
  89. readonly EXIT_CODE_SIGNAL_RECEIVED=12
  90. readonly EXIT_CODE_ANOTHER_INSTALLER_RUNNING=13
  91. readonly EXIT_CODE_CORRUPTED_PACKAGE=16
  92. #== 【退出码】管理系统环境变量配置
  93. readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
  94. readonly EXIT_CODE_UNSUPPORTED_DOWNGRADE=18
  95. readonly EXIT_CODE_OS_NOT_SUPPORTED=19
  96. readonly EXTERNAL_TAR_SIZE=233820160
  97. readonly ARTIFACTS_SIZE=953271934
  98. #**********************************************************
  99. # Logs
  100. #**********************************************************
  101. toLogFile() {
  102. if [ -e "${LOG_FILE}" ]; then
  103. printf '%s UTC %s\n' "$(date -u +"%Y-%m-%d %H:%M:%S")" "$*" >>"${LOG_FILE}" 2>/dev/null
  104. fi
  105. }
  106. toConsoleOnly() {
  107. printf '%s %s\n' "$(date +"%H:%M:%S")" "$*" 2>/dev/null
  108. }
  109. toLogInfo() {
  110. toLogFile "[INFO]" "$@"
  111. }
  112. toLogWarn() {
  113. toLogFile "[WARN]" "$@"
  114. }
  115. toLogError() {
  116. toLogFile "[ERROR]" "$@"
  117. }
  118. toLogAdaptive() {
  119. local success="${1}"
  120. shift
  121. if [ "${success}" -eq 0 ]; then
  122. toLogInfo "$@"
  123. else
  124. toLogError "$@"
  125. fi
  126. }
  127. toConsoleInfo() {
  128. toConsoleOnly "$@"
  129. toLogInfo "$@"
  130. }
  131. toConsoleWarn() {
  132. toConsoleOnly "Warn:" "$@"
  133. toLogWarn "$@"
  134. } >&2
  135. toConsoleError() {
  136. toConsoleOnly "Error:" "$@"
  137. toLogError "$@"
  138. } >&2
  139. #== 【0】【3】【4】=创建不存在的目录,并设置权限
  140. createDirIfNotExistAndSetRights() {
  141. local dir="${1}"
  142. local rights="${2}"
  143. toConsoleInfo "#DEBUG== createDirIfNotExistAndSetRights --- ${rights} --- ${dir}"
  144. if [ ! -d "${dir}" ]; then
  145. toLogInfo "Creating directory ${dir} with rights ${rights}"
  146. local message
  147. if ! message="$(mkdir -p "${dir}" 2>&1)"; then
  148. toConsoleWarn "Cannot create ${dir} directory."
  149. toLogWarn "Error message: ${message}"
  150. return 1
  151. fi
  152. fi
  153. if ! message="$(chmod "${rights}" "${dir}" 2>&1)"; then
  154. toConsoleWarn "Cannot change permisions of ${dir} directory to ${rights}."
  155. toLogWarn "Error message: ${message}"
  156. return 1
  157. fi
  158. return 0
  159. }
  160. createCurrentVersionSymlink() {
  161. toLogInfo "Creating symlink to current version..."
  162. local currentVersionLink="${AGENT_BASE_DIR}/current"
  163. local tempLink="${currentVersionLink}.tmp"
  164. if ! commandErrorWrapper ln -s "${AGENT_INSTALLER_VERSION}" "${tempLink}"; then
  165. toLogError "Failed to create current version link"
  166. return
  167. fi
  168. if ! commandErrorWrapper arch_moveReplaceTarget "${tempLink}" "${currentVersionLink}"; then
  169. toLogError "Failed to set up current version link"
  170. commandErrorWrapper rm -f "${tempLink}"
  171. return
  172. fi
  173. toLogInfo "Current version link created: ${currentVersionLink} -> ${AGENT_INSTALLER_VERSION}"
  174. }
  175. #== 【0】=创建日志目录及日志文件installation_$$.log
  176. createLogDirsIfMissing() {
  177. createDirIfNotExistAndSetRights "${INSTALL_BASE}" u+rwx,g+rx,o+rx
  178. createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" u+rwx,g+rx,o+rx
  179. #== agents根目录
  180. createDirIfNotExistAndSetRights "${AGENT_BASE_DIR}" 1775
  181. createDirIfNotExistAndSetRights "${INSTALL_DIR}" 1775
  182. # createDirIfNotExistAndSetRights "${LOG_DIR}" 1777
  183. createDirIfNotExistAndSetRights "${INSTALLER_LOG_DIR}" 1777
  184. # for agentLog in ${PLUGIN_LOG_NAMES}; do
  185. # createDirIfNotExistAndSetRights "${LOG_DIR}/${agentLog}" 1777
  186. # done
  187. touch "${LOG_FILE}"
  188. setRightsForFiles "${LOG_FILE}" 766
  189. }
  190. #**********************************************************
  191. # Platform characteristics detection
  192. #**********************************************************
  193. #== 【5】=获取系统发型版本
  194. getOsReleasePath() {
  195. local osReleasePath="/etc/os-release"
  196. if [ ! -f "${osReleasePath}" ]; then
  197. osReleasePath="/usr/lib/os-release"
  198. fi
  199. printf '%s' "${osReleasePath}"
  200. }
  201. parseOsReleaseFile() {
  202. local osReleasePath="$(getOsReleasePath)"
  203. #shellcheck disable=SC1090
  204. . "${osReleasePath}"
  205. local distrib="${NAME-}"
  206. if [ -z "${distrib}" ]; then
  207. distrib="${ID-}"
  208. fi
  209. local version="${VERSION_ID-}"
  210. if printf '%s' "${distrib}" | grep -iq "debian"; then
  211. version="$(cat /etc/debian_version)"
  212. elif printf '%s' "${distrib}" | grep -iq "fedora" && [ "${VARIANT_ID-}" = "coreos" ]; then
  213. distrib="${distrib} CoreOS"
  214. fi
  215. printf '%s %s' "${distrib}" "${version}"
  216. }
  217. #== 【5】=获取系统发型版本
  218. detectLinuxDistribution() {
  219. if [ -f /etc/oracle-release ]; then
  220. cat /etc/oracle-release
  221. elif [ -f /etc/fedora-release ]; then
  222. if [ -f "$(getOsReleasePath)" ]; then
  223. (
  224. parseOsReleaseFile
  225. )
  226. else
  227. cat /etc/fedora-release
  228. fi
  229. elif [ -f /etc/redhat-release ]; then
  230. cat /etc/redhat-release
  231. elif [ -f "$(getOsReleasePath)" ]; then
  232. (
  233. parseOsReleaseFile
  234. )
  235. elif [ -f /etc/SuSE-release ]; then
  236. head -1 /etc/SuSE-release
  237. elif [ -f /etc/lsb-release ]; then
  238. (
  239. . /etc/lsb-release
  240. printf "%s %s" "${DISTRIB_ID-}" "${DISTRIB_RELEASE-}"
  241. )
  242. elif ls /etc/*release* >/dev/null 2>&1; then
  243. # Generic fallback
  244. cat /etc/*release*
  245. else
  246. printf "AIX %s" "$(oslevel -s 2>&1)"
  247. fi
  248. }
  249. #== 【3】=检查系统init (INIT_SYSTEM、INIT_SYSTEM_VERSION)
  250. checkInitSystem() {
  251. local version
  252. if version="$(systemctl --version 2>&1)"; then
  253. if [ -d "${SYSTEMD_UNIT_FILES_DIR}" ]; then
  254. readonly INIT_SYSTEM=${INIT_SYSTEM_SYSTEMD}
  255. else
  256. readonly INIT_SYSTEM=${INIT_SYSTEM_SYSV}
  257. toLogWarn "${INIT_SYSTEM_SYSTEMD} was detected but ${SYSTEMD_UNIT_FILES_DIR} does not exist, using ${INIT_SYSTEM_SYSV} handling as a fallback"
  258. fi
  259. else
  260. readonly INIT_SYSTEM=${INIT_SYSTEM_SYSV}
  261. if ! version="$(init --version 2>&1)"; then
  262. if ! version="$(chkconfig --version 2>&1)"; then
  263. version="$(head -n1 /etc/inittab 2>&1)"
  264. fi
  265. fi
  266. fi
  267. readonly INIT_SYSTEM_VERSION="$(printf '%s' "${version}" 2>/dev/null | head -n1)"
  268. }
  269. #== 【3】=设置系统初始化脚本目录
  270. setLocationOfScripts() {
  271. toLogInfo "Determining location of scripts..."
  272. if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSTEMD}"x ] || [ "${ARCH_ARCH}"x = "AIX"x ]; then
  273. #== /opt/cloudwise/cwserveragent/scripts
  274. readonly INIT_DIR="${AGENT_SCRIPTS_DIR}"
  275. else
  276. if [ -d "/etc/init.d" ]; then
  277. readonly INIT_DIR="/etc/init.d"
  278. elif [ -d "/sbin/init.d" ]; then
  279. readonly INIT_DIR="/sbin/init.d"
  280. elif [ -d "/etc/rc.d" ]; then
  281. readonly INIT_DIR="/etc/rc.d"
  282. else
  283. return 1
  284. fi
  285. fi
  286. toLogInfo "Location of scripts ${INIT_DIR}"
  287. return 0
  288. }
  289. #== 【0】=检查系统结构(X86_64\IA64\X86)
  290. detectArchitecture() {
  291. local detected_arch=
  292. if isAvailable arch; then
  293. #== arch指令主要用于显示当前主机的硬件结构类型,查询结果与uname一致,我们可以看到它输出的结果有:i386、i486、mips、alpha等
  294. detected_arch="$(arch | tr '[:lower:]' '[:upper:]')"
  295. fi
  296. if [ -z "${detected_arch}" ]; then
  297. detected_arch="$(uname -m | tr '[:lower:]' '[:upper:]')"
  298. fi
  299. printf '%s' "${detected_arch}"
  300. }
  301. #**********************************************************
  302. # Misc functions
  303. #**********************************************************
  304. #== 【1】【4】【5】【6】=获取 agent (64\32)位数lib目录(""或lib64)
  305. getBinariesFolderByBitness() {
  306. local bitness="${1}"
  307. if [ "${bitness}" -eq 32 ]; then
  308. bitness=""
  309. fi
  310. printf 'lib%s' "${bitness}"
  311. }
  312. #== 【1】【2】【5】【6】=获取 agent tools/lib64/smartagentctl 路径
  313. #== getAgentCtlBinPath
  314. #== 【1】【4】【5】【6】=获取 agent 64位数lib路径(lib64/installaction)
  315. #== getAgentInstallActionPath
  316. #== 【5】【6】=获取OS bin配置路径 /opt/cloudwise/cwserveragent/lib64/cloudwiseosconfig
  317. getOsConfigBinPath() {
  318. printf "%s" "${INSTALL_DIR}/lib64/${AGENT_OS_CONFIG_BIN}"
  319. }
  320. #== 【5】=设置agent进程可用
  321. setProcessAgentEnabled() {
  322. local enabled="${1}"
  323. toLogInfo "Setting process agent enabled: ${enabled}..."
  324. local changeStatus=
  325. #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --set-process-agent-enabled
  326. changeStatus=$("$(getAgentInstallActionPath)" --set-process-agent-enabled "${enabled}" 2>&1)
  327. toLogAdaptive $? "Process agent enable(${enabled}) status: ${changeStatus}"
  328. }
  329. #== 【1】【4】【5】【6】=获取命令执行错误信息,并写日志
  330. commandErrorWrapper() {
  331. local command="${*}"
  332. local errorFile="/tmp/smartagent_commanderror_$$"
  333. ${command} 2>"${errorFile}"
  334. local returnCode=$?
  335. if [ ${returnCode} -ne 0 ]; then
  336. toLogWarn "Command '${command}' failed, return code: ${returnCode}, message: $(cat "${errorFile}")"
  337. fi
  338. rm -f "${errorFile}"
  339. return ${returnCode}
  340. }
  341. #== 【3】=是否独立的namespace
  342. isNamespaceIsolated() {
  343. local pid="${1}"
  344. local namespace="${2}"
  345. local initNamespaceId
  346. local processNamespaceId
  347. initNamespaceId="$(readlink "/proc/1/ns/${namespace}" 2>/dev/null | tr -dc '0-9')"
  348. processNamespaceId="$(readlink "/proc/${pid}/ns/${namespace}" 2>/dev/null | tr -dc '0-9')"
  349. if [ ! "${initNamespaceId}" ] || [ ! "${processNamespaceId}" ]; then
  350. toLogInfo "Link to /proc/*/ns/${namespace} does not exist"
  351. printf 'error'
  352. return
  353. fi
  354. if [ "${initNamespaceId}"x != "${processNamespaceId}"x ]; then
  355. printf 'true'
  356. else
  357. printf 'false'
  358. fi
  359. }
  360. #== 【0】=检查是否root
  361. checkRootAccess() {
  362. toConsoleInfo "Checking root privileges..."
  363. if [ "$(id -u)"x != "0"x ]; then
  364. toConsoleError "NOT OK"
  365. return 1
  366. fi
  367. toConsoleInfo "OK"
  368. return 0
  369. }
  370. #== 【3】=删除存在的路径
  371. removeIfExists() {
  372. local pathToRemove="${1}"
  373. if [ ! -e "${pathToRemove}" ]; then
  374. toLogInfo "${pathToRemove} does not exist, skipping removal"
  375. return
  376. fi
  377. local output
  378. if ! output="$(rm -rf "${pathToRemove}" 2>&1)"; then
  379. toLogWarn "Failed to remove ${pathToRemove}: ${output}"
  380. fi
  381. }
  382. #**********************************************************
  383. # SELinux related functions
  384. #**********************************************************
  385. #== 【5】【6】=执行 systemctl 命令
  386. executeSystemctlCommand() {
  387. local command="${1}"
  388. local unit="${2}"
  389. if [ "$(id -u)" != 0 ]; then
  390. #== 执行使用 os config bin
  391. executeUsingOsConfigBin "${command}" "${unit}"
  392. return $?
  393. fi
  394. local output=
  395. #== shellcheck disable=SC2086
  396. #== 执行 systemctl 命令
  397. output="$(systemctl "${command}" ${unit} 2>&1)"
  398. local exitCode=$?
  399. if [ ${exitCode} -eq 0 ]; then
  400. toLogInfo "Successfully executed: systemctl ${command} ${unit}"
  401. else
  402. toLogError "Failed to execute: systemctl ${command} ${unit}"
  403. toLogError "Command output: ${output}"
  404. if [ -n "${unit}" ]; then
  405. local reachBackNumSeconds=360
  406. toLogError "journalctl output: $(journalctl -u "${unit}" --since=-${reachBackNumSeconds} 2>&1)"
  407. fi
  408. fi
  409. return ${exitCode}
  410. } 2>>"${LOG_FILE}"
  411. #== 【6】=运行初始化命令(通过 service 方式 或 直接运行可执行命令)
  412. executeInitScriptCommand() {
  413. local command=
  414. local parameters="$*"
  415. local output=
  416. local exitCode=
  417. if isAvailable service; then
  418. command="service"
  419. parameters="${SERVICE_SCRIPT_FILE} ${parameters}"
  420. else
  421. command="${INIT_DIR}/${SERVICE_SCRIPT_FILE}"
  422. fi
  423. output="$("${command}" "${parameters}" 2>&1)"
  424. exitCode=$?
  425. toLogAdaptive ${exitCode} "Executed ${command} ${parameters}, exitCode = ${exitCode}, output: ${output}"
  426. return ${exitCode}
  427. }
  428. #== 【0】=信号捕获,并执行回调函数
  429. signalHandler() {
  430. local signal="${1}"
  431. local callback="${2}"
  432. toLogWarn "process received signal: ${signal}"
  433. ${callback}
  434. exit ${EXIT_CODE_SIGNAL_RECEIVED}
  435. }
  436. #== 【0】=配置信号捕获和回调
  437. configureSignalHandling() {
  438. local callback="${1}"
  439. for signal in HUP INT QUIT ABRT ALRM TERM; do
  440. # shellcheck disable=SC2064
  441. trap "signalHandler '${signal}' '${callback}'" ${signal}
  442. done
  443. trap "" PIPE
  444. }
  445. #== 【0】删除权限
  446. removeSecretsFromString() {
  447. printf "%s" "$*" | sed 's#\(LICENSE=\)[[:alnum:]]\{16\}#\1***#'
  448. }
  449. #== 【3】【5】=检查目录写权限
  450. testWriteAccessToDir() {
  451. local errorFile="/tmp/smartagent_commandError_$$"
  452. local dir="${1}"
  453. local tmpfilename
  454. if [ "${ARCH_ARCH}"x = "AIX"x ]; then
  455. tmpfilename="${dir}/.tmp_${BRAND_PRODUCT_NAME_LOWER}.$$${RANDOM}"
  456. touch "${tmpfilename}" 2>"${errorFile}"
  457. else
  458. tmpfilename="$(mktemp -p "${dir}" ".tmp_${BRAND_PRODUCT_NAME_LOWER}.XXXXXXXXXXXXXX" 2>"${errorFile}")"
  459. fi
  460. #== shellcheck disable=SC2181
  461. if [ $? -ne 0 ]; then
  462. toLogInfo "$(cat "${errorFile}")"
  463. rm -f "${errorFile}"
  464. return 1
  465. fi
  466. rm -f "${tmpfilename}" "${errorFile}"
  467. return 0
  468. }
  469. #== 【0】=设置PATH
  470. setPATH() {
  471. local prependToPATH="/usr/sbin:/usr/bin:/sbin:/bin"
  472. if [ "${PATH}" ]; then
  473. PATH=${prependToPATH}:${PATH}
  474. else
  475. PATH=${prependToPATH}
  476. fi
  477. }
  478. #== 【5】【6】=是否非root权限
  479. isNonRootModeEnabled() {
  480. #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-drop-root-privileges
  481. local output
  482. output="$(getValueFromConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "${LEGACY_AGENT_CONF_FILE}" "${PARAM_NON_ROOT_MODE}")"
  483. printf '%s' "${output}" | grep -qE "(true|no_ambient)"
  484. }
  485. #== 【5】=自动启动工具
  486. runAutostartAddingTool() {
  487. local prefix="${1}"
  488. local file="${2}"
  489. local suffix="${3}"
  490. local output
  491. local command="${prefix} ${file} ${suffix}"
  492. toLogInfo "Executing ${command}"
  493. output="$(${command} 2>&1)"
  494. local status=$?
  495. if [ "${output}" ]; then
  496. toLogAdaptive ${status} "${output}"
  497. fi
  498. return ${status}
  499. }
  500. #== 【0】【5】=查找软链接真实地址(通过ls命令)
  501. readLinkFromLs() {
  502. local path="${1}"
  503. local result="${path}"
  504. local lsOutput
  505. local parsedLinkTarget
  506. lsOutput="$(ls -dl "${path}" 2>/dev/null)"
  507. if printf '%s' "${lsOutput}" | grep -q " -> "; then
  508. parsedLinkTarget="$(printf '%s' "${lsOutput}" | sed 's|^.* -> ||')"
  509. if [ "${parsedLinkTarget}" ]; then
  510. result="${parsedLinkTarget}"
  511. else
  512. toLogWarn "Failed to parse ls output '${lsOutput}'"
  513. fi
  514. fi
  515. printf '%s' "${result}"
  516. }
  517. #== 【0】【5】=查找软链接真实地址(通过readlink 或 ls 命令)
  518. readLink() {
  519. local args=-e
  520. local path="${1}"
  521. if [ "${2}" ]; then
  522. args="${1}"
  523. path="${2}"
  524. fi
  525. (
  526. if [ "${ARCH_ARCH}"x = "AIX"x ]; then
  527. path="${PATH}:/opt/freeware/bin"
  528. fi
  529. #== 通过 readlink 命令查找地址
  530. if isAvailable readlink; then
  531. #shellcheck disable=SC2086
  532. readlink ${args} "${path}"
  533. else
  534. toLogInfo "readlink command not found, falling back to parsing ls output"
  535. readLinkFromLs "${path}"
  536. fi
  537. )
  538. }
  539. #== 【0】【3】【4】【5】【6】=检查命令是否有效/是否存在
  540. isAvailable() {
  541. command -v "${1}" >/dev/null 2>&1
  542. }
  543. #== 【0】【1】【3】【5】=读取配置文件配置参数信息
  544. getValueFromConfigFile() {
  545. local key="${1}"
  546. local configFile="${2}"
  547. local defaultValue="${3}"
  548. local value
  549. value="$(sed -n "s|^${key}=||p" "${configFile}" 2>/dev/null)"
  550. if [ "${value}" ]; then
  551. printf '%s' "${value}"
  552. else
  553. printf '%s' "${defaultValue}"
  554. fi
  555. }
  556. #== 【1】【5】=删除配置文件中配置
  557. removeValueFromConfigFile() {
  558. local key="${1}"
  559. local configFile="${2}"
  560. local output
  561. if ! output="$(cp -p "${configFile}" "${configFile}.tmp" 2>&1)"; then
  562. toLogWarn "Unable to initialize ${configFile}.tmp file using source file, privileges and ownership will not be preserved: ${output}"
  563. fi
  564. if sed "/^${key}/d" "${configFile}" >"${configFile}.tmp"; then
  565. mv -f "${configFile}.tmp" "${configFile}"
  566. else
  567. toLogWarn "Failed to remove ${key} from ${configFile}"
  568. rm -f "${configFile}.tmp"
  569. fi
  570. }
  571. #== 写配置到配置文件信息
  572. writeParamToConfigFile() {
  573. local key="${1}"
  574. local newValue="${2}"
  575. local configFile="${3}"
  576. local value
  577. value="$(sed -n "s|^${key}=||p" "${configFile}" 2>/dev/null)"
  578. toConsoleInfo "#DEBUG== writeParamToConfigFile --> edit ${key}=${value} to ${key}=${newValue}, configFile: ${configFile}"
  579. if [ "${value}" ]; then
  580. sed -i "s|^${key}=.*|${key}=${newValue}|" "${configFile}" 2>/dev/null
  581. else
  582. echo "${key}=${newValue}" >>"${configFile}" 2>/dev/null
  583. fi
  584. }
  585. writeContentToConfigFile() {
  586. local newValue="${1}"
  587. local configFile="${2}"
  588. toConsoleInfo "#DEBUG== writeContentToConfigFile --> edit ${newValue}, configFile: ${configFile}"
  589. echo "${newValue}" > "${configFile}" 2>/dev/null
  590. }
  591. #== 修改scripts/smartagent脚本配置信息
  592. editScriptFileParam() {
  593. local key="${1}"
  594. local newValue="${2}"
  595. local file="${3}"
  596. local value
  597. value="$(sed -n "s|^${key}=||p" "${file}" 2>/dev/null)"
  598. toConsoleInfo "#DEBUG== editScriptFileParam --> edit ${key}=${value} to ${key}=${newValue}, configFile: ${file}"
  599. if [ "${value}" ]; then
  600. sed -i "s|^${key}=.*|${key}=${newValue}|" "${file}" 2>/dev/null
  601. fi
  602. }
  603. #== 【0】=是否存在多个同时安装操作【通过判断 INSTALLER_LOCK_FILE 】
  604. isAnotherInstallationRunning() {
  605. if [ ! -f "${INSTALLER_LOCK_FILE}" ]; then
  606. return 1
  607. fi
  608. local pidFromLockFile
  609. local nameFromLockFile
  610. pidFromLockFile="$(head -n 1 "${INSTALLER_LOCK_FILE}")"
  611. nameFromLockFile="$(tail -n 1 "${INSTALLER_LOCK_FILE}")"
  612. if [ "$(wc -l <"${INSTALLER_LOCK_FILE}")" -ne 2 ] || [ -z "${pidFromLockFile}" ] || [ -z "${nameFromLockFile}" ]; then
  613. toConsoleWarn "Installation lock file ${INSTALLER_LOCK_FILE} is damaged, skipping uniqueness check."
  614. toConsoleWarn "Lock file contents: '$(cat ${INSTALLER_LOCK_FILE})'"
  615. return 1
  616. fi
  617. #== shellcheck disable=SC2009
  618. #== 获取正在执行安装的进程信息
  619. local foundProcesses
  620. foundProcesses="$(pgrep -f "pid,args" 2>&1 | grep -w "${nameFromLockFile}" | grep -v " grep ")"
  621. if printf '%s' "${foundProcesses}" | awk '{ print $1 }' | grep -wq "${pidFromLockFile}"; then
  622. local errorMessage="Another ${BRAND_PRODUCT_NAME} installer or uninstaller is already running"
  623. if printf '%s' "${foundProcesses}" | grep -q "${DOWNLOADS_DIR}"; then
  624. errorMessage="${errorMessage} (AutoUpdate is in progress)"
  625. fi
  626. toConsoleError "${errorMessage}, PID ${pidFromLockFile}. Exiting."
  627. return 0
  628. fi
  629. toConsoleInfo "Lock file exists but corresponding installation process does not run, contents of lock file: ${pidFromLockFile}, ${nameFromLockFile}."
  630. return 1
  631. }
  632. #== 【0】=创建安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
  633. createInstallationLockFile() {
  634. printf '%s\n%s\n' "$$" "$0" >"${INSTALLER_LOCK_FILE}" 2>/dev/null
  635. }
  636. #== 【0】【6】删除安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
  637. removeInstallationLockFile() {
  638. toLogInfo "Removing installation lock file."
  639. rm -f "${INSTALLER_LOCK_FILE}"
  640. }
  641. #== 【0】基础启动日志信息
  642. logBasicStartupInformation() {
  643. toLogInfo "Command line: $(removeSecretsFromString "${@}")"
  644. toLogInfo "Shell options: $-"
  645. toLogInfo "Working dir: $(pwd)"
  646. toLogInfo "PID: $$"
  647. toLogInfo "Parent process: $(
  648. printf '\n'
  649. ps -o user,pid,ppid,comm -p ${PPID} 2>&1
  650. )"
  651. toLogInfo "User id: $(id -u)"
  652. }
  653. #== 解压文件编码
  654. readonly UNPACK_BINARY=base64
  655. #== 解压文件编码参数
  656. readonly UNPACK_BINARY_ARGS="-di"
  657. readonly ARCH_ARCH="X86"
  658. #== 【0】=检查系统指令集(X86_64\IA64\X86)
  659. arch_checkArchitectureCompatibility() {
  660. #== 【0】=检查系统结构(X86_64)
  661. local arch
  662. arch="$(detectArchitecture)"
  663. if [ "${arch}"x = "X86_64"x ] || [ "${arch}"x = "IA64"x ]; then
  664. arch="X86_64"
  665. else
  666. arch="$(uname -m | sed -e 's/i.86/x86/' | sed -e 's/i86pc/x86/' | tr '[:lower:]' '[:upper:]')"
  667. fi
  668. printf '%s' "${arch}"
  669. [ "${arch}"x = "X86_64"x ] || [ "${arch}"x = "AARCH64"x ]
  670. }
  671. #== 【5】=获取 lib 目录
  672. arch_getLibMacro() {
  673. local libMacro=""
  674. if [ "${SYSTEM_LIB32}" ]; then
  675. #== shellcheck disable=SC2016
  676. libMacro="/${LIB}"
  677. fi
  678. printf "%s" "${libMacro}"
  679. }
  680. #== 'timeout' requires gnu-coreutils8, i.e. it is not available on RHEL5, that's why we need this utility function
  681. #== 【3】【5】=执行命令超时配置
  682. #== 【0】【3】=获取文件权限信息
  683. arch_getAccessRights() {
  684. stat --format='%A' "${1}"
  685. }
  686. #== 【4】=替换目录
  687. arch_moveReplaceTarget() {
  688. local source="${1}"
  689. local target="${2}"
  690. mv -fT "${source}" "${target}"
  691. }
  692. #== xz 压缩包文件名 Cloudwise-SmartAgent
  693. readonly INTERNAL_TAR_FILE_NAME=${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}.tar.xz
  694. #== -安装日志: installation-{timestamp}.log,如,installation-20220601110912.log
  695. readonly LOG_FILE="${INSTALLER_LOG_DIR}/installation-$(date -u +"%Y%m%d%H%M%S").log"
  696. #readonly LOG_FILE="${INSTALLER_LOG_DIR}/installation_$$.log"
  697. #== 【临时目录】安装临时目录
  698. readonly TMP_DIR=${INSTALL_DIR}_install_$$
  699. #== 【临时目录】解压缓存目录
  700. readonly UNPACK_CACHE=${BASE_INSTALL_DIR}/unpack_cache
  701. #== 【临时目录】从sh文件读取压缩文件 tarfile_$$.base64
  702. readonly EXTERNAL_TAR_FILE=${BASE_INSTALL_DIR}/tarfile_$$.base64
  703. #== 【临时目录】xz 压缩包文件
  704. readonly INTERNAL_TAR_FILE=${INSTALL_DIR}/${INTERNAL_TAR_FILE_NAME}
  705. #== 【0】=
  706. readonly INSTALLER_FILE=${0}
  707. #== 旧配置文件
  708. readonly LEGACY_AGENT_CONF_FILE="${AGENT_CONF_DIR}/${BRAND_PRODUCT_NAME_LOWER}.conf"
  709. #== 【0】=
  710. readonly LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS=50
  711. #== 【0】=
  712. readonly HELP_URL=""
  713. readonly CONF_FIELD_NM_DATA_SERVER="DataServer"
  714. readonly CONF_FIELD_NM_CONFIG_SERVER="ConfigServer"
  715. readonly CONF_FIELD_NM_LICENSE="License"
  716. readonly CONF_FIELD_NM_JSON_CONF="JSON_CONF"
  717. readonly CONF_FIELD_NM_USER="User"
  718. readonly CONF_FIELD_NM_GROUP="Group"
  719. readonly CONF_FIELD_NM_DATA_STORAGE="DataStorage"
  720. readonly CONF_FIELD_NM_NON_ROOT_MODE="NonRootMode"
  721. #== 配置默认用户权限
  722. readonly BASE_OMNI_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}
  723. readonly BASE_OMNI_INSTALL_CONF_DIR=${BASE_OMNI_INSTALL_DIR}/conf/installation.conf
  724. 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}")"
  725. #== Those are read from params section appended to installer by the server
  726. #== 【0】=【参数】数据服务地址
  727. PARAM_DATA_SERVER=
  728. #== 【0】=【参数】配置服务地址
  729. PARAM_CONFIG_SERVER=
  730. #== 【0】=【参数】license
  731. PARAM_LICENSE=
  732. PARAM_JSON_CONF=
  733. #== 【0】=【参数】安装路径
  734. PARAM_INSTALL_DIR=${INSTALL_DIR}
  735. #== 【0】=【参数】用户
  736. PARAM_USER=
  737. #== 【0】=【参数】用户组
  738. PARAM_GROUP=
  739. #== 【0】=【参数】非root模式
  740. PARAM_NON_ROOT_MODE=true
  741. PARAM_USER_LOGIN=false
  742. #== 【0】=【参数】不允许root回退
  743. PARAM_DISABLE_ROOT_FALLBACK=false
  744. #== 【0】=【参数】数据存储目录
  745. PARAM_DATA_STORAGE=
  746. #== 【0】=【参数】通过容器部署
  747. #== PARAM_INTERNAL_DEPLOYED_VIA_CONTAINER=false
  748. #== 【0】=【参数】跳过SELinux策略安装
  749. #== PARAM_INTERNAL_SKIP_SELINUX_POLICY_INSTALLER=false
  750. #== 【0】=【参数】是否使用解压缓存
  751. PARAM_INTERNAL_USE_UNPACK_CACHE=false
  752. #== 【0】=【参数】是否不使用 dump
  753. #== PARAM_INTERNAL_DISABLE_DUMPPROC=
  754. #== 【0】=【参数】是否跳过非root检查
  755. PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK=false
  756. #== 【0】【1】=【参数】额外的配置
  757. #== PARAM_INTERNAL_PASS_THROUGH_SETTERS=
  758. #== 【0】=检查是否降级安装
  759. SKIP_DOWNGRADE_CHECK=false
  760. SKIP_PRIVILEGES_CHECK=false
  761. #== 自定义字符串参数
  762. PARAM_TEST=
  763. #== 自定义字BOOL参数
  764. PARAM_BOOL=
  765. #== 【0】=常规日志
  766. initializeLog() {
  767. toConsoleInfo "Installation started, version ${AGENT_INSTALLER_VERSION}, build date: ${AGENT_BUILD_DATE}, PID $$."
  768. toLogInfo "Started from: ${INSTALLER_FILE}"
  769. if [ -f /proc/version ]; then
  770. toLogInfo "System version: $(cat /proc/version)"
  771. else
  772. toLogInfo "System version: $(uname -a)"
  773. fi
  774. toLogInfo "Path: ${PATH}"
  775. toLogInfo "INSTALL_DIR: ${INSTALL_DIR}"
  776. toLogInfo "Resolved installation path: $(readLink -e "${INSTALL_DIR}" 2>/dev/null)"
  777. logBasicStartupInformation "${@}"
  778. }
  779. #**********************************************************
  780. # Signing related stuff
  781. #**********************************************************
  782. #== 【0】【4】=通过占位分割读取位置
  783. locateDelimiter() {
  784. #== 占位符
  785. local delimiter="${1}"
  786. #== 从文件结尾读取行数
  787. local linesToReadFromEnd="${2}"
  788. local linesCount
  789. local offset
  790. if [ "${linesToReadFromEnd}" ]; then
  791. #== 文件总行数n(实际行数=n+1)
  792. linesCount="$(wc -l "${INSTALLER_FILE}" | awk '{print $1}')"
  793. #== 从后往前读取【linesToReadFromEnd】行
  794. offset="$(tail -n"${linesToReadFromEnd}" "${INSTALLER_FILE}" 2>/dev/null | awk '/^'"${delimiter}"'/ { print NR; exit }')"
  795. if [ -n "${offset}" ]; then
  796. printf "%d" "$((linesCount - linesToReadFromEnd + offset))"
  797. fi
  798. else
  799. #== 读取占位符所在行(实际行数=n+1)
  800. awk '/^'"${delimiter}"'/ { print NR; exit }' "${INSTALLER_FILE}"
  801. fi
  802. }
  803. #== 【0】=从指定行范围读取配置参数
  804. readParam() {
  805. local paramName="${1}"
  806. local paramsSectionBeggining="${2}"
  807. local paramsSectionEnd="${3}"
  808. sed -n "${paramsSectionBeggining},${paramsSectionEnd} s/^${paramName}=//p" "${INSTALLER_FILE}"
  809. }
  810. #== 【0】=读取以【----PARAMETERS】开始到 【----PARAMETERS--】之间的参数
  811. readParamsSection() {
  812. local sectionName="----PARAMETERS"
  813. local begin
  814. local end
  815. begin=$(locateDelimiter "${sectionName}" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})
  816. end=$(locateDelimiter "${sectionName}--" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})
  817. if [ -z "${begin}" ] || [ -z "${end}" ]; then
  818. return
  819. fi
  820. #== 从指定行范围读取配置参数
  821. local value
  822. if value="$(readParam PARAM_DATA_SERVER "${begin}" "${end}")"; then
  823. PARAM_DATA_SERVER="${value}"
  824. fi
  825. if value="$(readParam PARAM_CONFIG_SERVER "${begin}" "${end}")"; then
  826. PARAM_CONFIG_SERVER="${value}"
  827. fi
  828. if value="$(readParam PARAM_LICENSE "${begin}" "${end}")"; then
  829. PARAM_LICENSE="${value}"
  830. fi
  831. if value="$(readParam PARAM_JSON_CONF "${begin}" "${end}")"; then
  832. PARAM_JSON_CONF="${value}"
  833. fi
  834. if value="$(readParam PARAM_USER "${begin}" "${end}")"; then
  835. PARAM_USER="${value}"
  836. fi
  837. if value="$(readParam PARAM_GROUP "${begin}" "${end}")"; then
  838. PARAM_GROUP="${value}"
  839. fi
  840. if value="$(readParam PARAM_NON_ROOT_MODE "${begin}" "${end}")"; then
  841. if value="$(getBoolParam "${value}")"; then
  842. PARAM_NON_ROOT_MODE="${value}"
  843. fi
  844. fi
  845. if value="$(readParam PARAM_USER_LOGIN "${begin}" "${end}")"; then
  846. if value="$(getBoolParam "${value}")"; then
  847. PARAM_USER_LOGIN="${value}"
  848. fi
  849. fi
  850. toConsoleInfo "#DEBUG== install sh params, DATA_SERVER: ${PARAM_DATA_SERVER}, PARAM_CONFIG_SERVER: ${PARAM_CONFIG_SERVER}, PARAM_LICENSE:${PARAM_LICENSE}"
  851. 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}"
  852. }
  853. #== 【0】【6】=清空安装临时文件
  854. #== ${INSTALL_DIR}_install_$$
  855. #== EXTERNAL_TAR_FILE=${INSTALL_DIR}/tarfile_$$.base64
  856. #== ${INSTALL_DIR}/Dynatrace-OneAgent.tar.xz
  857. #== ${INSTALL_DIR}/xzdec
  858. #== /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
  859. cleanInstallationTemporaryFiles() {
  860. toLogInfo "Cleaning installation temporary files"
  861. rm -f "${EXTERNAL_TAR_FILE}" "${INTERNAL_TAR_FILE}" "${INSTALL_DIR}/xzdec"
  862. rm -Rf "${TMP_DIR}"
  863. local keepInstallationLockFile="${1}"
  864. if [ -z "${keepInstallationLockFile}" ]; then
  865. removeInstallationLockFile
  866. fi
  867. }
  868. #== 完成安装后清理临时目录
  869. finishInstallation() {
  870. if [ $# -eq 2 ]; then
  871. cleanInstallationTemporaryFiles "${2}"
  872. else
  873. cleanInstallationTemporaryFiles ""
  874. fi
  875. toLogInfo "Installation finished, PID $$, exit code: ${1}."
  876. changeWorkingDir "${CURR_PATH}"
  877. if [ "${CONF_LD_PRELOAD}"x = "true"x ]; then
  878. exec /bin/bash && exit 0
  879. fi
  880. exit "${1}"
  881. }
  882. #**********************************************************
  883. # Create folders, copy files, set rights
  884. #**********************************************************
  885. #== 【3】=创建临时目录
  886. prepareTempFolder() {
  887. #== 删除存在的路径
  888. removeIfExists "${TMP_DIR}"
  889. toLogInfo "Creating temporary folder $TMP_DIR"
  890. createDirIfNotExistAndSetRights "${TMP_DIR}" 755
  891. }
  892. #== 【4】=设置文件可执行权限
  893. setRightsForFiles() {
  894. local file="${1}"
  895. local perms="${2}"
  896. if [ -e "${file}" ]; then
  897. chmod "${perms}" "${file}"
  898. fi
  899. }
  900. setRightsForDir() {
  901. local dir="${1}"
  902. local perms="${2}"
  903. if [ -d "${dir}" ]; then
  904. chmod -R "${perms}" "${dir}"
  905. fi
  906. }
  907. #== 【4】=安装类型(f:文件,d:目录)递归设置权限
  908. chmod4FilesRecursively() {
  909. local dir="${1}"
  910. local type="${2}"
  911. local mask="${3}"
  912. find "${dir}" -type "${type}" -exec chmod "${mask}" {} \;
  913. }
  914. #== 【4】=移动目录到指定位置
  915. moveFolderToDestination() {
  916. local source="${1}"
  917. local destination="${2}"
  918. local fullDestination
  919. fullDestination="${destination}/$(basename "${source}")"
  920. local output
  921. toLogInfo "Moving ${source} to ${destination}"
  922. if [ ! -e "${fullDestination}" ]; then
  923. if output="$(mv -f "${source}" "${destination}" 2>&1)"; then
  924. toLogInfo "Moving Successfully."
  925. return
  926. fi
  927. toLogWarn "Failed to move ${source} to ${destination}: ${output}, attempting to copy"
  928. else
  929. toLogInfo "${fullDestination} already exists, attempting to copy"
  930. fi
  931. if ! output="$(cp -Rfp "${source}" "${destination}" 2>&1)"; then
  932. toLogError "Failed to copy ${source} to ${destination}: ${output}"
  933. fi
  934. }
  935. #== 【4】=将 bin 下版本内容移动到安装目录
  936. installVersionedContent() {
  937. toLogInfo "Installing versioned content..."
  938. createDirIfNotExistAndSetRights "${AGENT_BIN_DIR}" 755
  939. local sourceDir="${TMP_DIR}/bin"
  940. if [ ! -d "${AGENT_BIN_DIR}" ]; then
  941. moveFolderToDestination "${sourceDir}" "${AGENT_BIN_DIR}"
  942. return
  943. fi
  944. toLogInfo "Directory ${AGENT_BIN_DIR} already exist, repairing the directory"
  945. rm -rf "${AGENT_BIN_DIR}"
  946. moveFolderToDestination "${sourceDir}" "${AGENT_BIN_DIR}"
  947. }
  948. #== 【4】=创建当前版本软连接
  949. #== 【4】=删除存在的目录
  950. listAndRemoveDirectoryIfExists() {
  951. local directory="${1}"
  952. if [ -d "${directory}" ]; then
  953. toLogInfo "${directory} exists, removing it."
  954. toLogInfo "Contents: $(ls -lR "${directory}")"
  955. rm -rf "${directory}"
  956. fi
  957. }
  958. #== 【4】=临时目录中conf 移动到 agent 安装目录中
  959. setupConfFolder() {
  960. toLogInfo "Setup conf folder..."
  961. #== 移动目录到指定位置
  962. moveFolderToDestination "${TMP_DIR}/conf" "${INSTALL_DIR}"
  963. chmod 755 "${AGENT_CONF_DIR}"
  964. toLogInfo "Setup conf done."
  965. }
  966. #== 【4】=给距离当前目录至少 ${mindepth} 个子目录的所有文件设置权限
  967. chmodFilesWithMindepth() {
  968. local dir="${1}"
  969. local mindepth="${2}"
  970. local mask="${3}"
  971. if [ "${ARCH_ARCH}"x = "AIX"x ]; then
  972. #== 安装类型(f:文件,d:目录)递归设置权限
  973. chmod4FilesRecursively "${1}" f "${3}"
  974. else
  975. #== 查找深度距离当前目录至少 ${mindepth} 个子目录的所有文件
  976. find "${dir}" -mindepth "${mindepth}" -print0 | xargs -r -0 chmod "${mask}"
  977. fi
  978. }
  979. #== 【4】=配置其他文件(cwserveragent.service、installer.version)
  980. setupMiscFiles() {
  981. toLogInfo "Setup misc files..."
  982. #== 创建 cwserveragent.service
  983. createSystemdUnitFile
  984. #== echo "${AGENT_INSTALLER_VERSION}" >"${INSTALL_DIR}/installer.version"
  985. mv -f "${TMP_DIR}/installer.version" "${INSTALL_DIR}/"
  986. toLogInfo "Setup misc done."
  987. }
  988. #== 【4】=创建 cwserveragent.service
  989. createSystemdUnitFile() {
  990. toLogInfo "creating init scripts ${AGENT_SCRIPTS_DIR}"
  991. if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
  992. return
  993. fi
  994. createDirIfNotExistAndSetRights "${AGENT_SCRIPTS_DIR}" 755
  995. cat <<EOF >${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}
  996. [Unit]
  997. Description=${BRAND_AGENT_PRODUCT_NAME}
  998. After=network-online.target
  999. Wants=network-online.target
  1000. [Service]
  1001. User=root
  1002. ExecStart=${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} start
  1003. ExecStop=${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} stop
  1004. Type=forking
  1005. #Restart=always
  1006. KillMode=process
  1007. TimeoutSec=240
  1008. [Install]
  1009. WantedBy=multi-user.target
  1010. EOF
  1011. setRightsForFiles "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" 755
  1012. if [ "${INIT_DIR}"x != "${AGENT_SCRIPTS_DIR}"x ]; then
  1013. cp -f "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" ${INIT_DIR}
  1014. toLogInfo "Copy scripts ${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT} to ${INIT_DIR} done."
  1015. fi
  1016. toLogInfo "creating init scripts ${AGENT_SCRIPTS_DIR} done."
  1017. }
  1018. setupAll() {
  1019. # moveFolderToDestination "${TMP_DIR}/package_dir/*" "${INSTALL_DIR}"
  1020. #ls ${TMP_DIR}/package_dir/*
  1021. #== 移动所有文件到目录
  1022. cp -Rfp ${TMP_DIR}/package_dir/* "${INSTALL_DIR}"
  1023. local installVersionFile="${INSTALL_DIR}/installer.version"
  1024. echo ${AGENT_INSTALLER_VERSION} > ${installVersionFile}
  1025. # mv ${INSTALL_DIR}/package_dir/* ${INSTALL_DIR}
  1026. # echo "${TMP_DIR}/*" "${INSTALL_DIR}/"
  1027. }
  1028. #== 【4】=配置 lib、conf、bin、cwserveragent.service、installer.version、plugins
  1029. setupOptDir() {
  1030. createDirIfNotExistAndSetRights "${INSTALL_DIR}" 1775
  1031. #== 临时目录中conf 移动到 agent 安装目录中
  1032. setupConfFolder
  1033. #== 将 bin 下版本内容移动到安装目录
  1034. installVersionedContent
  1035. #== 配置其他文件(cwserveragent.service、installer.version)
  1036. setupMiscFiles
  1037. }
  1038. #== 【4】=复制临时目录 scripts/cwserveragent 到指定目录下
  1039. copyScriptsToDirectory() {
  1040. local scriptLocation="${1}"
  1041. #== scripts/cwserveragent
  1042. local scriptFile="${TMP_DIR}/scripts/${SERVICE_SCRIPT_FILE}"
  1043. toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} begin."
  1044. local output
  1045. if ! output="$(cp "${scriptFile}" "${scriptLocation}/" 2>&1)"; then
  1046. toLogError "Failed to copy ${scriptFile} to ${scriptLocation}, output: ${output}"
  1047. return
  1048. fi
  1049. setRightsForFiles "${scriptLocation}/${SERVICE_SCRIPT_FILE}" 755
  1050. toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} done."
  1051. #== scripts/uninstall.sh
  1052. # local scriptLocation="${1}"
  1053. # #== scripts/cwserveragent
  1054. # local scriptFile="${TMP_DIR}/scripts/uninstall.sh"
  1055. #
  1056. # toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} begin."
  1057. #
  1058. # local output
  1059. # if ! output="$(cp "${scriptFile}" "${scriptLocation}/" 2>&1)"; then
  1060. # toLogError "Failed to copy ${scriptFile} to ${scriptLocation}, output: ${output}"
  1061. # return
  1062. # fi
  1063. # setRightsForFiles "${scriptLocation}/uninstall.sh" 755
  1064. # toLogInfo "Copy scripts ${scriptFile} to ${scriptLocation} done."
  1065. }
  1066. #== 【4】=复制临时目录 scripts/cwserveragent 到指定目录下
  1067. copyScripts() {
  1068. toLogInfo "Copy scripts..."
  1069. #== 创建目录 /opt/cloudwise/cwserveragent/scripts
  1070. createDirIfNotExistAndSetRights "${AGENT_SCRIPTS_DIR}" 755
  1071. #== 创建目录 /opt/cloudwise/{product}/agents
  1072. createDirIfNotExistAndSetRights "${AGENTS_BASE_DIR}" 775
  1073. #== 创建目录 /opt/cloudwise/{product}/meta
  1074. createDirIfNotExistAndSetRights "${META_BASE_DIR}" 775
  1075. #== 创建目录 /opt/cloudwise/{product}/runtime
  1076. createDirIfNotExistAndSetRights "${AGENT_RUNTIME_DIR}" 775
  1077. #== scripts/uninstall.sh
  1078. local uninstallScript="${TMP_DIR}/scripts/uninstall.sh"
  1079. toLogInfo "Copy scripts ${uninstallScript} to ${INSTALL_DIR} begin."
  1080. local output
  1081. if ! output="$(cp "${uninstallScript}" "${INSTALL_DIR}/uninstall.sh" 2>&1)"; then
  1082. toLogError "Failed to copy ${uninstallScript} to ${INSTALL_DIR}/uninstall.sh, output: ${output}"
  1083. else
  1084. setRightsForFiles "${INSTALL_DIR}/uninstall.sh" 755
  1085. fi
  1086. toLogInfo "Copy scripts ${uninstallScript} to ${INSTALL_DIR} done."
  1087. #== 复制临时目录 scripts/ 到安装目录 /opt/cloudwise/cwserveragent/scripts
  1088. copyScriptsToDirectory "${AGENT_SCRIPTS_DIR}"
  1089. if [ "${INIT_DIR}"x != "${AGENT_SCRIPTS_DIR}"x ]; then
  1090. copyScriptsToDirectory "${INIT_DIR}"
  1091. fi
  1092. toLogInfo "Copy scripts done."
  1093. }
  1094. #== 【4】=调用 agent 64位数lib路径(lib64/installaction)执行指令 --create-cluster-timestamp-file
  1095. createFirstClusterTimestampFile() {
  1096. toLogInfo "Creating firstClusterTimestamp file"
  1097. #== 调用 agent 64位数lib路径(lib64/installaction)执行指令 --create-cluster-timestamp-file
  1098. "$(getAgentInstallActionPath)" "--create-cluster-timestamp-file" >>"${LOG_FILE}" 2>&1
  1099. }
  1100. #== 【4】=配置数据存储目录
  1101. setupDataStorageDir() {
  1102. toLogInfo "Setup datastorage dir..."
  1103. local dataStorage
  1104. dataStorage="$(getValueFromConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${LEGACY_AGENT_CONF_FILE}" "${DATA_STORAGE_DIR}")"
  1105. if [ "${dataStorage}"x = "${LOG_DIR}"x ]; then
  1106. toLogInfo "Detected legacy data storage setting, changing it to the new default location"
  1107. writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${DATA_STORAGE_DIR}" "${LEGACY_AGENT_CONF_FILE}"
  1108. writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${DATA_STORAGE_DIR}" "${INSTALLER_CONF_FILE}"
  1109. fi
  1110. if [ "${PARAM_DATA_STORAGE}" ]; then
  1111. writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${PARAM_DATA_STORAGE}" "${LEGACY_AGENT_CONF_FILE}"
  1112. writeParamToConfigFile "${CONF_FIELD_NM_DATA_STORAGE}" "${PARAM_DATA_STORAGE}" "${INSTALLER_CONF_FILE}"
  1113. fi
  1114. toLogInfo "Setup datastorage dir done."
  1115. }
  1116. #**********************************************************
  1117. # Processing command line parameters
  1118. #**********************************************************
  1119. #== 【0】=help
  1120. displayHelp() {
  1121. printf '%s\n' "Usage: $(basename "${INSTALLER_FILE}") [-h] [-v] "
  1122. #== 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]"
  1123. local beginStr="Usage: "
  1124. local pad="${#beginStr}"
  1125. printf "\n\n"
  1126. pad=25
  1127. printf "%-${pad}s%s\n" "-h, --help" "Display this help and exit."
  1128. printf "%-${pad}s%s\n" "-v, --version" "Print version and exit."
  1129. }
  1130. printParamMessage() {
  1131. local paramNm="${1}"
  1132. local paramValue="${2}"
  1133. toConsoleInfo "---> Parameter ${paramNm}=${paramValue}."
  1134. }
  1135. printOtherParamMessage() {
  1136. local param="${1}"
  1137. toConsoleInfo "---> Parameter ${param}"
  1138. }
  1139. #== 【0】=大小写转化,并返回判断结果
  1140. istrcmp() {
  1141. local s1
  1142. local s2
  1143. s1="$(printf '%s' "${1}" | tr '[:upper:]' '[:lower:]')"
  1144. s2="$(printf '%s' "${2}" | tr '[:upper:]' '[:lower:]')"
  1145. [ "${s1}"x = "${s2}"x ]
  1146. }
  1147. #== 【0】=
  1148. isParamTrue() {
  1149. [ "${1}"x = "1"x ] || [ "${1}"x = "true"x ] || [ "${1}"x = "enable"x ] || [ "${1}"x = "yes"x ]
  1150. }
  1151. #== 【1】【5】=
  1152. isParamFalse() {
  1153. [ "${1}"x = "0"x ] || [ "${1}"x = "false"x ] || [ "${1}"x = "disable"x ] || [ "${1}"x = "no"x ]
  1154. }
  1155. #== 【1】【5】=
  1156. invertBoolValue() {
  1157. local valueToInvert="${1}"
  1158. if isParamFalse "${valueToInvert}"; then
  1159. printf '%s' "true"
  1160. else
  1161. printf '%s' "false"
  1162. fi
  1163. }
  1164. #== shellcheck disable=SC2003
  1165. #== 【0】=获取参数值
  1166. getParamValue() {
  1167. local paramName="${1}"
  1168. local input="${2}"
  1169. local paramNameLength="${#paramName}"
  1170. paramNameLength=$((paramNameLength + 1))
  1171. local partParam
  1172. partParam="$(expr substr "${input}" 1 ${paramNameLength})"
  1173. # partParam=$(substr "${input}" 1 ${paramNameLength})
  1174. if ! istrcmp "${partParam}" "${paramName}="; then
  1175. return 1
  1176. fi
  1177. local valueSeparator=$((paramNameLength + 1))
  1178. local value
  1179. value="$(expr substr "${input}" ${valueSeparator} 1000)"
  1180. # value=$(substr "${input}" ${valueSeparator} 1000)
  1181. if [ -z "${value}" ]; then
  1182. return 1
  1183. fi
  1184. printf '%s' "${value}"
  1185. return 0
  1186. }
  1187. #== 【0】=获取bool参数
  1188. readBoolParam() {
  1189. local value
  1190. value="$(getParamValue "${1}" "${2}")"
  1191. if value="$(getBoolParam "${value}")"; then
  1192. printf "%s" "${value}"
  1193. return 0
  1194. fi
  1195. return 1
  1196. }
  1197. #== 【0】=获取bool参数
  1198. getBoolParam() {
  1199. local value="${1}"
  1200. if [ "${value}" ]; then
  1201. if isParamFalse "${value}"; then
  1202. printf "false"
  1203. return 0
  1204. fi
  1205. if isParamTrue "${value}"; then
  1206. printf "true"
  1207. return 0
  1208. fi
  1209. fi
  1210. return 1
  1211. }
  1212. #== 【0】=校验格式是否规范[1、大于4个字符且不能"cw."开头,2、不能超过100字符,3、只能包含字母数字字符,连字符,下划线和点。]
  1213. validateParameter() {
  1214. local name="${1}"
  1215. local value="${2}"
  1216. if [ "$(printf '%s' "${value}" | cut -c -3)"x = "cw."x ]; then
  1217. toConsoleError "${name} must not begin with 'cw.'"
  1218. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1219. fi
  1220. if [ "${#value}" -gt 100 ]; then
  1221. toConsoleError "Maximum allowed length of ${name} is 100."
  1222. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1223. fi
  1224. if printf '%s' "${value}" | grep -q "[^[:alnum:]._-]"; then
  1225. toConsoleError "${name} can only contain alphanumeric characters, hyphen, underscore and dot."
  1226. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1227. fi
  1228. }
  1229. #== 【0】=验证用户和用户组是否匹配
  1230. validateUserAndGroupParameters() {
  1231. local user="${1}"
  1232. local group="${2}"
  1233. local permittedNameRegex='^[[:alnum:]._][[:alnum:]._-]{2,31}$'
  1234. if [ ! "${group}" ]; then
  1235. group="${user}"
  1236. fi
  1237. if ! printf '%s' "${user}" | grep -qE "${permittedNameRegex}"; then
  1238. toConsoleError "USER can only contain alphanumeric characters, hyphen, underscore and dot, and must have length from 3 to 32 characters."
  1239. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1240. fi
  1241. if ! printf '%s' "${group}" | grep -qE "${permittedNameRegex}"; then
  1242. toConsoleError "GROUP can only contain alphanumeric characters, hyphen, underscore and dot, and must have length from 3 to 32 characters."
  1243. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1244. fi
  1245. #== 校验用户/用户组信息
  1246. validateUserPrimaryGroup "${user}" "${group}"
  1247. }
  1248. #== 【0】【3】【5】=获取系统权限信息
  1249. getSystemEntityInfo() {
  1250. local database="${1}"
  1251. local valueToCheck="${2}"
  1252. #== 校验命令getent是否存在
  1253. if ! isAvailable "getent"; then
  1254. toLogInfo "Command getent is not available"
  1255. return 2
  1256. fi
  1257. #== 查看系统权限
  1258. local output
  1259. output="$(getent "${database}" "${valueToCheck}" 2>&1)"
  1260. local returnCode=$?
  1261. if [ "${returnCode}" != 0 ]; then
  1262. if [ "${returnCode}" != 2 ]; then
  1263. toLogWarn "Failed to check ${valueToCheck} in ${database} database, message: ${output}, code: ${returnCode}"
  1264. fi
  1265. return 1
  1266. elif [ ! "${output}" ]; then
  1267. toLogWarn "Failed to get user information: getent returned no output"
  1268. fi
  1269. printf '%s' "${output}"
  1270. return 0
  1271. }
  1272. #== 【0】【3】=查看用户/用户组信息
  1273. isEntityPassedById() {
  1274. local database="${1}"
  1275. local name="${2}"
  1276. local output
  1277. output="$(getSystemEntityInfo "${database}" "${name}")"
  1278. local returnCode=$?
  1279. if [ ${returnCode} -ne 0 ]; then
  1280. if [ ${returnCode} -eq 2 ]; then
  1281. toLogInfo "Installer will not be able to verify whether entity was passed by name or by ID"
  1282. fi
  1283. return 1
  1284. fi
  1285. local nameFromDatabase
  1286. nameFromDatabase="$(printf '%s' "${output}" | cut -d: -f1)"
  1287. if [ "${nameFromDatabase}"x = "${name}"x ]; then
  1288. return 1
  1289. fi
  1290. toLogWarn "Name from config and from ${database} system database do not match"
  1291. toLogWarn "Config: ${name}, database: ${nameFromDatabase}"
  1292. return 0
  1293. }
  1294. #== 【0】【3】【5】=用户是否存在
  1295. userExistsInSystem() {
  1296. local user="${1}"
  1297. getSystemEntityInfo "passwd" "${user}" >/dev/null
  1298. local returnCode=$?
  1299. if [ ${returnCode} -ne 2 ]; then
  1300. return ${returnCode}
  1301. fi
  1302. toLogInfo "Trying to determine user existence using 'id' command"
  1303. id "${user}" >/dev/null 2>&1
  1304. }
  1305. #== 【5】= 查看group
  1306. groupExistsInSystem() {
  1307. local group="${1}"
  1308. getSystemEntityInfo "group" "${group}" >/dev/null
  1309. local returnCode=$?
  1310. if [ ${returnCode} -ne 2 ]; then
  1311. return ${returnCode}
  1312. fi
  1313. toLogInfo "Installer will not be able to determine group existence"
  1314. return 1
  1315. }
  1316. #== 【3】=用户是否存在
  1317. validateUserExistence() {
  1318. local user="${1}"
  1319. if ! userExistsInSystem "${user}"; then
  1320. toConsoleError "User named '${user}' configured for ${BRAND_PRODUCT_NAME} does not exist. Installation aborted."
  1321. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1322. fi
  1323. }
  1324. #== 【0】【3】=检查用户/用户组信息
  1325. checkIfEntityWasNotPassedById() {
  1326. local database="${1}"
  1327. local valueToCheck="${2}"
  1328. local valueTypeToLog="user"
  1329. if [ "${database}"x = "group"x ]; then
  1330. valueTypeToLog="group"
  1331. fi
  1332. if isEntityPassedById "${database}" "${valueToCheck}"; then
  1333. toConsoleError "\"${valueToCheck}\" is not a ${valueTypeToLog} name but its ID. Installation aborted."
  1334. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1335. fi
  1336. }
  1337. #== 【0】【3】=用户权限下用户组ID
  1338. getUserPrimaryGroupIdForComparison() {
  1339. local user="${1}"
  1340. local userPrimaryGroupId
  1341. userPrimaryGroupId="$(getSystemEntityInfo "passwd" "${user}")"
  1342. local returnCode=$?
  1343. if [ ${returnCode} -ne 2 ]; then
  1344. printf '%s' "${userPrimaryGroupId}" | cut -d: -f4
  1345. return ${returnCode}
  1346. fi
  1347. toLogInfo "Returning user primary group name instead of its id"
  1348. id -gn "${user}"
  1349. }
  1350. #== 【0】【3】=获取用户组信息
  1351. getGroupIdForComparison() {
  1352. local group="${1}"
  1353. local groupId
  1354. groupId="$(getSystemEntityInfo "group" "${group}")"
  1355. local returnCode=$?
  1356. if [ ${returnCode} -ne 2 ]; then
  1357. printf '%s' "${groupId}" | cut -d: -f3
  1358. return ${returnCode}
  1359. fi
  1360. toLogInfo "Returning group name instead of its id"
  1361. printf '%s' "${group}"
  1362. }
  1363. #== 【0】【3】=校验用户/用户组信息
  1364. validateUserPrimaryGroup() {
  1365. local user="${1}"
  1366. local group="${2}"
  1367. if ! userExistsInSystem "${user}"; then
  1368. return
  1369. fi
  1370. checkIfEntityWasNotPassedById "passwd" "${user}"
  1371. checkIfEntityWasNotPassedById "group" "${group}"
  1372. #== 获取用户组ID
  1373. local groupId
  1374. groupId="$(getGroupIdForComparison "${group}")"
  1375. #== 获取用户下用户组ID
  1376. local userPrimaryGroupId
  1377. userPrimaryGroupId="$(getUserPrimaryGroupIdForComparison "${user}")"
  1378. toConsoleInfo "#DEBUG== group \"${group}\" id: \"${groupId}\", user \"${user}\" primaryGroupId: \"${userPrimaryGroupId}\""
  1379. if [ "${userPrimaryGroupId}"x != "${groupId}"x ]; then
  1380. toConsoleError "User named \"${user}\" does not have group named \"${group}\" as its primary group. Installation aborted."
  1381. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1382. fi
  1383. }
  1384. #== 【3】=检查用户/用户组是否存在和匹配
  1385. checkUserAndGroupFromConfig() {
  1386. local configUser
  1387. local configGroup
  1388. configUser="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  1389. configGroup="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  1390. toLogInfo "Checking validity of user account '${configUser}:${configGroup}'"
  1391. if [ "${PARAM_UPGRADE}"x = "yes"x ]; then
  1392. validateUserExistence "${configUser}"
  1393. fi
  1394. #== 校验用户/用户组信息
  1395. validateUserPrimaryGroup "${configUser}" "${configGroup}"
  1396. }
  1397. #== 【0】=解析命令行中参数
  1398. parseCommandLineParameters() {
  1399. local dataServerIsEmpty=true
  1400. local configServerIsEmpty=true
  1401. while [ $# -gt 0 ]; do
  1402. local param="${1}"
  1403. local value=
  1404. if value=$(getParamValue DATA_SERVER "${param}"); then
  1405. PARAM_DATA_SERVER="${value}"
  1406. dataServerIsEmpty=false
  1407. printParamMessage "DATA_SERVER" "${value}"
  1408. shift
  1409. continue
  1410. fi
  1411. if value=$(getParamValue CONFIG_SERVER "${param}"); then
  1412. PARAM_CONFIG_SERVER="${value}"
  1413. configServerIsEmpty=false
  1414. printParamMessage "CONFIG_SERVER" "${value}"
  1415. shift
  1416. continue
  1417. fi
  1418. if value=$(getParamValue LICENSE "${param}"); then
  1419. PARAM_LICENSE="${value}"
  1420. printParamMessage "LICENSE" "${value}"
  1421. shift
  1422. continue
  1423. fi
  1424. if value=$(getParamValue JSON_CONF "${param}"); then
  1425. PARAM_JSON_CONF="${value}"
  1426. printParamMessage "JSON_CONF" "${value}"
  1427. shift
  1428. continue
  1429. fi
  1430. if value=$(getParamValue INSTALL_DIR "${param}"); then
  1431. PARAM_INSTALL_DIR="${value}"
  1432. printParamMessage "INSTALL_DIR" "${value}"
  1433. shift
  1434. continue
  1435. fi
  1436. if value=$(getParamValue DATA_STORAGE "${param}"); then
  1437. PARAM_DATA_STORAGE="${value}"
  1438. printParamMessage "DATA_STORAGE" "${value}"
  1439. shift
  1440. continue
  1441. fi
  1442. if value=$(readBoolParam DISABLE_SYSTEM_LOGS_ACCESS "${param}"); then
  1443. PARAM_DISABLE_SYSTEM_LOGS_ACCESS="${value}"
  1444. printParamMessage "DISABLE_SYSTEM_LOGS_ACCESS" "${value}"
  1445. shift
  1446. continue
  1447. fi
  1448. if value=$(getParamValue INTERNAL_OVERRIDE_CHECKS "${param}"); then
  1449. if printf '%s' "${value}" | grep -wq "privileges"; then
  1450. PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK=true
  1451. fi
  1452. if printf '%s' "${value}" | grep -wq "downgrade"; then
  1453. SKIP_DOWNGRADE_CHECK=true
  1454. fi
  1455. printParamMessage "INTERNAL_OVERRIDE_CHECKS" "${value}"
  1456. shift
  1457. continue
  1458. fi
  1459. if value=$(readBoolParam INTERNAL_USE_UNPACK_CACHE "${param}"); then
  1460. PARAM_INTERNAL_USE_UNPACK_CACHE="${value}"
  1461. printParamMessage "INTERNAL_USE_UNPACK_CACHE" "${value}"
  1462. shift
  1463. continue
  1464. fi
  1465. if [ "${ARCH_ARCH}"x != "AIX"x ]; then
  1466. if value=$(getParamValue USER "${param}"); then
  1467. PARAM_USER="${value}"
  1468. printParamMessage "USER" "${value}"
  1469. shift
  1470. continue
  1471. fi
  1472. if value=$(getParamValue GROUP "${param}"); then
  1473. PARAM_GROUP="${value}"
  1474. printParamMessage "GROUP" "${value}"
  1475. shift
  1476. continue
  1477. fi
  1478. if value=$(readBoolParam NON_ROOT_MODE "${param}"); then
  1479. PARAM_NON_ROOT_MODE="${value}"
  1480. printParamMessage "NON_ROOT_MODE" "${value}"
  1481. shift
  1482. continue
  1483. fi
  1484. if value=$(readBoolParam USER_LOGIN "${param}"); then
  1485. PARAM_USER_LOGIN="${value}"
  1486. printParamMessage "USER_LOGIN" "${value}"
  1487. shift
  1488. continue
  1489. fi
  1490. #== 自定义参数获取
  1491. if value=$(getParamValue TEST "${param}"); then
  1492. PARAM_TEST="${value}"
  1493. printParamMessage "TEST" "${value}"
  1494. shift
  1495. continue
  1496. fi
  1497. #== 自定义bool参数
  1498. if value=$(readBoolParam BOOL "${param}"); then
  1499. PARAM_BOOL="${value}"
  1500. printParamMessage "BOOL" "${value}"
  1501. shift
  1502. continue
  1503. fi
  1504. if value=$(readBoolParam DISABLE_ROOT_FALLBACK "${param}"); then
  1505. PARAM_DISABLE_ROOT_FALLBACK="${value}"
  1506. printParamMessage "DISABLE_ROOT_FALLBACK" "${value}"
  1507. shift
  1508. continue
  1509. fi
  1510. if value=$(readBoolParam NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK "${param}"); then
  1511. PARAM_INTERNAL_NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK="${value}"
  1512. printParamMessage "NON_ROOT_MODE_SKIP_PRIVILEGES_CHECK" "${value}"
  1513. shift
  1514. continue
  1515. fi
  1516. if value=$(readBoolParam INTERNAL_SKIP_SELINUX_POLICY_INSTALLER "${param}"); then
  1517. #== PARAM_INTERNAL_SKIP_SELINUX_POLICY_INSTALLER="${value}"
  1518. printParamMessage "INTERNAL_SKIP_SELINUX_POLICY_INSTALLER" "${value}"
  1519. shift
  1520. continue
  1521. fi
  1522. if value=$(readBoolParam DOCKER_ENABLED "${param}"); then
  1523. #== PARAM_INTERNAL_DEPLOYED_VIA_CONTAINER="${value}"
  1524. printParamMessage "DOCKER_ENABLED" "${value}"
  1525. shift
  1526. continue
  1527. fi
  1528. fi
  1529. if [ "${ARCH_ARCH}"x != "AIX"x ] && [ "${ARCH_ARCH}"x != "S390"x ]; then
  1530. if value=$(readBoolParam INTERNAL_DISABLE_DUMPPROC "${param}"); then
  1531. #== PARAM_INTERNAL_DISABLE_DUMPPROC="${value}"
  1532. printParamMessage "INTERNAL_DISABLE_DUMPPROC" "${value}"
  1533. shift
  1534. continue
  1535. fi
  1536. fi
  1537. if [ "${param}"x = "-h"x ] || [ "${param}"x = "--help"x ]; then
  1538. displayHelp
  1539. finishInstallation "${EXIT_CODE_OK}"
  1540. fi
  1541. if [ "${param}"x = "-v"x ] || [ "${param}"x = "--version"x ]; then
  1542. printf "%s\n" "${AGENT_INSTALLER_VERSION}"
  1543. finishInstallation "${EXIT_CODE_OK}"
  1544. fi
  1545. printOtherParamMessage ${param}
  1546. shift
  1547. done
  1548. if [ "${configServerIsEmpty}"x = "true"x ] && [ "${dataServerIsEmpty}"x != "true"x ]; then
  1549. PARAM_CONFIG_SERVER="${PARAM_DATA_SERVER}"
  1550. fi
  1551. }
  1552. #== 【0】=校验PARAM_INSTALL_DIR是否规范【1、不能包含空格,2、不能在根目录,3、安装路径必须是绝对的】
  1553. validateInstallPathParameter() {
  1554. if printf '%s' "${PARAM_INSTALL_DIR}" | grep -q "[[:space:]]"; then
  1555. toConsoleError "Installation path must not contain spaces."
  1556. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1557. fi
  1558. if [ "${PARAM_INSTALL_DIR}"x = "/"x ]; then
  1559. toConsoleError "Installation path must not point to the filesystem root directory."
  1560. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1561. fi
  1562. if [ "$(printf '%s' "${PARAM_INSTALL_DIR}" | cut -c 1)"x != "/"x ]; then
  1563. toConsoleError "Installation path must be absolute."
  1564. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1565. fi
  1566. }
  1567. #== 【0】=校验PARAM_DATA_STORAGE是否规范【1、不能包含空格,2、不能在根目录,3、安装路径必须是绝对的,4、数据目录不能放在安装目录下】
  1568. validateDataStorageParameter() {
  1569. if printf '%s' "${PARAM_DATA_STORAGE}" | grep -q "[[:space:]]"; then
  1570. toConsoleError "Data storage path must not contain spaces."
  1571. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1572. fi
  1573. if [ "${PARAM_DATA_STORAGE}"x = "/"x ]; then
  1574. toConsoleError "Data storage path must not point to the filesystem root directory."
  1575. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1576. fi
  1577. if [ "$(printf '%s' "${PARAM_DATA_STORAGE}" | cut -c 1)"x != "/"x ]; then
  1578. toConsoleError "Data storage path must be absolute."
  1579. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1580. fi
  1581. if printf '%s' "${PARAM_DATA_STORAGE}" | grep -q "^${INSTALL_DIR}"; then
  1582. toConsoleError "Data storage path must not be located within ${INSTALL_DIR}."
  1583. finishInstallation "${EXIT_CODE_INVALID_PARAM}"
  1584. fi
  1585. }
  1586. #**********************************************************
  1587. # Config files
  1588. #**********************************************************
  1589. #== 【3】【5】=格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
  1590. formatSize() {
  1591. local sizeInKiB="${1}"
  1592. local formattedSize
  1593. for symbol in "KiB" "MiB" "GiB" "TiB"; do
  1594. if printf '%s' "${sizeInKiB}" | awk '$1 >= 1024 { exit 1; }'; then
  1595. formattedSize="${sizeInKiB} ${symbol}"
  1596. break
  1597. fi
  1598. sizeInKiB="$(printf '%s' "${sizeInKiB}" | awk '{ print $1 / 1024 }')"
  1599. done
  1600. printf '%s' "${formattedSize}"
  1601. }
  1602. #== 【3】【5】=
  1603. cropSizeValue() {
  1604. local size="${1}"
  1605. local value
  1606. local unit
  1607. value="$(printf '%s' "${size}" | cut -d' ' -f1)"
  1608. unit="$(printf '%s' "${size}" | cut -d' ' -f2)"
  1609. printf '%.2f %s' "${value}" "${unit}"
  1610. }
  1611. #== 【3】【5】=检查目录可用空间(单位:k)
  1612. checkFreeSpace() {
  1613. local path="${1}"
  1614. local requiredSpaceInKiB="${2}"
  1615. local dfOutput
  1616. local baseFilesystem
  1617. local freeSpace
  1618. local formattedRequiredSpace
  1619. local formattedFreeSpace
  1620. #== shellcheck disable=SC2086
  1621. dfOutput="$(df -P ${AIX_DF_SPECIFIC_FLAG} "${path}" | tail -n +2)"
  1622. #== 文件系统目录
  1623. baseFilesystem="$(printf "%s" "${dfOutput}" | awk '{ print $NF }')"
  1624. #== 剩余空间(单位:k)
  1625. freeSpace="$(printf "%s" "${dfOutput}" | awk '{ print $4 }')"
  1626. #== 格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
  1627. formattedRequiredSpace="$(formatSize "${requiredSpaceInKiB}")"
  1628. toLogInfo "Filesystem with ${path} is mounted under ${baseFilesystem}. Space required: ${formattedRequiredSpace}."
  1629. if [ ! "${freeSpace}" ]; then
  1630. printf 'Cannot determine amount of free space on %s (filesystem mounted under %s)' "${path}" "${baseFilesystem}"
  1631. return 1
  1632. fi
  1633. #== 格式化空间大小(将 1024KiB 格式化成 1MiB, 将 1024MiB 格式化成 1GiB,...)
  1634. formattedFreeSpace="$(formatSize "${freeSpace}")"
  1635. toLogInfo "Available free space: ${formattedFreeSpace}"
  1636. if [ "${freeSpace}" -lt "${requiredSpaceInKiB}" ]; then
  1637. printf 'Not enough free space on %s (filesystem mounted under %s). ' "${path}" "${baseFilesystem}"
  1638. printf 'Required: %s, available: %s' "$(cropSizeValue "${formattedRequiredSpace}")" "$(cropSizeValue "${formattedFreeSpace}")"
  1639. return 2
  1640. fi
  1641. printf 'Free space is sufficient'
  1642. return 0
  1643. }
  1644. #== 【3】=检查文件系统类型
  1645. #== 【3】=检查安装目录空间
  1646. checkInstallPathFreeSpace() {
  1647. local externalTarSize=${EXTERNAL_TAR_SIZE}
  1648. local artifactsSize=${ARTIFACTS_SIZE}
  1649. #== use 10% additional margin
  1650. local requiredSpace=$((externalTarSize + artifactsSize * 11 / 10))
  1651. #== convert to kibibytes
  1652. requiredSpace=$((requiredSpace / 1024))
  1653. toConsoleInfo "Checking free space in ${INSTALL_DIR}"
  1654. local message
  1655. #== 检查目录可用空间(单位:k)
  1656. message="$(checkFreeSpace "${INSTALL_DIR}" "${requiredSpace}")"
  1657. case $? in
  1658. 0) toLogInfo "${message}" ;;
  1659. 1) toConsoleWarn "${message}. Installation may be incomplete." ;;
  1660. 2)
  1661. toConsoleError "${message}"
  1662. finishInstallation "${EXIT_CODE_NOT_ENOUGH_SPACE}"
  1663. ;;
  1664. esac
  1665. }
  1666. #== 【3】=获取指定路径的文件系统信息
  1667. getFilesystemInfo() {
  1668. if [ "${ARCH_ARCH}"x = "AIX"x ]; then
  1669. mount | grep " ${1} "
  1670. else
  1671. grep " ${1} " /proc/self/mounts
  1672. fi
  1673. }
  1674. #== 【3】=检查目录指定权限信息
  1675. checkAccessRightsTo() {
  1676. local dir="${1}"
  1677. toLogInfo "Checking access to ${dir}..."
  1678. #== 获取文件权限信息
  1679. local accessRights
  1680. accessRights="$(arch_getAccessRights "${dir}" | cut -c 2-4)"
  1681. if ! printf '%s' "${accessRights}" | grep -q rwx; then
  1682. toConsoleError "Insufficient permissions on ${dir}: '${accessRights}'."
  1683. toLogInfo "$(ls -dl "${dir}" 2>&1)"
  1684. finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
  1685. fi
  1686. local dfResult
  1687. local filesystem
  1688. local filesystemInfo
  1689. dfResult="$(df -P "${dir}")"
  1690. #== 获取目录文件系统路径
  1691. filesystem="$(printf '%s' "${dfResult}" | tail -1 | awk '{ print $NF }')"
  1692. #== 获取指定路径的文件系统信息
  1693. filesystemInfo="$(getFilesystemInfo "${filesystem}")"
  1694. if ! printf '%s' "${filesystemInfo}" | grep -qw rw; then
  1695. toLogWarn "df-based check determined filesystem mounted under ${filesystem} as readonly, trying fallback."
  1696. toLogWarn "Filesystem access rights: '${filesystemInfo}'"
  1697. toLogWarn "df returned: ${dfResult}"
  1698. if ! testWriteAccessToDir "${dir}"; then
  1699. toConsoleError "readonly filesystem mounted under ${filesystem}"
  1700. finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
  1701. fi
  1702. fi
  1703. toLogInfo "Rights on directory ${dir} are sufficient"
  1704. } 2>>"${LOG_FILE}"
  1705. #== 【3】=目录是否写权限
  1706. checkIfInstallationPathIsWriteable() {
  1707. for dir in "${@}"; do
  1708. if [ -d "${dir}" ]; then
  1709. checkAccessRightsTo "${dir}"
  1710. break
  1711. fi
  1712. done
  1713. }
  1714. #== 【3】=检查目录权限
  1715. checkAccessRightsToDirs() {
  1716. checkIfInstallationPathIsWriteable "${INSTALL_DIR}" "${BASE_INSTALL_DIR}" "${INSTALL_BASE}" /
  1717. if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
  1718. checkAccessRightsTo "${INIT_DIR}"
  1719. fi
  1720. }
  1721. #== 【0】=检查系统是 LINUX、AIX及指令集(X86_64\IA64\X86)
  1722. checkSystemCompatibility() {
  1723. local expectedPlatform="LINUX"
  1724. if [ "${ARCH_ARCH}"x = "AIX"x ]; then
  1725. expectedPlatform="AIX"
  1726. fi
  1727. #== 获取系统名称
  1728. local platform
  1729. platform="$(uname | sed -e 's/_.*//' | sed -e 's/\///' | tr '[:lower:]' '[:upper:]')"
  1730. if [ "${platform}"x != "${expectedPlatform}"x ]; then
  1731. printf "Cannot determine platform or platform not supported: <%s>" "${platform}"
  1732. return 1
  1733. fi
  1734. #== 检查系统指令集(X86_64\IA64\X86)
  1735. local detectedArchitecture
  1736. if ! detectedArchitecture="$(arch_checkArchitectureCompatibility)"; then
  1737. printf "Cannot determine architecture or architecture not supported: <%s>" "${detectedArchitecture}"
  1738. return 1
  1739. fi
  1740. printf 'Detected platform: %s' "${platform}"
  1741. if [ "${detectedArchitecture}" ]; then
  1742. printf ' arch: %s' "${detectedArchitecture}"
  1743. fi
  1744. return 0
  1745. }
  1746. #== 【4】=从sh文件读取压缩文件 tarfile_$$.base64
  1747. separateExternalTar() {
  1748. toLogInfo "Determining begin of tar archive..."
  1749. local tarBegin
  1750. local tarEnd
  1751. #== 压缩文件开始行数,占位符为【#################ENDOFSCRIPTMARK############】
  1752. tarBegin="$(locateDelimiter "#################ENDOFSCRIPTMARK############" "")"
  1753. tarBegin=$((tarBegin + 1))
  1754. #== 压缩文件结束行数,占位符为【----SIGNED-INSTALLER】
  1755. tarEnd="$(locateDelimiter "----SIGNED-INSTALLER" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS})"
  1756. toLogInfo "tarBegin=${tarBegin} tarEnd=${tarEnd}"
  1757. if [ ! "${tarEnd}" ]; then
  1758. toConsoleError "S/MIME signature is missing, installation package is corrupted."
  1759. finishInstallation "${EXIT_CODE_CORRUPTED_PACKAGE}"
  1760. fi
  1761. local tarLength=$((tarEnd - tarBegin))
  1762. toLogInfo "tarLength=${tarLength}"
  1763. #== 从sh文件读取压缩文件 tarfile_$$.base64
  1764. tail -n +"${tarBegin}" "${INSTALLER_FILE}" 2>/dev/null | head -${tarLength} >"${EXTERNAL_TAR_FILE}"
  1765. }
  1766. #== 【4】【5】=进入目录
  1767. changeWorkingDir() {
  1768. if ! cd "${1}"; then
  1769. toLogError "Failed to change working directory to ${1}"
  1770. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  1771. fi
  1772. }
  1773. #== shellcheck disable=SC2181
  1774. #== 【4】=解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
  1775. unpackArchiveWithoutCache() {
  1776. #== 解压文件编码
  1777. local base64Binary="${UNPACK_BINARY}"
  1778. #== 解压文件编码参数
  1779. local base64BinaryArgs="${UNPACK_BINARY_ARGS}"
  1780. #== 使用xzdec命令可以进行liblzma为基础的xz文件解压缩
  1781. local xzBinary="${INSTALL_DIR}/xzdec"
  1782. #== 进入目录
  1783. changeWorkingDir "${INSTALL_DIR}"
  1784. if ! isAvailable tar; then
  1785. toConsoleError "tar binary not found. Setup can't continue"
  1786. finishInstallation "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
  1787. fi
  1788. local totalLines
  1789. if ! isAvailable "${base64Binary}"; then
  1790. toLogInfo "${base64Binary} not found. Falling back to openssl decode"
  1791. if ! isAvailable openssl; then
  1792. toConsoleError "Neither ${base64Binary} nor openssl can be found. Setup can't continue"
  1793. finishInstallation "${EXIT_CODE_MISCONFIGURED_ENVIRONMENT}"
  1794. fi
  1795. #== 如果没有 base64 命令,则使用 openssl 解压文件
  1796. base64Binary="openssl"
  1797. base64BinaryArgs="enc -base64 -d -in"
  1798. if [ "${ARCH_ARCH}"x = "AIX"x ]; then
  1799. #truncate the first and the last one line due to specific format of uuencode on aix
  1800. totalLines="$(wc -l "${EXTERNAL_TAR_FILE}" | awk '{print $1}')"
  1801. head -$((totalLines - 1)) "${EXTERNAL_TAR_FILE}" 2>/dev/null | tail +2 >"${EXTERNAL_TAR_FILE}.$$"
  1802. mv -f "${EXTERNAL_TAR_FILE}.$$" "${EXTERNAL_TAR_FILE}"
  1803. fi
  1804. fi
  1805. {
  1806. #== base64 转编码后,执行 tar 解压
  1807. "${base64Binary}" "${base64BinaryArgs}" "${EXTERNAL_TAR_FILE}" | tar -x -p -f -
  1808. } 2>>"${LOG_FILE}"
  1809. #== base64 转编码 或 tar解压失败
  1810. if [ $? -gt 0 ]; then
  1811. toConsoleError "Archive is corrupted or memory allocation failed. Installation aborted."
  1812. finishInstallation "${EXIT_CODE_NOT_ENOUGH_MEMORY}"
  1813. fi
  1814. #== 进入目录
  1815. changeWorkingDir "${TMP_DIR}"
  1816. {
  1817. #== 使用xzdec命令解压后,执行 tar 解压
  1818. "${xzBinary}" "${INTERNAL_TAR_FILE}" | tar -x -p -f -
  1819. } 2>>"${LOG_FILE}"
  1820. if [ $? -gt 0 ]; then
  1821. toConsoleError "XZ compressed archive is corrupted or memory allocation failed. Installation aborted."
  1822. finishInstallation "${EXIT_CODE_NOT_ENOUGH_MEMORY}"
  1823. fi
  1824. #== 进入目录
  1825. changeWorkingDir "${INSTALL_DIR}"
  1826. }
  1827. #== 【4】=解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
  1828. unpackArchive() {
  1829. toConsoleInfo "Unpacking. This may take a while..."
  1830. #== 【参数】是否使用解压缓存
  1831. if [ "${PARAM_INTERNAL_USE_UNPACK_CACHE}"x = "true"x ]; then
  1832. if [ -d "${UNPACK_CACHE}" ]; then
  1833. toLogInfo "Unpack cache will be used."
  1834. cp -Rp "${UNPACK_CACHE}"/* "${TMP_DIR}"
  1835. else
  1836. toLogInfo "Unpack cache does not exist."
  1837. mkdir -p "${UNPACK_CACHE}"
  1838. #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
  1839. unpackArchiveWithoutCache
  1840. cp -Rp "${TMP_DIR}"/* "${UNPACK_CACHE}"
  1841. fi
  1842. else
  1843. toLogInfo "Unpacking without cache"
  1844. #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
  1845. unpackArchiveWithoutCache
  1846. fi
  1847. toConsoleInfo "Unpacking complete."
  1848. }
  1849. #== 【3】=检查容器部署、运行情况、配置参数
  1850. #isDeployedInsideOpenVZContainer
  1851. #isProcessRunningInContainer
  1852. #isDeployedViaContainer
  1853. #== Checking if libc is new enough
  1854. #== 【3】=格式化version
  1855. format_version() {
  1856. printf '%s' "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }'
  1857. }
  1858. #== 【3】=格式化路径
  1859. format_patch() {
  1860. printf '%s' "$@" | tail -n 1 | awk -F- '{ printf("%d\n", $3); }'
  1861. }
  1862. #== 【3】=检查是否降级安装
  1863. checkIfDowngrade() {
  1864. if [ "${SKIP_DOWNGRADE_CHECK}"x = "true"x ]; then
  1865. toConsoleInfo "Skipped downgrade check"
  1866. return
  1867. fi
  1868. local installVersionFile="${INSTALL_DIR}/installer.version"
  1869. if [ ! -f "${installVersionFile}" ]; then
  1870. toLogWarn "Could not perform downgrade check, ${installVersionFile} file is missing"
  1871. return
  1872. fi
  1873. local oldVersion
  1874. oldVersion="$(cat "${installVersionFile}")"
  1875. if [ "$(format_version "${AGENT_INSTALLER_VERSION}")" -eq "$(format_version "${oldVersion}")" ]; then
  1876. toConsoleError "${BRAND_PRODUCT_NAME} is already installed, please uninstall the old version using [${INSTALL_DIR}/uninstall.sh]."
  1877. # toLogError "Attempted downgrade from ${oldVersion} to ${AGENT_INSTALLER_VERSION}"
  1878. finishInstallation "${EXIT_CODE_UNSUPPORTED_DOWNGRADE}"
  1879. fi
  1880. }
  1881. #== 【3】=检查是否已经安装
  1882. checkIfAlreadyInstalled() {
  1883. if [ -f "${INSTALL_DIR}/uninstall.sh" ] && [ -f "${AGENT_BIN_DIR}/${AGENT_PROC}" ] ; then
  1884. # toConsoleError "Agent already installed. Uninstalling previous version."
  1885. # finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  1886. checkIfDowngrade
  1887. PARAM_UPGRADE="yes"
  1888. else
  1889. # if [ -f "${SIF_AGENT_INSTALL_PATH}/lib64/${AGENT_BIN}" ]; then
  1890. # sif_toConsoleError "Upgrade is not possible because uninstall script is missing"
  1891. # finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  1892. # fi
  1893. local fileNum
  1894. fileNum=`ls ${INSTALL_DIR} | wc -l`
  1895. if [ "${fileNum}" -gt 1 ];then
  1896. toConsoleError "${INSTALL_DIR} is not empty. Please clean or change the installation directory manually."
  1897. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  1898. fi
  1899. fi
  1900. }
  1901. #**********************************************************
  1902. # Init related functions
  1903. #**********************************************************
  1904. #== clears dependencies in LSB init script
  1905. #== 【5】=清除LSB init脚本中的依赖项
  1906. clearDependenciesInLSBInit() {
  1907. local file="${1}"
  1908. toConsoleInfo "Clearing dependencies in file ${file}"
  1909. awk '
  1910. BEGIN {
  1911. req_start_found=0;
  1912. req_stop_found=0;
  1913. REQ_START="# Required-Start:";
  1914. REQ_STOP="# Required-Stop:";
  1915. PATTERN_REQ_START="^" REQ_START;
  1916. PATTERN_REQ_STOP="^" REQ_STOP;
  1917. }
  1918. {
  1919. if ($0 ~ PATTERN_REQ_START && req_start_found == 0) {
  1920. print REQ_START;
  1921. req_start_found++;
  1922. } else if ($0 ~ PATTERN_REQ_STOP && req_stop_found == 0) {
  1923. print REQ_STOP;
  1924. req_stop_found++;
  1925. } else
  1926. print $0
  1927. }' "${file}" >"${file}.tmp" && mv -f "${file}.tmp" "${file}"
  1928. chmod +x "${file}"
  1929. }
  1930. #== 【5】=指定目录添加自动启动脚本
  1931. addScriptToSystemvAutostart() {
  1932. local prefix="${1}"
  1933. local file="${2}"
  1934. local suffix="${3}"
  1935. toLogInfo "Adding ${file} to autostart"
  1936. #== 自动启动工具
  1937. if ! runAutostartAddingTool "${prefix}" "${file}" "${suffix}"; then
  1938. toLogWarn "Failed to add ${file} script to autostart. Trying without dependencies..."
  1939. #== 清除LSB init脚本中的依赖项
  1940. clearDependenciesInLSBInit "${INIT_DIR}/${file}"
  1941. if ! runAutostartAddingTool "${prefix}" "${file}" "${suffix}"; then
  1942. toConsoleError "Cannot add ${file} to autostart. For details, see: ${LOG_FILE}"
  1943. fi
  1944. fi
  1945. }
  1946. #== 【5】=指定目录添加自动启动脚本
  1947. addScriptsToAutostart() {
  1948. local prefix="${1}"
  1949. local suffix="${2}"
  1950. #== 指定目录添加自动启动脚本
  1951. addScriptToSystemvAutostart "${prefix}" "${SERVICE_SCRIPT_FILE}" "${suffix}"
  1952. }
  1953. #== 【5】=设置自动启动
  1954. #setupSystemvAutostart() {
  1955. # toLogInfo "Adding ${BRAND_AGENT_PRODUCT_NAME} to autostart..."
  1956. #
  1957. # if [ -x /usr/bin/update-rc.d ]; then #Ubuntu
  1958. # #== 指定目录添加自动启动脚本
  1959. # addScriptsToAutostart "/usr/bin/update-rc.d " "defaults"
  1960. # elif [ -x /usr/sbin/update-rc.d ]; then #Ubuntu
  1961. # addScriptsToAutostart "/usr/sbin/update-rc.d " "defaults"
  1962. # elif [ -x /sbin/chkconfig ]; then #RedHat
  1963. # addScriptsToAutostart "/sbin/chkconfig --add "
  1964. # elif [ -x /usr/lib/lsb/install_initd ]; then #Suse
  1965. # addScriptsToAutostart "/usr/lib/lsb/install_initd ${INIT_DIR}/"
  1966. # elif [ "${ARCH_ARCH}"x = "AIX"x ]; then
  1967. # #== 【不存在】
  1968. # arch_setAutostart
  1969. # else
  1970. # toConsoleError "Couldn't add ${BRAND_AGENT_PRODUCT_NAME} to autostart. Please adjust and add it manually."
  1971. # fi
  1972. #}
  1973. #== 【5】=设置 cwserveragent.service 中用户
  1974. setServiceScriptUser() {
  1975. if ! isNonRootModeEnabled; then
  1976. return
  1977. fi
  1978. #== 读取用户名(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-user)
  1979. local user
  1980. user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  1981. #== 修改 cwserveragent.service 中用户信息
  1982. sed -i "s/User=.*/User=${user}/g" "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}"
  1983. }
  1984. #== 【5】=配置自动启动 cwserveragent.service
  1985. setupSystemdAutostart() {
  1986. mv -f "${AGENT_SCRIPTS_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" "${SYSTEMD_UNIT_FILES_DIR}/"
  1987. setRightsForFiles "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}" 644
  1988. #== 设置 cwserveragent.service 中用户
  1989. setServiceScriptUser
  1990. if isAvailable restorecon; then
  1991. restorecon "${SYSTEMD_UNIT_FILES_DIR}/${SYSTEMD_UNIT_FILE_AGENT}"
  1992. fi
  1993. #== 执行 systemctl 命令配置允许开机启动 cwserveragent.service
  1994. executeSystemctlCommand enable "${SYSTEMD_UNIT_FILE_AGENT}"
  1995. #== 执行 systemctl 命令重新加载模块
  1996. executeSystemctlCommand daemon-reload ""
  1997. }
  1998. #== 【6】=运行service 脚本
  1999. execIntoServiceScript() {
  2000. toConsoleInfo "${SERVICE_SCRIPT_FILE} will be started via exec()"
  2001. #== 清除安装临时文件
  2002. cleanInstallationTemporaryFiles
  2003. toLogInfo "Installation finished, PID $$."
  2004. local command="exec ${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE} exec"
  2005. toLogInfo "Executing: ${command}"
  2006. #== 执行 cwserveragent exec
  2007. ${command}
  2008. toLogError "Could not execute: ${command}"
  2009. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2010. }
  2011. #== 【6】=运行agent
  2012. runAgents() {
  2013. toConsoleInfo "Starting agents..."
  2014. toLogInfo "Using ${INIT_SYSTEM} to start the agent"
  2015. if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
  2016. #== 运行初始化命令(通过 service start 方式 或 直接运行可执行命令)
  2017. executeInitScriptCommand start "true"
  2018. else
  2019. #== 执行 systemctl start 命令
  2020. executeSystemctlCommand start "${SYSTEMD_UNIT_FILE_AGENT}"
  2021. fi
  2022. if [ $? -eq 0 ]; then
  2023. toConsoleInfo "${SERVICE_SCRIPT_FILE} service started"
  2024. else
  2025. toConsoleError "Failed to start service: ${SERVICE_SCRIPT_FILE}, it is possible that your init system is not functioning properly. For details, see: ${LOG_FILE}"
  2026. fi
  2027. }
  2028. #== 【5】=配置自动启动
  2029. #setupAutostart() {
  2030. # if [ "${INIT_SYSTEM}"x = "${INIT_SYSTEM_SYSV}"x ]; then
  2031. # #== 设置自动启动
  2032. # setupSystemvAutostart
  2033. # else
  2034. # #== 配置自动启动 cwserveragent.service
  2035. # setupSystemdAutostart
  2036. # fi
  2037. #}
  2038. #**********************************************************
  2039. # Process agent related functions
  2040. #**********************************************************
  2041. #== 【5】=创建 agent 状态文件
  2042. createAgentStateFile() {
  2043. local path="${1}"
  2044. local agentStateContents="RUNNING"
  2045. toLogInfo "Writing ${agentStateContents} to ${path} file"
  2046. {
  2047. printf "%s" "${agentStateContents}" >"${path}.tmp"
  2048. mv -f "${path}.tmp" "${path}"
  2049. } 2>>"${LOG_FILE}"
  2050. }
  2051. #== 【0】=检查全路径是否可读权限(目录最深100层)
  2052. checkIfPathIsGloballyReadable() {
  2053. local path="${1}"
  2054. local sourcePath="${path}"
  2055. local maxDepth=100
  2056. while [ "${path}"x != "/"x ]; do
  2057. #== 【0】=获取文件权限信息
  2058. local accessRights
  2059. accessRights="$(arch_getAccessRights "${path}")"
  2060. if ! printf '%s' "${accessRights}" | cut -c 8-10 | grep -qE "r.[xt]"; then
  2061. toConsoleError "Insufficient access rights (${accessRights}) on: ${path}"
  2062. toConsoleError "${sourcePath} path must be globally readable (r-x permissions for others)."
  2063. toConsoleError "Please adjust the permissions and then retry the installation."
  2064. finishInstallation "${EXIT_CODE_INSUFFICIENT_PERMISSIONS}"
  2065. fi
  2066. path="$(dirname "${path}")"
  2067. maxDepth=$((maxDepth - 1))
  2068. if [ "${maxDepth}" -eq 0 ]; then
  2069. toLogWarn "Unable to verify access rights on ${path}"
  2070. return
  2071. fi
  2072. done
  2073. }
  2074. #== 【0】=创建 PARAM_INSTALL_DIR -> INSTALL_DIR 软连接
  2075. createSymlinkToInstallLocation() {
  2076. #== INSTALL_DIR 不能是软链接地址
  2077. if [ -L "${INSTALL_DIR}" ] && [ ! -e "${INSTALL_DIR}" ]; then
  2078. toConsoleError "Detected that ${INSTALL_DIR} is a dangling symlink, please remove it and then retry the installation"
  2079. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2080. fi
  2081. #== PARAM_INSTALL_DIR 和 INSTALL_DIR 都不能是空地址
  2082. if [ "${PARAM_INSTALL_DIR}"x = "${INSTALL_DIR}"x ] || [ -z "${PARAM_INSTALL_DIR}" ]; then
  2083. return
  2084. fi
  2085. #== INSTALL_DIR 是软连接,并获取 PARAM_INSTALL_DIR 和 INSTALL_DIR 的真实地址
  2086. if [ -L "${INSTALL_DIR}" ] && [ "$(readLink -m "${PARAM_INSTALL_DIR}")"x = "$(readLink -m "${INSTALL_DIR}")"x ]; then
  2087. return
  2088. fi
  2089. #== 目录存在,表示未卸载
  2090. if [ -e "${INSTALL_DIR}" ]; then
  2091. toConsoleError "Leftovers from previous agent installation detected"
  2092. toConsoleError "If you wish to use INSTALL_DIR parameter then perform a cleanup by following these steps:"
  2093. toConsoleError "1. Uninstall the agent"
  2094. toConsoleError "2. Restart all applications that have Deep Monitoring enabled (host restart is fine as well)"
  2095. toConsoleError "3. Remove ${INSTALL_DIR}"
  2096. toConsoleError "and then retry the installation."
  2097. toConsoleError "#DEBUG==For further information please visit ${HELP_URL}/command-line-install"
  2098. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2099. fi
  2100. #== 创建不存在的目录
  2101. createDirIfNotExistAndSetRights "${PARAM_INSTALL_DIR}" 1775
  2102. #== 检查全路径是否可读权限(目录最深100层)
  2103. checkIfPathIsGloballyReadable "${PARAM_INSTALL_DIR}"
  2104. #== 创建不存在的目录 /opt/cloudwise
  2105. createDirIfNotExistAndSetRights "${BASE_INSTALL_DIR}" 755
  2106. #== 创建 PARAM_INSTALL_DIR -> INSTALL_DIR
  2107. local lnOutput
  2108. if lnOutput="$(ln -fs "${PARAM_INSTALL_DIR}" "${INSTALL_DIR}" 2>&1)"; then
  2109. toConsoleInfo "Symlink ${INSTALL_DIR} -> ${PARAM_INSTALL_DIR} created"
  2110. else
  2111. toConsoleError "Failed to create symlink ${INSTALL_DIR} -> ${PARAM_INSTALL_DIR}, aborting installation: ${lnOutput}"
  2112. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2113. fi
  2114. }
  2115. #== 【5】=修改文件系统用户和用户组
  2116. changeFilesOwnership() {
  2117. local user
  2118. local group
  2119. user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  2120. group="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  2121. toLogInfo "Changing ownership of files to root:${group}"
  2122. #== /opt/cloudwise/cwserveragent 目录下用户和用户组
  2123. commandErrorWrapper chown "${user}:${group}" "${AGENT_BASE_DIR}"
  2124. commandErrorWrapper chown -R "${user}:${group}" "${INSTALL_DIR}"
  2125. toLogInfo "Recursively changing group ownership of ${AGENT_CONF_DIR} to ${group}"
  2126. }
  2127. #== 【5】=文件用户权限检查
  2128. fileCapabilitiesCompatibilityCheck() {
  2129. #== 获取配置用户
  2130. local user
  2131. user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  2132. #== 获取OS bin配置路径 /opt/cloudwise/cwserveragent/lib64/cloudwiseosconfig
  2133. if output="$("$(getOsConfigBinPath)" file-capabilities-compatibility-check "${user}" 2>&1)"; then
  2134. return 0
  2135. fi
  2136. if [ "${PARAM_NON_ROOT_MODE}" ]; then
  2137. toConsoleWarn "Failed to enable non-privileged mode, kernel does not support file capabilities. For details, see: ${LOG_FILE}"
  2138. toLogWarn "Capabilities test output: ${output}"
  2139. else
  2140. toConsoleInfo "Non-privileged mode was not enabled, kernel does not support file capabilities. For details, see: ${LOG_FILE}"
  2141. toLogInfo "Capabilities test output: ${output}"
  2142. fi
  2143. #== 设置删除root权限
  2144. "$(getAgentInstallActionPath)" "--set-drop-root-privileges" "false" >>"${LOG_FILE}" 2>&1
  2145. return 1
  2146. }
  2147. #**********************************************************
  2148. # User and group related functions
  2149. #**********************************************************
  2150. #== 【5】=添加用户组
  2151. addGroup() {
  2152. local group="${1}"
  2153. if groupExistsInSystem "${group}"; then
  2154. toLogInfo "Group '${group}' already exists"
  2155. return 0
  2156. fi
  2157. local errorMessage
  2158. errorMessage="$(groupadd "${group}" 2>&1)"
  2159. local returnCode=$?
  2160. case ${returnCode} in
  2161. 0) toLogInfo "Group '${group}' successfully created" ;;
  2162. 9) toLogInfo "Group '${group}' already exists" ;;
  2163. *)
  2164. toLogError "Error occured while adding '${group}' group, return code: ${returnCode}, message ${errorMessage}"
  2165. return 1
  2166. ;;
  2167. esac
  2168. return 0
  2169. }
  2170. #== 【5】=添加用户
  2171. addUser() {
  2172. local user="${1}"
  2173. local group="${2}"
  2174. local groupCreated="${3}"
  2175. local errorMessage
  2176. local mod="/bin/false"
  2177. if [ "${PARAM_USER_LOGIN}"x == "true"x ]; then
  2178. mod="/bin/bash"
  2179. fi
  2180. if userExistsInSystem "${user}"; then
  2181. toLogInfo "User '${user}' already exists."
  2182. #-- 权限更新
  2183. # errorMessage="$(usermod -s "${mod}" "${user}" 2>&1)"
  2184. return 0
  2185. fi
  2186. if [ "${groupCreated}" -eq 0 ]; then
  2187. errorMessage="$(useradd -r --shell "${mod}" -g "${group}" "${user}" 2>&1)"
  2188. else
  2189. errorMessage="$(useradd -r --shell "${mod}" "${user}" 2>&1)"
  2190. fi
  2191. local returnCode=$?
  2192. if [ ${returnCode} -ne 0 ]; then
  2193. toConsoleError "Failed to create user '${user}'"
  2194. toLogError "Error occured while adding '${user}' user, return value: ${returnCode}, error message: ${errorMessage}."
  2195. return 1
  2196. fi
  2197. toConsoleInfo "User '${user}' added successfully."
  2198. return 0
  2199. }
  2200. #== 【5】=添加用户和用户组信息
  2201. addUserAndGroup() {
  2202. local user="${1}"
  2203. local group="${2}"
  2204. #== 添加用户组
  2205. addGroup "${group}"
  2206. #== 添加用户
  2207. addUser "${user}" "${group}" $?
  2208. }
  2209. #== 【5】=配置用户和用户组
  2210. handleUser() {
  2211. toLogInfo "Processing user and group..."
  2212. local user
  2213. local group
  2214. #== 读取用户名(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-user)
  2215. user="$(getValueFromConfigFile "${CONF_FIELD_NM_USER}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  2216. #== 读取用户组(调用 agent 64位数lib路径(lib64/installaction)执行指令 --get-group)
  2217. group="$(getValueFromConfigFile "${CONF_FIELD_NM_GROUP}" "${LEGACY_AGENT_CONF_FILE}" "${BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME}")"
  2218. #== 添加用户和用户组信息
  2219. addUserAndGroup "${user}" "${group}"
  2220. }
  2221. #== 【4】=获取agent preLoad 安装路径,并校验是否可执行
  2222. checkCompatibilityWithInstallActionBinary() {
  2223. local output
  2224. #== 获取agent preLoad 安装路径,并校验是否可执行
  2225. output="$("$(getAgentInstallActionPathPreInstallation)" "--sanity-check" 2>&1)"
  2226. local exitCode=$?
  2227. toLogAdaptive ${exitCode} "Compatibility check exit code = ${exitCode}, output = ${output}"
  2228. if [ ${exitCode} -ne 0 ] || [ "${output}"x != "SUCCESS"x ]; then
  2229. toConsoleError "System compatibility check failed, this may be caused by a problem with glibc, dynamic loader or incompatible operating system version."
  2230. toConsoleError "Detected version: $(detectLinuxDistribution)"
  2231. toConsoleError "For a list of supported distributions and versions, see: ${HELP_URL}"
  2232. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2233. fi
  2234. }
  2235. #== 【4】=【部署】解压文件
  2236. extractFiles() {
  2237. umask 000
  2238. toConsoleInfo "Extracting..."
  2239. #== 从sh文件读取压缩文件 tarfile_$$.base64
  2240. separateExternalTar
  2241. #== 解压文件(1、通过base64转码后,执行tar解压;2、通过xzdec解压xz文件后在执行tar解压)
  2242. unpackArchive
  2243. umask 022
  2244. }
  2245. #== 【3】=检查发现初始化系统信息(INIT_SYSTEM、INIT_SYSTEM_VERSION、INIT_DIR)
  2246. detectInitSystem() {
  2247. #== 获取初始化系统信息 (INIT_SYSTEM、INIT_SYSTEM_VERSION)
  2248. checkInitSystem
  2249. toLogInfo "Detected init system: ${INIT_SYSTEM}, version: ${INIT_SYSTEM_VERSION}"
  2250. #== 设置系统初始化脚本目录
  2251. if ! setLocationOfScripts; then
  2252. toConsoleError "Cannot determine location of init scripts."
  2253. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2254. fi
  2255. }
  2256. #== 【4】=【旧配置】读取旧配置参数
  2257. readLegacySetting() {
  2258. local paramName="${1}"
  2259. local value
  2260. value="$(sed -n "s|^${paramName}=||p" "${LEGACY_AGENT_CONF_FILE}" | tr -d '\r' 2>/dev/null)"
  2261. if [ "${value}" ]; then
  2262. local valueToPrint="${value}"
  2263. if [ "${paramName}"x = "${CONF_FIELD_NM_LICENSE}"x ]; then
  2264. valueToPrint="***"
  2265. fi
  2266. toLogInfo "Read legacy value: ${paramName} = ${valueToPrint}"
  2267. fi
  2268. printf '%s' "${value}"
  2269. }
  2270. #== 【4】=【旧配置】迁移旧配置文件
  2271. migrateLegacySettingsFromAgentConf() {
  2272. toLogInfo "Looking for legacy config to migrate."
  2273. #== 旧配置文件
  2274. if [ ! -f "${LEGACY_AGENT_CONF_FILE}" ]; then
  2275. toLogInfo "Unable to read agent config file, skipping legacy config migration"
  2276. return
  2277. fi
  2278. if [ ! "${PARAM_CONFIG_SERVER}" ]; then
  2279. local configServerValue
  2280. configServerValue="$(readLegacySetting ${CONF_FIELD_NM_CONFIG_SERVER})"
  2281. toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_CONFIG_SERVER}: ${PARAM_CONFIG_SERVER}"
  2282. if [ "${configServerValue}"x = "http://localhost:8020"x ]; then
  2283. toLogInfo "Param 'server' has default value set, skipping it"
  2284. else
  2285. PARAM_CONFIG_SERVER="${configServerValue}"
  2286. fi
  2287. fi
  2288. if [ ! "${PARAM_DATA_SERVER}" ]; then
  2289. PARAM_DATA_SERVER="$(readLegacySetting ${CONF_FIELD_NM_DATA_SERVER})"
  2290. toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_DATA_SERVER}: ${PARAM_DATA_SERVER}"
  2291. fi
  2292. if [ ! "${PARAM_LICENSE}" ]; then
  2293. PARAM_LICENSE="$(readLegacySetting ${CONF_FIELD_NM_LICENSE})"
  2294. toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_LICENSE}: ${PARAM_LICENSE}"
  2295. fi
  2296. if [ ! "${PARAM_JSON_CONF}" ]; then
  2297. PARAM_JSON_CONF="$(readLegacySetting ${CONF_FIELD_NM_JSON_CONF})"
  2298. toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_JSON_CONF}: ${PARAM_JSON_CONF}"
  2299. fi
  2300. if [ ! "${PARAM_USER}" ]; then
  2301. PARAM_USER="$(readLegacySetting ${CONF_FIELD_NM_USER})"
  2302. toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_USER}: ${PARAM_USER}"
  2303. if [ ! "${PARAM_GROUP}" ]; then
  2304. PARAM_GROUP="$(readLegacySetting ${CONF_FIELD_NM_GROUP})"
  2305. toConsoleInfo "#DEBUG== legacy config: ${CONF_FIELD_NM_GROUP}: ${PARAM_GROUP}"
  2306. fi
  2307. fi
  2308. }
  2309. listProcesses() {
  2310. local errorMessage="${1}"
  2311. local includeRegex="${2}"
  2312. local excludeRegex=" grep"
  2313. if [ "${3}" ]; then
  2314. excludeRegex="grep|${3}"
  2315. fi
  2316. toLogInfo "#DEBUG== listProcesses command: ps -e -o \"pid,args\" 2>&1 | grep -E \"${includeRegex}\" | awk '{{ print \$1,\$2 }}' | grep -vE \"${excludeRegex}\""
  2317. local output
  2318. if ! output="$(pgrep -f "pid,args" 2>&1 | grep -E "${includeRegex}" | awk '{{ print $1,$2 }}')"; then
  2319. toLogError "Failed to get ${errorMessage}, output: ${output}"
  2320. return 1
  2321. fi
  2322. local foundProcesses
  2323. foundProcesses="$(printf '%s' "${output}" | grep -vE "${excludeRegex}")"
  2324. if [ ! "${foundProcesses}" ]; then
  2325. return 1
  2326. fi
  2327. printf '%s' "${foundProcesses}" | awk '{{ print $1 }}'
  2328. return 0
  2329. }
  2330. #== 版本&帮助信息
  2331. preParams() {
  2332. if [ $# -gt 0 ]; then
  2333. if [ "${1}"x = "-h"x ] || [ "${1}"x = "--help"x ]; then
  2334. displayHelp
  2335. exit "${EXIT_CODE_OK}"
  2336. fi
  2337. if [ "${1}"x = "-v"x ] || [ "${1}"x = "--version"x ]; then
  2338. pad=20
  2339. printf "%-${pad}s%s\n" "Version:" "${AGENT_INSTALLER_VERSION}"
  2340. printf "%-${pad}s%s\n" "Commit:" "${AGENT_BUILD_TAG}"
  2341. printf "%-${pad}s%s\n" "Build At(UTC):" "${AGENT_BUILD_DATE_INFO}"
  2342. printf "%-${pad}s%s\n" "Uploader:" "${AGENT_BUILD_UPLOADER}"
  2343. exit "${EXIT_CODE_OK}"
  2344. fi
  2345. fi
  2346. }
  2347. #**********************************************************
  2348. # Main script functions
  2349. #**********************************************************
  2350. #== 【0】=初始化安装环境
  2351. initializeInstallation() {
  2352. preParams "$@"
  2353. #== 设置PATH
  2354. setPATH
  2355. #== 配置umask权限
  2356. local initialUmask
  2357. initialUmask="$(umask)"
  2358. umask 022
  2359. #== 读取配置参数
  2360. # readParamsSection
  2361. #== 解析命令行参数
  2362. parseCommandLineParameters "$@"
  2363. #== 校验配置参数
  2364. #== 是否存在多个同时安装操作【通过判断 INSTALLER_LOCK_FILE 】
  2365. if isAnotherInstallationRunning; then
  2366. #== 结束安装操作
  2367. finishInstallation "${EXIT_CODE_ANOTHER_INSTALLER_RUNNING}" "keep_lock_file"
  2368. fi
  2369. #== 创建安装标示文件 /tmp/${BRAND_PRODUCT_NAME_LOWER}.lock
  2370. createInstallationLockFile
  2371. #== 配置是否更新
  2372. PARAM_UPGRADE="no"
  2373. #== 获取并校验系统兼容性【LINUX/AIX X86_64/IA64】
  2374. local platformDetectionString
  2375. if ! platformDetectionString="$(checkSystemCompatibility)"; then
  2376. toConsoleError "${platformDetectionString}"
  2377. finishInstallation "${EXIT_CODE_OS_NOT_SUPPORTED}"
  2378. fi
  2379. #== 创建 PARAM_INSTALL_DIR -> INSTALL_DIR 软连接
  2380. createSymlinkToInstallLocation
  2381. #== 创建日志目录及日志文件installation_$$.log
  2382. createLogDirsIfMissing
  2383. #== 配置信号捕获,执行清空安装临时目录
  2384. configureSignalHandling "cleanInstallationTemporaryFiles"
  2385. #== 常规日志
  2386. initializeLog "${@}"
  2387. toLogInfo "Initial umask: ${initialUmask}"
  2388. toConsoleInfo "${platformDetectionString}"
  2389. toLogInfo "Distribution: $(detectLinuxDistribution)"
  2390. }
  2391. #== 【3】=安装前检查
  2392. preInstallationChecks() {
  2393. #== 检查发现初始化系统信息(INIT_SYSTEM、INIT_SYSTEM_VERSION、INIT_DIR)
  2394. detectInitSystem
  2395. #== 检查目录权限
  2396. checkAccessRightsToDirs
  2397. #== 创建临时目录
  2398. prepareTempFolder
  2399. #== 检查是否已经安装
  2400. checkIfAlreadyInstalled
  2401. if [ ! "${PARAM_USER}" ] && [ "${ARCH_ARCH}"x != "AIX"x ] ; then
  2402. #== 配置文件中配置用户和用户组是否存在
  2403. checkUserAndGroupFromConfig
  2404. fi
  2405. #== 检查安装目录空间
  2406. checkInstallPathFreeSpace
  2407. }
  2408. uninstallAgent() {
  2409. toConsoleInfo "Agent already installed. Uninstalling previous version."
  2410. # printf '%s' "upgrade" >"${UNINSTALL_INFO_FILE_LEGACY_PATH}"
  2411. #shellcheck disable=SC2086
  2412. "${INSTALL_DIR}/uninstall.sh" $$ ${SKIP_PRIVILEGES_CHECK} 2>>"${LOG_FILE}"
  2413. local uninstallExitCode=$?
  2414. if [ ${uninstallExitCode} -gt 0 ]; then
  2415. toConsoleError "Error during uninstalling, code: ${uninstallExitCode}. Installation aborted."
  2416. finishInstallation "${EXIT_CODE_GENERIC_ERROR}"
  2417. fi
  2418. toConsoleInfo "Agent uninstalled."
  2419. }
  2420. #== 【4】=部署文件
  2421. deployFiles() {
  2422. if [ "${PARAM_UPGRADE}" = "yes" ]; then
  2423. uninstallAgent
  2424. fi
  2425. #== 【部署】解压文件
  2426. extractFiles
  2427. setupAll
  2428. createCurrentVersionSymlink
  2429. }
  2430. enableRootDropping() {
  2431. local output=
  2432. if ! isAvailable setcap; then
  2433. toConsoleWarn "Failed to enable non-privileged mode, kernel does not support file capabilities. Set NON_ROOT_MODE=false."
  2434. #== writeParamToConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "false" "${LEGACY_AGENT_CONF_FILE}"
  2435. #== writeParamToConfigFile "${CONF_FIELD_NM_NON_ROOT_MODE}" "false" "${INSTALLER_CONF_FILE}"
  2436. #== editScriptFileParam "readonly PARAM_NON_ROOT_MODE" "false" "${AGENT_SCRIPTS_DIR}/${SERVICE_SCRIPT_FILE}"
  2437. return
  2438. fi
  2439. #== 设置文件权限 (https://www.cnblogs.com/xzongblogs/p/14106481.html)
  2440. #== CAP_DAC_OVERRIDE:绕过文件的读,写,和执行权限检查。
  2441. #== CAP_FOWNER:对于通常要求进程的文件系统 UID 与文件的 UID 匹配的操作,绕过权限检查 (比如,chmod(2),utime(2)),除了那些包含在 CAP_DAC_OVERRIDE 和 CAP_DAC_READ_SEARCH 中的操作
  2442. #== CAP_IPC_LOCK:允许锁定共享内存片段
  2443. #== CAP_SYS_PTRACE:允许跟踪任何进程
  2444. #== CAP_SYS_ADMIN:访问特权 perf 事件信息
  2445. #== CAP_SYS_RESOURCE:忽略资源限制
  2446. #== CAP_NET_ADMIN:允许执行多种网络有关的操作
  2447. commandErrorWrapper setcap cap_dac_override,cap_fowner,cap_ipc_lock,cap_sys_ptrace,cap_sys_admin,cap_sys_resource,cap_net_admin+ep "${AGENT_BIN_DIR}/${AGENT_PROC}"
  2448. local setCapCwServerAgentExitCode=$?
  2449. if [ ${setCapCwServerAgentExitCode} -eq 0 ] ; then
  2450. toConsoleInfo "Set file capabilities [${AGENT_PROC}]"
  2451. else
  2452. toConsoleWarn "Failed to enable non-privileged mode. Exit Code : ${setCapCwServerAgentExitCode} . For details, see: ${LOG_FILE}"
  2453. toLogWarn "Set file capabilities output: ${output}"
  2454. fi
  2455. }
  2456. #== 【5】=配置安装
  2457. configureInstallation() {
  2458. #== 配置参数(param、installation.conf)
  2459. #== 自定义修改配置, sed ,echo ... 参考 applyAgentSettings
  2460. if [ "${PARAM_TEST}" ]; then
  2461. toConsoleOnly "Applying test value is: ${PARAM_TEST}"
  2462. fi
  2463. #== 获取bool值参数
  2464. if [ "${PARAM_BOOL}" ]; then
  2465. toConsoleOnly "Applying bool value is: ${PARAM_BOOL}"
  2466. fi
  2467. if [ "${ARCH_ARCH}"x != "AIX"x ]; then
  2468. #== 配置用户和用户组
  2469. if handleUser; then
  2470. #== 修改文件系统用户和用户组
  2471. changeFilesOwnership
  2472. fi
  2473. #== 设置root权限
  2474. enableRootDropping
  2475. fi
  2476. #== 系统配置(策略配置、dump proc、agent 进程配置、自动启动)
  2477. # setupAutostart
  2478. }
  2479. #== 【6】=验证安装状态、运行启动脚本
  2480. postInstallationSteps() {
  2481. #== 运行agent
  2482. # runAgents
  2483. finishInstallation "${EXIT_CODE_OK}"
  2484. }
  2485. readonly CURR_PATH="$(pwd)"
  2486. main() {
  2487. #== 【0】=初始化安装环境
  2488. initializeInstallation "$@"
  2489. #== 【3】=安装前检查
  2490. preInstallationChecks
  2491. #== 【4】=部署文件
  2492. deployFiles
  2493. #== 【5】=配置安装
  2494. configureInstallation
  2495. #== 【6】=验证安装状态、运行启动脚本
  2496. postInstallationSteps
  2497. }
  2498. #**********************************************************
  2499. # Script start
  2500. #**********************************************************
  2501. main "$@"
  2502. ################################################
  2503. ############# DO NOT REMOVE THIS ###############
  2504. #### DO NOT ADD ANYTHING BELOW THIS COMMENT ####
  2505. ################################################
  2506. #################ENDOFSCRIPTMARK################
  2507. ----SIGNED-INSTALLER