functions.sh 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. #!/bin/sh
  2. # SPDX-License-Identifier: GPL-3.0-or-later
  3. # next unused error code: L0003
  4. # make sure we have a UID
  5. [ -z "${UID}" ] && UID="$(id -u)"
  6. # -----------------------------------------------------------------------------
  7. setup_terminal() {
  8. TPUT_RESET=""
  9. TPUT_BLACK=""
  10. TPUT_RED=""
  11. TPUT_GREEN=""
  12. TPUT_YELLOW=""
  13. TPUT_BLUE=""
  14. TPUT_PURPLE=""
  15. TPUT_CYAN=""
  16. TPUT_WHITE=""
  17. TPUT_BGBLACK=""
  18. TPUT_BGRED=""
  19. TPUT_BGGREEN=""
  20. TPUT_BGYELLOW=""
  21. TPUT_BGBLUE=""
  22. TPUT_BGPURPLE=""
  23. TPUT_BGCYAN=""
  24. TPUT_BGWHITE=""
  25. TPUT_BOLD=""
  26. TPUT_DIM=""
  27. TPUT_UNDERLINED=""
  28. TPUT_BLINK=""
  29. TPUT_INVERTED=""
  30. TPUT_STANDOUT=""
  31. TPUT_BELL=""
  32. TPUT_CLEAR=""
  33. # Is stderr on the terminal? If not, then fail
  34. test -t 2 || return 1
  35. if command -v tput 1> /dev/null 2>&1; then
  36. if [ $(($(tput colors 2> /dev/null))) -ge 8 ]; then
  37. # Enable colors
  38. TPUT_RESET="$(tput sgr 0)"
  39. # shellcheck disable=SC2034
  40. TPUT_BLACK="$(tput setaf 0)"
  41. # shellcheck disable=SC2034
  42. TPUT_RED="$(tput setaf 1)"
  43. TPUT_GREEN="$(tput setaf 2)"
  44. # shellcheck disable=SC2034
  45. TPUT_YELLOW="$(tput setaf 3)"
  46. # shellcheck disable=SC2034
  47. TPUT_BLUE="$(tput setaf 4)"
  48. # shellcheck disable=SC2034
  49. TPUT_PURPLE="$(tput setaf 5)"
  50. # shellcheck disable=SC2034
  51. TPUT_CYAN="$(tput setaf 6)"
  52. TPUT_WHITE="$(tput setaf 7)"
  53. # shellcheck disable=SC2034
  54. TPUT_BGBLACK="$(tput setab 0)"
  55. TPUT_BGRED="$(tput setab 1)"
  56. TPUT_BGGREEN="$(tput setab 2)"
  57. # shellcheck disable=SC2034
  58. TPUT_BGYELLOW="$(tput setab 3)"
  59. # shellcheck disable=SC2034
  60. TPUT_BGBLUE="$(tput setab 4)"
  61. # shellcheck disable=SC2034
  62. TPUT_BGPURPLE="$(tput setab 5)"
  63. # shellcheck disable=SC2034
  64. TPUT_BGCYAN="$(tput setab 6)"
  65. # shellcheck disable=SC2034
  66. TPUT_BGWHITE="$(tput setab 7)"
  67. TPUT_BOLD="$(tput bold)"
  68. TPUT_DIM="$(tput dim)"
  69. # shellcheck disable=SC2034
  70. TPUT_UNDERLINED="$(tput smul)"
  71. # shellcheck disable=SC2034
  72. TPUT_BLINK="$(tput blink)"
  73. # shellcheck disable=SC2034
  74. TPUT_INVERTED="$(tput rev)"
  75. # shellcheck disable=SC2034
  76. TPUT_STANDOUT="$(tput smso)"
  77. # shellcheck disable=SC2034
  78. TPUT_BELL="$(tput bel)"
  79. # shellcheck disable=SC2034
  80. TPUT_CLEAR="$(tput clear)"
  81. fi
  82. fi
  83. return 0
  84. }
  85. setup_terminal || echo > /dev/null
  86. progress() {
  87. echo >&2 " --- ${TPUT_DIM}${TPUT_BOLD}${*}${TPUT_RESET} --- "
  88. }
  89. check_for_curl() {
  90. if [ -z "${curl}" ]; then
  91. curl="$(PATH="${PATH}:/opt/netdata/bin" command -v curl 2>/dev/null && true)"
  92. fi
  93. }
  94. get() {
  95. url="${1}"
  96. check_for_curl
  97. if [ -n "${curl}" ]; then
  98. "${curl}" -q -o - -sSL --connect-timeout 10 --retry 3 "${url}"
  99. elif command -v wget > /dev/null 2>&1; then
  100. wget -T 15 -O - "${url}"
  101. else
  102. fatal "I need curl or wget to proceed, but neither is available on this system." "L0002"
  103. fi
  104. }
  105. download_file() {
  106. url="${1}"
  107. dest="${2}"
  108. name="${3}"
  109. opt="${4}"
  110. check_for_curl
  111. if [ -n "${curl}" ]; then
  112. run "${curl}" -q -sSL --connect-timeout 10 --retry 3 --output "${dest}" "${url}"
  113. elif command -v wget > /dev/null 2>&1; then
  114. run wget -T 15 -O "${dest}" "${url}"
  115. else
  116. echo >&2
  117. echo >&2 "Downloading ${name} from '${url}' failed because of missing mandatory packages."
  118. if [ -n "$opt" ]; then
  119. echo >&2 "Either add packages or disable it by issuing '--disable-${opt}' in the installer"
  120. fi
  121. echo >&2
  122. run_failed "I need curl or wget to proceed, but neither is available on this system."
  123. fi
  124. }
  125. # -----------------------------------------------------------------------------
  126. # external component handling
  127. fetch_and_verify() {
  128. component="${1}"
  129. url="${2}"
  130. base_name="${3}"
  131. tmp="${4}"
  132. override="${5}"
  133. if [ -z "${override}" ]; then
  134. download_file "${url}" "${tmp}/${base_name}" "${component}"
  135. else
  136. progress "Using provided ${component} archive ${override}"
  137. run cp "${override}" "${tmp}/${base_name}"
  138. fi
  139. if [ ! -f "${tmp}/${base_name}" ] || [ ! -s "${tmp}/${base_name}" ]; then
  140. run_failed "Unable to find usable archive for ${component}"
  141. return 1
  142. fi
  143. grep "${base_name}\$" "${INSTALLER_DIR}/packaging/${component}.checksums" > "${tmp}/sha256sums.txt" 2> /dev/null
  144. # Checksum validation
  145. if ! (cd "${tmp}" && safe_sha256sum -c "sha256sums.txt"); then
  146. run_failed "${component} files checksum validation failed."
  147. return 1
  148. fi
  149. }
  150. # -----------------------------------------------------------------------------
  151. netdata_banner() {
  152. l1=" ^" \
  153. l2=" |.-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-" \
  154. l4=" +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+--->" \
  155. space=" "
  156. l3f=" | '-' '-' '-' '-' '-'"
  157. l3e=" '-' '-' '-' '-' '-' "
  158. netdata="netdata"
  159. chartcolor="${TPUT_DIM}"
  160. echo >&2
  161. echo >&2 "${chartcolor}${l1}${TPUT_RESET}"
  162. echo >&2 "${chartcolor}${l2%-. .-. .-. .-. .-. .-. .-. .-}${space}${TPUT_RESET}${TPUT_BOLD}${TPUT_GREEN}${netdata}${TPUT_RESET}${chartcolor}${l2# |.-. .-. .-. .-. .-. .-. .-. }${TPUT_RESET}"
  163. echo >&2 "${chartcolor}${l3f}${l3e}${TPUT_RESET}"
  164. echo >&2 "${chartcolor}${l4}${TPUT_RESET}"
  165. echo >&2
  166. }
  167. # -----------------------------------------------------------------------------
  168. # Feature management and configuration commands
  169. enable_feature() {
  170. NETDATA_CMAKE_OPTIONS="$(echo "${NETDATA_CMAKE_OPTIONS}" | sed -e "s/-DENABLE_${1}=Off[[:space:]]*//g" -e "s/-DENABLE_${1}=On[[:space:]]*//g")"
  171. if [ "${2}" -eq 1 ]; then
  172. NETDATA_CMAKE_OPTIONS="$(echo "${NETDATA_CMAKE_OPTIONS}" | sed "s/$/ -DENABLE_${1}=On/")"
  173. else
  174. NETDATA_CMAKE_OPTIONS="$(echo "${NETDATA_CMAKE_OPTIONS}" | sed "s/$/ -DENABLE_${1}=Off/")"
  175. fi
  176. }
  177. check_for_module() {
  178. if [ -z "${pkgconf}" ]; then
  179. pkgconf="$(command -v pkgconf 2>/dev/null)"
  180. [ -z "${pkgconf}" ] && pkgconf="$(command -v pkg-config 2>/dev/null)"
  181. [ -z "${pkgconf}" ] && fatal "Unable to find a usable pkgconf/pkg-config command, cannot build Netdata." I0013
  182. fi
  183. "${pkgconf}" "${1}"
  184. return "${?}"
  185. }
  186. check_for_feature() {
  187. feature_name="${1}"
  188. feature_state="${2}"
  189. shift 2
  190. feature_modules="${*}"
  191. if [ -z "${feature_state}" ]; then
  192. # shellcheck disable=SC2086
  193. if check_for_module ${feature_modules}; then
  194. enable_feature "${feature_name}" 1
  195. else
  196. enable_feature "${feature_name}" 0
  197. fi
  198. else
  199. enable_feature "${feature_name}" "${feature_state}"
  200. fi
  201. }
  202. prepare_cmake_options() {
  203. NETDATA_CMAKE_OPTIONS="-S ./ -B ${NETDATA_BUILD_DIR} ${CMAKE_OPTS} ${NETDATA_PREFIX+-DCMAKE_INSTALL_PREFIX="${NETDATA_PREFIX}"} ${NETDATA_USER:+-DNETDATA_USER=${NETDATA_USER}} ${NETDATA_CMAKE_OPTIONS} "
  204. if [ "${USE_SYSTEM_PROTOBUF:-1}" -eq 1 ]; then
  205. enable_feature BUNDLED_PROTOBUF 0
  206. else
  207. enable_feature BUNDLED_PROTOBUF 1
  208. fi
  209. if [ -z "${ENABLE_SYSTEMD_JOURNAL}" ]; then
  210. if check_for_module libsystemd; then
  211. if check_for_module libelogind; then
  212. ENABLE_SYSTEMD_JOURNAL=0
  213. else
  214. ENABLE_SYSTEMD_JOURNAL=1
  215. fi
  216. else
  217. ENABLE_SYSTEMD_JOURNAL=0
  218. fi
  219. fi
  220. enable_feature PLUGIN_SYSTEMD_JOURNAL "${ENABLE_SYSTEMD_JOURNAL}"
  221. if command -v cups-config >/dev/null 2>&1 || check_for_module libcups || check_for_module cups; then
  222. ENABLE_CUPS=1
  223. else
  224. ENABLE_CUPS=0
  225. fi
  226. enable_feature PLUGIN_CUPS "${ENABLE_CUPS}"
  227. IS_LINUX=0
  228. [ "$(uname -s)" = "Linux" ] && IS_LINUX=1
  229. enable_feature PLUGIN_DEBUGFS "${IS_LINUX}"
  230. enable_feature PLUGIN_PERF "${IS_LINUX}"
  231. enable_feature PLUGIN_SLABINFO "${IS_LINUX}"
  232. enable_feature PLUGIN_CGROUP_NETWORK "${IS_LINUX}"
  233. enable_feature PLUGIN_LOCAL_LISTENERS "${IS_LINUX}"
  234. enable_feature PLUGIN_EBPF "${ENABLE_EBPF:-0}"
  235. enable_feature PLUGIN_LOGS_MANAGEMENT "${ENABLE_LOGS_MANAGEMENT:-0}"
  236. enable_feature LOGS_MANAGEMENT_TESTS "${ENABLE_LOGS_MANAGEMENT_TESTS:-0}"
  237. enable_feature ACLK "${ENABLE_CLOUD:-1}"
  238. enable_feature CLOUD "${ENABLE_CLOUD:-1}"
  239. enable_feature BUNDLED_JSONC "${NETDATA_BUILD_JSON_C:-0}"
  240. enable_feature BUNDLED_YAML "${BUNDLE_YAML:-0}"
  241. enable_feature DBENGINE "${ENABLE_DBENGINE:-1}"
  242. enable_feature H2O "${ENABLE_H2O:-1}"
  243. enable_feature ML "${NETDATA_ENABLE_ML:-1}"
  244. ENABLE_APPS=0
  245. if [ "${IS_LINUX}" = 1 ] || [ "$(uname -s)" = "FreeBSD" ]; then
  246. ENABLE_APPS=1
  247. fi
  248. enable_feature PLUGIN_APPS "${ENABLE_APPS}"
  249. check_for_feature EXPORTER_PROMETHEUS_REMOTE_WRITE "${EXPORTER_PROMETHEUS}" snappy
  250. check_for_feature EXPORTER_MONGODB "${EXPORTER_MONGODB}" libmongoc-1.0
  251. check_for_feature PLUGIN_FREEIPMI "${ENABLE_FREEIPMI}" libipmimonitoring
  252. check_for_feature PLUGIN_NFACCT "${ENABLE_NFACCT}" libnetfilter_acct libnml
  253. check_for_feature PLUGIN_XENSTAT "${ENABLE_XENSTAT}" xenstat xenlight
  254. }
  255. # -----------------------------------------------------------------------------
  256. # portable service command
  257. service_cmd="$(command -v service 2> /dev/null || true)"
  258. rcservice_cmd="$(command -v rc-service 2> /dev/null || true)"
  259. systemctl_cmd="$(command -v systemctl 2> /dev/null || true)"
  260. service() {
  261. cmd="${1}"
  262. action="${2}"
  263. if [ -n "${systemctl_cmd}" ]; then
  264. run "${systemctl_cmd}" "${action}" "${cmd}"
  265. return $?
  266. elif [ -n "${service_cmd}" ]; then
  267. run "${service_cmd}" "${cmd}" "${action}"
  268. return $?
  269. elif [ -n "${rcservice_cmd}" ]; then
  270. run "${rcservice_cmd}" "${cmd}" "${action}"
  271. return $?
  272. fi
  273. return 1
  274. }
  275. # -----------------------------------------------------------------------------
  276. # portable pidof
  277. safe_pidof() {
  278. pidof_cmd="$(command -v pidof 2> /dev/null)"
  279. if [ -n "${pidof_cmd}" ]; then
  280. ${pidof_cmd} "${@}"
  281. return $?
  282. else
  283. ps -acxo pid,comm |
  284. sed "s/^ *//g" |
  285. grep netdata |
  286. cut -d ' ' -f 1
  287. return $?
  288. fi
  289. }
  290. # -----------------------------------------------------------------------------
  291. find_processors() {
  292. # Most UNIX systems have `nproc` as part of their userland (including Linux and BSD)
  293. if command -v nproc > /dev/null; then
  294. nproc && return
  295. fi
  296. # macOS has no nproc but it may have gnproc installed from Homebrew or from Macports.
  297. if command -v gnproc > /dev/null; then
  298. gnproc && return
  299. fi
  300. if [ -f "/proc/cpuinfo" ]; then
  301. # linux
  302. cpus=$(grep -c ^processor /proc/cpuinfo)
  303. else
  304. # freebsd
  305. cpus=$(sysctl hw.ncpu 2> /dev/null | grep ^hw.ncpu | cut -d ' ' -f 2)
  306. fi
  307. if [ -z "${cpus}" ] || [ $((cpus)) -lt 1 ]; then
  308. echo 1
  309. else
  310. echo "${cpus}"
  311. fi
  312. }
  313. # -----------------------------------------------------------------------------
  314. exit_reason() {
  315. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  316. EXIT_REASON="${1}"
  317. EXIT_CODE="${2}"
  318. if [ -n "${NETDATA_PROPAGATE_WARNINGS}" ]; then
  319. if [ -n "${NETDATA_SCRIPT_STATUS_PATH}" ]; then
  320. {
  321. echo "EXIT_REASON=\"${EXIT_REASON}\""
  322. echo "EXIT_CODE=\"${EXIT_CODE}\""
  323. echo "NETDATA_WARNINGS=\"${NETDATA_WARNINGS}${SAVED_WARNINGS}\""
  324. } >> "${NETDATA_SCRIPT_STATUS_PATH}"
  325. else
  326. export EXIT_REASON
  327. export EXIT_CODE
  328. export NETDATA_WARNINGS="${NETDATA_WARNINGS}${SAVED_WARNINGS}"
  329. fi
  330. fi
  331. fi
  332. }
  333. fatal() {
  334. printf >&2 "%s ABORTED %s %s \n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD}" "${TPUT_RESET}" "${1}"
  335. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  336. SAVED_WARNINGS="${SAVED_WARNINGS}\n - ${1}"
  337. fi
  338. exit_reason "${1}" "${2}"
  339. exit 1
  340. }
  341. warning() {
  342. printf >&2 "%s WARNING %s %s\n\n" "${TPUT_BGYELLOW}${TPUT_BLACK}${TPUT_BOLD}" "${TPUT_RESET}" "${1}"
  343. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  344. SAVED_WARNINGS="${SAVED_WARNINGS}\n - ${1}"
  345. fi
  346. }
  347. run_ok() {
  348. printf >&2 "%s OK %s %s\n\n" "${TPUT_BGGREEN}${TPUT_WHITE}${TPUT_BOLD}" "${TPUT_RESET}" "${1:-''}"
  349. }
  350. run_failed() {
  351. printf >&2 "%s FAILED %s %s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD}" "${TPUT_RESET}" "${1:-''}"
  352. if [ -n "${NETDATA_SAVE_WARNINGS}" ] && [ -n "${1:-''}" ]; then
  353. SAVED_WARNINGS="${SAVED_WARNINGS}\n - ${1}"
  354. fi
  355. }
  356. ESCAPED_PRINT_METHOD=
  357. if printf "%s " test > /dev/null 2>&1; then
  358. ESCAPED_PRINT_METHOD="printfq"
  359. fi
  360. escaped_print() {
  361. if [ "${ESCAPED_PRINT_METHOD}" = "printfq" ]; then
  362. printf "%s " "${@}"
  363. else
  364. printf "%s" "${*}"
  365. fi
  366. return 0
  367. }
  368. run_logfile="/dev/null"
  369. run() {
  370. local_user="${USER--}"
  371. local_dir="${PWD}"
  372. if [ "${UID}" = "0" ]; then
  373. info="[root ${local_dir}]# "
  374. info_console="[${TPUT_DIM}${local_dir}${TPUT_RESET}]# "
  375. else
  376. info="[${local_user} ${local_dir}]$ "
  377. info_console="[${TPUT_DIM}${local_dir}${TPUT_RESET}]$ "
  378. fi
  379. {
  380. printf "%s" "${info}"
  381. escaped_print "${@}"
  382. printf "%s" " ... "
  383. } >> "${run_logfile}"
  384. printf >&2 "%s" "${info_console}${TPUT_BOLD}${TPUT_YELLOW}"
  385. escaped_print >&2 "${@}"
  386. printf >&2 "%s\n" "${TPUT_RESET}"
  387. "${@}"
  388. ret=$?
  389. if [ ${ret} -ne 0 ]; then
  390. run_failed
  391. printf >> "${run_logfile}" "FAILED with exit code %s\n" "${ret}"
  392. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  393. SAVED_WARNINGS="${SAVED_WARNINGS}\n - Command '${*}' failed with exit code ${ret}."
  394. fi
  395. else
  396. run_ok
  397. printf >> "${run_logfile}" "OK\n"
  398. fi
  399. return ${ret}
  400. }
  401. iscontainer() {
  402. # man systemd-detect-virt
  403. cmd=$(command -v systemd-detect-virt 2> /dev/null)
  404. if [ -n "${cmd}" ] && [ -x "${cmd}" ]; then
  405. "${cmd}" --container > /dev/null 2>&1 && return 0
  406. fi
  407. # /proc/1/sched exposes the host's pid of our init !
  408. # http://stackoverflow.com/a/37016302
  409. pid=$(head -n 1 /proc/1/sched 2> /dev/null | {
  410. # shellcheck disable=SC2034
  411. IFS='(),#:' read -r name pid th threads
  412. echo "$pid"
  413. })
  414. if [ -n "${pid}" ]; then
  415. pid=$((pid + 0))
  416. [ ${pid} -gt 1 ] && return 0
  417. fi
  418. # lxc sets environment variable 'container'
  419. # shellcheck disable=SC2154
  420. [ -n "${container}" ] && return 0
  421. # docker creates /.dockerenv
  422. # http://stackoverflow.com/a/25518345
  423. [ -f "/.dockerenv" ] && return 0
  424. # ubuntu and debian supply /bin/running-in-container
  425. # https://www.apt-browse.org/browse/ubuntu/trusty/main/i386/upstart/1.12.1-0ubuntu4/file/bin/running-in-container
  426. if [ -x "/bin/running-in-container" ]; then
  427. "/bin/running-in-container" > /dev/null 2>&1 && return 0
  428. fi
  429. return 1
  430. }
  431. get_os_key() {
  432. if [ -f /etc/os-release ]; then
  433. # shellcheck disable=SC1091
  434. . /etc/os-release || return 1
  435. echo "${ID}-${VERSION_ID}"
  436. elif [ -f /etc/redhat-release ]; then
  437. cat /etc/redhat-release
  438. else
  439. echo "unknown"
  440. fi
  441. }
  442. get_group(){
  443. if command -v getent > /dev/null 2>&1; then
  444. getent group "${1:-""}"
  445. else
  446. grep "^${1}:" /etc/group
  447. fi
  448. }
  449. issystemd() {
  450. pids=''
  451. p=''
  452. myns=''
  453. ns=''
  454. systemctl=''
  455. # if the directory /lib/systemd/system OR /usr/lib/systemd/system (SLES 12.x) does not exit, it is not systemd
  456. if [ ! -d /lib/systemd/system ] && [ ! -d /usr/lib/systemd/system ]; then
  457. return 1
  458. fi
  459. # if there is no systemctl command, it is not systemd
  460. systemctl=$(command -v systemctl 2> /dev/null)
  461. if [ -z "${systemctl}" ] || [ ! -x "${systemctl}" ]; then
  462. return 1
  463. fi
  464. # if pid 1 is systemd, it is systemd
  465. [ "$(basename "$(readlink /proc/1/exe)" 2> /dev/null)" = "systemd" ] && return 0
  466. # if systemd is not running, it is not systemd
  467. pids=$(safe_pidof systemd 2> /dev/null)
  468. [ -z "${pids}" ] && return 1
  469. # check if the running systemd processes are not in our namespace
  470. myns="$(readlink /proc/self/ns/pid 2> /dev/null)"
  471. for p in ${pids}; do
  472. ns="$(readlink "/proc/${p}/ns/pid" 2> /dev/null)"
  473. # if pid of systemd is in our namespace, it is systemd
  474. [ -n "${myns}" ] && [ "${myns}" = "${ns}" ] && return 0
  475. done
  476. # else, it is not systemd
  477. return 1
  478. }
  479. get_systemd_service_dir() {
  480. if [ -w "/lib/systemd/system" ]; then
  481. echo "/lib/systemd/system"
  482. elif [ -w "/usr/lib/systemd/system" ]; then
  483. echo "/usr/lib/systemd/system"
  484. elif [ -w "/etc/systemd/system" ]; then
  485. echo "/etc/systemd/system"
  486. fi
  487. }
  488. run_install_service_script() {
  489. if [ -z "${tmpdir}" ]; then
  490. tmpdir="${TMPDIR:-/tmp}"
  491. fi
  492. # shellcheck disable=SC2154
  493. save_path="${tmpdir}/netdata-service-cmds"
  494. # shellcheck disable=SC2068
  495. "${NETDATA_PREFIX}/usr/libexec/netdata/install-service.sh" --save-cmds "${save_path}" ${@}
  496. case $? in
  497. 0)
  498. if [ -r "${save_path}" ]; then
  499. # shellcheck disable=SC1090
  500. . "${save_path}"
  501. fi
  502. if [ -z "${NETDATA_INSTALLER_START_CMD}" ]; then
  503. if [ -n "${NETDATA_START_CMD}" ]; then
  504. NETDATA_INSTALLER_START_CMD="${NETDATA_START_CMD}"
  505. else
  506. NETDATA_INSTALLER_START_CMD="netdata"
  507. fi
  508. fi
  509. ;;
  510. 1)
  511. if [ -z "${NETDATA_SERVICE_WARNED_1}" ]; then
  512. warning "Intenral error encountered while attempting to install or manage Netdata as a system service. This is probably a bug."
  513. NETDATA_SERVICE_WARNED_1=1
  514. fi
  515. ;;
  516. 2)
  517. if [ -z "${NETDATA_SERVICE_WARNED_2}" ]; then
  518. warning "Failed to detect system service manager type. Cannot cleanly install or manage Netdata as a system service. If you are running this script in a container, this is expected and can safely be ignored."
  519. NETDATA_SERVICE_WARNED_2=1
  520. fi
  521. ;;
  522. 3)
  523. if [ -z "${NETDATA_SERVICE_WARNED_3}" ]; then
  524. warning "Detected an unsupported system service manager. Manual setup will be required to manage Netdata as a system service."
  525. NETDATA_SERVICE_WARNED_3=1
  526. fi
  527. ;;
  528. 4)
  529. if [ -z "${NETDATA_SERVICE_WARNED_4}" ]; then
  530. warning "Detected a supported system service manager, but failed to install Netdata as a system service. Usually this is a result of incorrect permissions. Manually running ${NETDATA_PREFIX}/usr/libexec/netdata/install-service.sh may provide more information about the exact issue."
  531. NETDATA_SERVICE_WARNED_4=1
  532. fi
  533. ;;
  534. 5)
  535. if [ -z "${NETDATA_SERVICE_WARNED_5}" ]; then
  536. warning "We do not support managing Netdata as a system service on this platform. Manual setup will be required."
  537. NETDATA_SERVICE_WARNED_5=1
  538. fi
  539. ;;
  540. esac
  541. }
  542. install_netdata_service() {
  543. if [ "${UID}" -eq 0 ]; then
  544. if [ -x "${NETDATA_PREFIX}/usr/libexec/netdata/install-service.sh" ]; then
  545. run_install_service_script && return 0
  546. else
  547. warning "Could not find service install script, not installing Netdata as a system service."
  548. fi
  549. fi
  550. return 1
  551. }
  552. # -----------------------------------------------------------------------------
  553. # stop netdata
  554. pidisnetdata() {
  555. if [ -d /proc/self ]; then
  556. if [ -z "$1" ] || [ ! -f "/proc/$1/stat" ]; then
  557. return 1
  558. fi
  559. [ "$(cut -d '(' -f 2 "/proc/$1/stat" | cut -d ')' -f 1)" = "netdata" ] && return 0
  560. return 1
  561. fi
  562. return 0
  563. }
  564. stop_netdata_on_pid() {
  565. pid="${1}"
  566. ret=0
  567. count=0
  568. pidisnetdata "${pid}" || return 0
  569. printf >&2 "Stopping netdata on pid %s ..." "${pid}"
  570. while [ -n "${pid}" ] && [ ${ret} -eq 0 ]; do
  571. if [ ${count} -gt 24 ]; then
  572. warning "Cannot stop netdata agent with PID ${pid}."
  573. return 1
  574. fi
  575. count=$((count + 1))
  576. pidisnetdata "${pid}" || ret=1
  577. if [ ${ret} -eq 1 ]; then
  578. break
  579. fi
  580. if [ ${count} -lt 12 ]; then
  581. run kill "${pid}" 2> /dev/null
  582. ret=$?
  583. else
  584. run kill -9 "${pid}" 2> /dev/null
  585. ret=$?
  586. fi
  587. test ${ret} -eq 0 && printf >&2 "." && sleep 5
  588. done
  589. echo >&2
  590. if [ ${ret} -eq 0 ]; then
  591. warning "Failed to stop netdata agent process with PID ${pid}."
  592. return 1
  593. fi
  594. echo >&2 "netdata on pid ${pid} stopped."
  595. return 0
  596. }
  597. netdata_pids() {
  598. myns="$(readlink /proc/self/ns/pid 2> /dev/null)"
  599. for p in \
  600. $(cat /var/run/netdata.pid 2> /dev/null) \
  601. $(cat /var/run/netdata/netdata.pid 2> /dev/null) \
  602. $(safe_pidof netdata 2> /dev/null); do
  603. ns="$(readlink "/proc/${p}/ns/pid" 2> /dev/null)"
  604. if [ -z "${myns}" ] || [ -z "${ns}" ] || [ "${myns}" = "${ns}" ]; then
  605. pidisnetdata "${p}" && echo "${p}"
  606. fi
  607. done
  608. }
  609. stop_all_netdata() {
  610. stop_success=0
  611. if [ -x "${NETDATA_PREFIX}/usr/libexec/netdata/install-service.sh" ]; then
  612. run_install_service_script --cmds-only
  613. fi
  614. if [ "${UID}" -eq 0 ]; then
  615. uname="$(uname 2>/dev/null)"
  616. # Any of these may fail, but we need to not bail if they do.
  617. if [ -n "${NETDATA_STOP_CMD}" ]; then
  618. if ${NETDATA_STOP_CMD}; then
  619. stop_success=1
  620. sleep 5
  621. fi
  622. elif issystemd; then
  623. if systemctl stop netdata; then
  624. stop_success=1
  625. sleep 5
  626. fi
  627. elif [ "${uname}" = "Darwin" ]; then
  628. if launchctl stop netdata; then
  629. stop_success=1
  630. sleep 5
  631. fi
  632. elif [ "${uname}" = "FreeBSD" ]; then
  633. if /etc/rc.d/netdata stop; then
  634. stop_success=1
  635. sleep 5
  636. fi
  637. else
  638. if service netdata stop; then
  639. stop_success=1
  640. sleep 5
  641. fi
  642. fi
  643. fi
  644. if [ "$stop_success" = "0" ]; then
  645. if [ -n "$(netdata_pids)" ] && [ -n "$(command -v netdatacli)" ]; then
  646. netdatacli shutdown-agent
  647. sleep 20
  648. fi
  649. for p in $(netdata_pids); do
  650. # shellcheck disable=SC2086
  651. stop_netdata_on_pid ${p}
  652. done
  653. fi
  654. }
  655. # -----------------------------------------------------------------------------
  656. # restart netdata
  657. restart_netdata() {
  658. netdata="${1}"
  659. shift
  660. started=0
  661. progress "Restarting netdata instance"
  662. if [ -x "${NETDATA_PREFIX}/usr/libexec/netdata/install-service.sh" ]; then
  663. run_install_service_script --cmds-only
  664. fi
  665. if [ -z "${NETDATA_INSTALLER_START_CMD}" ]; then
  666. if [ -n "${NETDATA_START_CMD}" ]; then
  667. NETDATA_INSTALLER_START_CMD="${NETDATA_START_CMD}"
  668. else
  669. NETDATA_INSTALLER_START_CMD="${netdata}"
  670. fi
  671. fi
  672. if [ "${UID}" -eq 0 ]; then
  673. echo >&2
  674. echo >&2 "Stopping all netdata threads"
  675. run stop_all_netdata
  676. echo >&2 "Starting netdata using command '${NETDATA_INSTALLER_START_CMD}'"
  677. # shellcheck disable=SC2086
  678. run ${NETDATA_INSTALLER_START_CMD} && started=1
  679. if [ ${started} -eq 1 ] && sleep 5 && [ -z "$(netdata_pids)" ]; then
  680. echo >&2 "Ooops! it seems netdata is not started."
  681. started=0
  682. fi
  683. if [ ${started} -eq 0 ]; then
  684. echo >&2 "Attempting another netdata start using command '${NETDATA_INSTALLER_START_CMD}'"
  685. # shellcheck disable=SC2086
  686. run ${NETDATA_INSTALLER_START_CMD} && started=1
  687. fi
  688. if [ ${started} -eq 1 ] && sleep 5 && [ -z "$(netdata_pids)" ]; then
  689. echo >&2 "Hm... it seems netdata is still not started."
  690. started=0
  691. fi
  692. fi
  693. if [ ${started} -eq 0 ]; then
  694. # still not started... another forced attempt, just run the binary
  695. warning "Netdata service still not started, attempting another forced restart by running '${netdata} ${*}'"
  696. run stop_all_netdata
  697. run "${netdata}" "${@}"
  698. return $?
  699. fi
  700. return 0
  701. }
  702. # -----------------------------------------------------------------------------
  703. # install netdata logrotate
  704. install_netdata_logrotate() {
  705. src="${NETDATA_PREFIX}/usr/lib/netdata/system/logrotate/netdata"
  706. if [ "${UID}" -eq 0 ]; then
  707. if [ -d /etc/logrotate.d ]; then
  708. if [ ! -f /etc/logrotate.d/netdata ]; then
  709. run cp "${src}" /etc/logrotate.d/netdata
  710. fi
  711. if [ -f /etc/logrotate.d/netdata ]; then
  712. run chmod 644 /etc/logrotate.d/netdata
  713. fi
  714. return 0
  715. fi
  716. fi
  717. return 1
  718. }
  719. # -----------------------------------------------------------------------------
  720. # create netdata.conf
  721. create_netdata_conf() {
  722. path="${1}"
  723. url="${2}"
  724. if [ -s "${path}" ]; then
  725. return 0
  726. fi
  727. if [ -n "$url" ]; then
  728. echo >&2 "Downloading default configuration from netdata..."
  729. sleep 5
  730. # remove a possibly obsolete configuration file
  731. [ -f "${path}.new" ] && rm "${path}.new"
  732. # disable a proxy to get data from the local netdata
  733. export http_proxy=
  734. export https_proxy=
  735. check_for_curl
  736. if [ -n "${curl}" ]; then
  737. run "${curl}" -sSL --connect-timeout 10 --retry 3 "${url}" > "${path}.new"
  738. elif command -v wget 1> /dev/null 2>&1; then
  739. run wget -T 15 -O - "${url}" > "${path}.new"
  740. fi
  741. if [ -s "${path}.new" ]; then
  742. run mv "${path}.new" "${path}"
  743. run_ok "New configuration saved for you to edit at ${path}"
  744. else
  745. [ -f "${path}.new" ] && rm "${path}.new"
  746. run_failed "Cannot download configuration from netdata daemon using url '${url}'"
  747. url=''
  748. fi
  749. fi
  750. if [ -z "$url" ]; then
  751. cat << EOF > "${path}"
  752. # netdata can generate its own config which is available at 'http://<IP>:19999/netdata.conf'
  753. # You can download it using:
  754. # curl -o ${path} http://localhost:19999/netdata.conf
  755. # or
  756. # wget -O ${path} http://localhost:19999/netdata.conf
  757. EOF
  758. fi
  759. }
  760. portable_add_user() {
  761. username="${1}"
  762. homedir="${2}"
  763. [ -z "${homedir}" ] && homedir="/tmp"
  764. # Check if user exists
  765. if command -v getent > /dev/null 2>&1; then
  766. if getent passwd "${username}" > /dev/null 2>&1; then
  767. echo >&2 "User '${username}' already exists."
  768. return 0
  769. fi
  770. else
  771. if cut -d ':' -f 1 < /etc/passwd | grep "^${username}$" 1> /dev/null 2>&1; then
  772. echo >&2 "User '${username}' already exists."
  773. return 0
  774. fi
  775. fi
  776. echo >&2 "Adding ${username} user account with home ${homedir} ..."
  777. nologin="$(command -v nologin || echo '/bin/false')"
  778. if command -v useradd 1> /dev/null 2>&1; then
  779. run useradd -r -g "${username}" -c "${username}" -s "${nologin}" --no-create-home -d "${homedir}" "${username}" && return 0
  780. elif command -v pw 1> /dev/null 2>&1; then
  781. run pw useradd "${username}" -d "${homedir}" -g "${username}" -s "${nologin}" && return 0
  782. elif command -v adduser 1> /dev/null 2>&1; then
  783. run adduser -h "${homedir}" -s "${nologin}" -D -G "${username}" "${username}" && return 0
  784. elif command -v sysadminctl 1> /dev/null 2>&1; then
  785. run sysadminctl -addUser "${username}" && return 0
  786. fi
  787. warning "Failed to add ${username} user account!"
  788. return 1
  789. }
  790. portable_add_group() {
  791. groupname="${1}"
  792. # Check if group exist
  793. if get_group "${groupname}" > /dev/null 2>&1; then
  794. echo >&2 "Group '${groupname}' already exists."
  795. return 0
  796. fi
  797. echo >&2 "Adding ${groupname} user group ..."
  798. # Linux
  799. if command -v groupadd 1> /dev/null 2>&1; then
  800. run groupadd -r "${groupname}" && return 0
  801. elif command -v pw 1> /dev/null 2>&1; then
  802. run pw groupadd "${groupname}" && return 0
  803. elif command -v addgroup 1> /dev/null 2>&1; then
  804. run addgroup "${groupname}" && return 0
  805. elif command -v dseditgroup 1> /dev/null 2>&1; then
  806. dseditgroup -o create "${groupname}" && return 0
  807. fi
  808. warning >&2 "Failed to add ${groupname} user group !"
  809. return 1
  810. }
  811. portable_add_user_to_group() {
  812. groupname="${1}"
  813. username="${2}"
  814. # Check if group exist
  815. if ! get_group "${groupname}" > /dev/null 2>&1; then
  816. echo >&2 "Group '${groupname}' does not exist."
  817. # Don’t treat this as a failure, if the group does not exist we should not be trying to add the user to it.
  818. return 0
  819. fi
  820. # Check if user is in group
  821. if get_group "${groupname}" | cut -d ':' -f 4 | grep -wq "${username}"; then
  822. # username is already there
  823. echo >&2 "User '${username}' is already in group '${groupname}'."
  824. return 0
  825. else
  826. # username is not in group
  827. echo >&2 "Adding ${username} user to the ${groupname} group ..."
  828. # Linux
  829. if command -v usermod 1> /dev/null 2>&1; then
  830. run usermod -a -G "${groupname}" "${username}" && return 0
  831. elif command -v pw 1> /dev/null 2>&1; then
  832. run pw groupmod "${groupname}" -m "${username}" && return 0
  833. elif command -v addgroup 1> /dev/null 2>&1; then
  834. run addgroup "${username}" "${groupname}" && return 0
  835. elif command -v dseditgroup 1> /dev/null 2>&1; then
  836. dseditgroup -u "${username}" "${groupname}" && return 0
  837. fi
  838. warning >&2 "Failed to add user ${username} to group ${groupname}!"
  839. return 1
  840. fi
  841. }
  842. safe_sha256sum() {
  843. # Within the context of the installer, we only use -c option that is common between the two commands
  844. # We will have to reconsider if we start non-common options
  845. if command -v sha256sum > /dev/null 2>&1; then
  846. sha256sum "$@"
  847. elif command -v shasum > /dev/null 2>&1; then
  848. shasum -a 256 "$@"
  849. else
  850. fatal "I could not find a suitable checksum binary to use" "L0001"
  851. fi
  852. }
  853. _get_scheduler_type() {
  854. if _get_intervaldir > /dev/null ; then
  855. echo 'interval'
  856. elif issystemd ; then
  857. echo 'systemd'
  858. elif [ -d /etc/cron.d ] ; then
  859. echo 'crontab'
  860. else
  861. echo 'none'
  862. fi
  863. }
  864. _get_intervaldir() {
  865. if [ -d /etc/cron.daily ]; then
  866. echo /etc/cron.daily
  867. elif [ -d /etc/periodic/daily ]; then
  868. echo /etc/periodic/daily
  869. else
  870. return 1
  871. fi
  872. return 0
  873. }
  874. install_netdata_updater() {
  875. if [ "${INSTALLER_DIR}" ] && [ -f "${INSTALLER_DIR}/packaging/installer/netdata-updater.sh" ]; then
  876. cat "${INSTALLER_DIR}/packaging/installer/netdata-updater.sh" > "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh" || return 1
  877. fi
  878. if [ "${NETDATA_SOURCE_DIR}" ] && [ -f "${NETDATA_SOURCE_DIR}/packaging/installer/netdata-updater.sh" ]; then
  879. cat "${NETDATA_SOURCE_DIR}/packaging/installer/netdata-updater.sh" > "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh" || return 1
  880. fi
  881. # these files are installed by cmake
  882. libsysdir="${NETDATA_PREFIX}/usr/lib/netdata/system/systemd/"
  883. if [ -d "${libsysdir}" ] && issystemd && [ -n "$(get_systemd_service_dir)" ]; then
  884. cat "${libsysdir}/netdata-updater.timer" > "$(get_systemd_service_dir)/netdata-updater.timer"
  885. cat "${libsysdir}/netdata-updater.service" > "$(get_systemd_service_dir)/netdata-updater.service"
  886. fi
  887. sed -i -e "s|THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT|${NETDATA_USER_CONFIG_DIR}/.environment|" "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh" || return 1
  888. chmod 0755 "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh"
  889. echo >&2 "Update script is located at ${TPUT_GREEN}${TPUT_BOLD}${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh${TPUT_RESET}"
  890. echo >&2
  891. return 0
  892. }
  893. set_netdata_updater_channel() {
  894. sed -i -e "s/^RELEASE_CHANNEL=.*/RELEASE_CHANNEL=\"${RELEASE_CHANNEL}\"/" "${NETDATA_USER_CONFIG_DIR}/.environment"
  895. }