netdata-updater.sh 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. #!/bin/sh
  2. # Netdata updater utility
  3. #
  4. # Variables needed by script:
  5. # - PATH
  6. # - CFLAGS
  7. # - LDFLAGS
  8. # - MAKEOPTS
  9. # - IS_NETDATA_STATIC_BINARY
  10. # - NETDATA_CONFIGURE_OPTIONS
  11. # - REINSTALL_OPTIONS
  12. # - NETDATA_TARBALL_URL
  13. # - NETDATA_TARBALL_CHECKSUM_URL
  14. # - NETDATA_TARBALL_CHECKSUM
  15. # - NETDATA_PREFIX
  16. # - NETDATA_LIB_DIR
  17. #
  18. # Optional environment options:
  19. #
  20. # - TMPDIR (set to a usable temporary directory)
  21. # - NETDATA_NIGHTLIES_BASEURL (set the base url for downloading the dist tarball)
  22. #
  23. # Copyright: 2018-2023 Netdata Inc.
  24. # SPDX-License-Identifier: GPL-3.0-or-later
  25. #
  26. # Author: Paweł Krupa <paulfantom@gmail.com>
  27. # Author: Pavlos Emm. Katsoulakis <paul@netdata.cloud>
  28. # Author: Austin S. Hemmelgarn <austin@netdata.cloud>
  29. # Next unused error code: U001B
  30. set -e
  31. PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/install-required-packages.sh"
  32. NETDATA_STABLE_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata/releases}"
  33. NETDATA_NIGHTLY_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata-nightlies/releases}"
  34. # Following variables are intended to be overridden by the updater config file.
  35. NETDATA_UPDATER_JITTER=3600
  36. NETDATA_NO_SYSTEMD_JOURNAL=0
  37. script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)"
  38. if [ -x "${script_dir}/netdata-updater" ]; then
  39. script_source="${script_dir}/netdata-updater"
  40. else
  41. script_source="${script_dir}/netdata-updater.sh"
  42. fi
  43. PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
  44. if [ ! -t 1 ]; then
  45. INTERACTIVE=0
  46. else
  47. INTERACTIVE=1
  48. fi
  49. if [ -n "${script_source}" ]; then
  50. script_name="$(basename "${script_source}")"
  51. else
  52. script_name="netdata-updater.sh"
  53. fi
  54. info() {
  55. echo >&3 "$(date) : INFO: ${script_name}: " "${1}"
  56. }
  57. warning() {
  58. echo >&3 "$(date) : WARNING: ${script_name}: " "${@}"
  59. }
  60. error() {
  61. echo >&3 "$(date) : ERROR: ${script_name}: " "${1}"
  62. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  63. NETDATA_WARNINGS="${NETDATA_WARNINGS}\n - ${1}"
  64. fi
  65. }
  66. fatal() {
  67. echo >&3 "$(date) : FATAL: ${script_name}: FAILED TO UPDATE NETDATA: " "${1}"
  68. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  69. NETDATA_WARNINGS="${NETDATA_WARNINGS}\n - ${1}"
  70. fi
  71. exit_reason "${1}" "${2}"
  72. exit 1
  73. }
  74. exit_reason() {
  75. if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
  76. EXIT_REASON="${1}"
  77. EXIT_CODE="${2}"
  78. if [ -n "${NETDATA_PROPAGATE_WARNINGS}" ]; then
  79. if [ -n "${NETDATA_SCRIPT_STATUS_PATH}" ]; then
  80. {
  81. echo "EXIT_REASON=\"${EXIT_REASON}\""
  82. echo "EXIT_CODE=\"${EXIT_CODE}\""
  83. echo "NETDATA_WARNINGS=\"${NETDATA_WARNINGS}\""
  84. } >> "${NETDATA_SCRIPT_STATUS_PATH}"
  85. else
  86. export EXIT_REASON
  87. export EXIT_CODE
  88. export NETDATA_WARNINGS
  89. fi
  90. fi
  91. fi
  92. }
  93. is_integer () {
  94. case "${1#[+-]}" in
  95. *[!0123456789]*) return 1 ;;
  96. '') return 1 ;;
  97. *) return 0 ;;
  98. esac
  99. }
  100. issystemd() {
  101. # if the directory /lib/systemd/system OR /usr/lib/systemd/system (SLES 12.x) does not exit, it is not systemd
  102. if [ ! -d /lib/systemd/system ] && [ ! -d /usr/lib/systemd/system ]; then
  103. return 1
  104. fi
  105. # if there is no systemctl command, it is not systemd
  106. systemctl=$(command -v systemctl 2> /dev/null)
  107. if [ -z "${systemctl}" ] || [ ! -x "${systemctl}" ]; then
  108. return 1
  109. fi
  110. # if pid 1 is systemd, it is systemd
  111. [ "$(basename "$(readlink /proc/1/exe)" 2> /dev/null)" = "systemd" ] && return 0
  112. # if systemd is not running, it is not systemd
  113. pids=$(safe_pidof systemd 2> /dev/null)
  114. [ -z "${pids}" ] && return 1
  115. # check if the running systemd processes are not in our namespace
  116. myns="$(readlink /proc/self/ns/pid 2> /dev/null)"
  117. for p in ${pids}; do
  118. ns="$(readlink "/proc/${p}/ns/pid" 2> /dev/null)"
  119. # if pid of systemd is in our namespace, it is systemd
  120. [ -n "${myns}" ] && [ "${myns}" = "${ns}" ] && return 0
  121. done
  122. # else, it is not systemd
  123. return 1
  124. }
  125. _get_intervaldir() {
  126. if [ -d /etc/cron.daily ]; then
  127. echo /etc/cron.daily
  128. elif [ -d /etc/periodic/daily ]; then
  129. echo /etc/periodic/daily
  130. else
  131. return 1
  132. fi
  133. return 0
  134. }
  135. _get_scheduler_type() {
  136. if _get_intervaldir > /dev/null ; then
  137. echo 'interval'
  138. elif issystemd ; then
  139. echo 'systemd'
  140. elif [ -d /etc/cron.d ] ; then
  141. echo 'crontab'
  142. else
  143. echo 'none'
  144. fi
  145. }
  146. install_build_dependencies() {
  147. bash="$(command -v bash 2> /dev/null)"
  148. if [ -z "${bash}" ] || [ ! -x "${bash}" ]; then
  149. error "Unable to find a usable version of \`bash\` (required for local build)."
  150. return 1
  151. fi
  152. info "Fetching dependency handling script..."
  153. download "${PACKAGES_SCRIPT}" "./install-required-packages.sh" || true
  154. if [ ! -s "./install-required-packages.sh" ]; then
  155. error "Downloaded dependency installation script is empty."
  156. else
  157. info "Running dependency handling script..."
  158. opts="--dont-wait --non-interactive"
  159. # shellcheck disable=SC2086
  160. if ! "${bash}" "./install-required-packages.sh" ${opts} netdata >&3 2>&3; then
  161. error "Installing build dependencies failed. The update should still work, but you might be missing some features."
  162. fi
  163. fi
  164. }
  165. enable_netdata_updater() {
  166. updater_type="$(echo "${1}" | tr '[:upper:]' '[:lower:]')"
  167. case "${updater_type}" in
  168. systemd|interval|crontab)
  169. updater_type="${1}"
  170. ;;
  171. "")
  172. updater_type="$(_get_scheduler_type)"
  173. ;;
  174. *)
  175. fatal "Unrecognized updater type ${updater_type} requested. Supported types are 'systemd', 'interval', and 'crontab'." U0001
  176. ;;
  177. esac
  178. case "${updater_type}" in
  179. "systemd")
  180. if issystemd; then
  181. systemctl enable netdata-updater.timer
  182. info "Auto-updating has been ENABLED using a systemd timer unit.\n"
  183. info "If the update process fails, the failure will be logged to the systemd journal just like a regular service failure."
  184. info "Successful updates should produce empty logs."
  185. else
  186. error "Systemd-based auto-update scheduling requested, but this does not appear to be a systemd system. Auto-updates have NOT been enabled."
  187. return 1
  188. fi
  189. ;;
  190. "interval")
  191. if _get_intervaldir > /dev/null; then
  192. ln -sf "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh" "$(_get_intervaldir)/netdata-updater"
  193. info "Auto-updating has been ENABLED through cron, updater script linked to $(_get_intervaldir)/netdata-updater\n"
  194. info "If the update process fails and you have email notifications set up correctly for cron on this system, you should receive an email notification of the failure."
  195. info "Successful updates will not send an email."
  196. else
  197. error "Interval-based auto-update scheduling requested, but I could not find an interval scheduling directory. Auto-updates have NOT been enabled."
  198. return 1
  199. fi
  200. ;;
  201. "crontab")
  202. if [ -d "/etc/cron.d" ]; then
  203. [ -f "/etc/cron.d/netdata-updater" ] && rm -f "/etc/cron.d/netdata-updater"
  204. install -p -m 0644 -o 0 -g 0 "${NETDATA_PREFIX}/usr/lib/system/cron/netdata-updater-daily" "/etc/cron.d/netdata-updater-daily"
  205. info "Auto-updating has been ENABLED through cron, using a crontab at /etc/cron.d/netdata-updater\n"
  206. info "If the update process fails and you have email notifications set up correctly for cron on this system, you should receive an email notification of the failure."
  207. info "Successful updates will not send an email."
  208. else
  209. error "Crontab-based auto-update scheduling requested, but there is no '/etc/cron.d'. Auto-updates have NOT been enabled."
  210. return 1
  211. fi
  212. ;;
  213. *)
  214. error "Unable to determine what type of auto-update scheduling to use. Auto-updates have NOT been enabled."
  215. return 1
  216. esac
  217. return 0
  218. }
  219. disable_netdata_updater() {
  220. if issystemd && ( systemctl list-units --full -all | grep -Fq "netdata-updater.timer" ) ; then
  221. systemctl disable netdata-updater.timer
  222. fi
  223. if [ -d /etc/cron.daily ]; then
  224. rm -f /etc/cron.daily/netdata-updater.sh
  225. rm -f /etc/cron.daily/netdata-updater
  226. fi
  227. if [ -d /etc/periodic/daily ]; then
  228. rm -f /etc/periodic/daily/netdata-updater.sh
  229. rm -f /etc/periodic/daily/netdata-updater
  230. fi
  231. if [ -d /etc/cron.d ]; then
  232. rm -f /etc/cron.d/netdata-updater
  233. rm -f /etc/cron.d/netdata-updater-daily
  234. fi
  235. info "Auto-updates have been DISABLED."
  236. return 0
  237. }
  238. str_in_list() {
  239. printf "%s\n" "${2}" | tr ' ' "\n" | grep -qE "^${1}\$"
  240. return $?
  241. }
  242. safe_sha256sum() {
  243. # Within the context of the installer, we only use -c option that is common between the two commands
  244. # We will have to reconsider if we start non-common options
  245. if command -v shasum > /dev/null 2>&1; then
  246. shasum -a 256 "$@"
  247. elif command -v sha256sum > /dev/null 2>&1; then
  248. sha256sum "$@"
  249. else
  250. fatal "I could not find a suitable checksum binary to use" U0002
  251. fi
  252. }
  253. cleanup() {
  254. if [ -n "${logfile}" ]; then
  255. cat >&2 "${logfile}"
  256. rm "${logfile}"
  257. fi
  258. if [ -n "$ndtmpdir" ] && [ -d "$ndtmpdir" ]; then
  259. rm -rf "$ndtmpdir"
  260. fi
  261. }
  262. _cannot_use_tmpdir() {
  263. testfile="$(TMPDIR="${1}" mktemp -q -t netdata-test.XXXXXXXXXX)"
  264. ret=0
  265. if [ -z "${testfile}" ] ; then
  266. return "${ret}"
  267. fi
  268. if printf '#!/bin/sh\necho SUCCESS\n' > "${testfile}" ; then
  269. if chmod +x "${testfile}" ; then
  270. if [ "$("${testfile}" 2>/dev/null)" = "SUCCESS" ] ; then
  271. ret=1
  272. fi
  273. fi
  274. fi
  275. rm -f "${testfile}"
  276. return "${ret}"
  277. }
  278. create_tmp_directory() {
  279. if [ -n "${NETDATA_TMPDIR_PATH}" ]; then
  280. echo "${NETDATA_TMPDIR_PATH}"
  281. else
  282. if [ -z "${NETDATA_TMPDIR}" ] || _cannot_use_tmpdir "${NETDATA_TMPDIR}" ; then
  283. if [ -z "${TMPDIR}" ] || _cannot_use_tmpdir "${TMPDIR}" ; then
  284. if _cannot_use_tmpdir /tmp ; then
  285. if _cannot_use_tmpdir "${PWD}" ; then
  286. fatal "Unable to find a usable temporary directory. Please set \$TMPDIR to a path that is both writable and allows execution of files and try again." U0003
  287. else
  288. TMPDIR="${PWD}"
  289. fi
  290. else
  291. TMPDIR="/tmp"
  292. fi
  293. fi
  294. else
  295. TMPDIR="${NETDATA_TMPDIR}"
  296. fi
  297. mktemp -d -t netdata-updater-XXXXXXXXXX
  298. fi
  299. }
  300. check_for_curl() {
  301. if [ -z "${curl}" ]; then
  302. curl="$(PATH="${PATH}:/opt/netdata/bin" command -v curl 2>/dev/null && true)"
  303. fi
  304. }
  305. _safe_download() {
  306. url="${1}"
  307. dest="${2}"
  308. check_for_curl
  309. if [ -n "${curl}" ]; then
  310. "${curl}" -sSL --connect-timeout 10 --retry 3 "${url}" > "${dest}"
  311. return $?
  312. elif command -v wget > /dev/null 2>&1; then
  313. wget -T 15 -O - "${url}" > "${dest}"
  314. return $?
  315. else
  316. return 255
  317. fi
  318. }
  319. download() {
  320. url="${1}"
  321. dest="${2}"
  322. _safe_download "${url}" "${dest}"
  323. ret=$?
  324. if [ ${ret} -eq 0 ]; then
  325. return 0
  326. elif [ ${ret} -eq 255 ]; then
  327. fatal "I need curl or wget to proceed, but neither is available on this system." U0004
  328. else
  329. fatal "Cannot download ${url}" U0005
  330. fi
  331. }
  332. get_netdata_latest_tag() {
  333. url="${1}/latest"
  334. dest="${2}"
  335. check_for_curl
  336. if [ -n "${curl}" ]; then
  337. tag=$("${curl}" "${url}" -s -L -I -o /dev/null -w '%{url_effective}' | grep -m 1 -o '[^/]*$')
  338. elif command -v wget >/dev/null 2>&1; then
  339. tag=$(wget -S -O /dev/null "${url}" 2>&1 | grep -m 1 Location | grep -o '[^/]*$')
  340. else
  341. fatal "I need curl or wget to proceed, but neither of them are available on this system." U0006
  342. fi
  343. echo "${tag}" >"${dest}"
  344. }
  345. newer_commit_date() {
  346. info "Checking if a newer version of the updater script is available."
  347. commit_check_url="https://api.github.com/repos/netdata/netdata/commits?path=packaging%2Finstaller%2Fnetdata-updater.sh&page=1&per_page=1"
  348. python_version_check="from __future__ import print_function;import sys,json;data = json.load(sys.stdin);print(data[0]['commit']['committer']['date'] if isinstance(data, list) else '')"
  349. if command -v jq > /dev/null 2>&1; then
  350. commit_date="$(_safe_download "${commit_check_url}" /dev/stdout | jq '.[0].commit.committer.date' 2>/dev/null | tr -d '"')"
  351. elif command -v python > /dev/null 2>&1;then
  352. commit_date="$(_safe_download "${commit_check_url}" /dev/stdout | python -c "${python_version_check}")"
  353. elif command -v python3 > /dev/null 2>&1;then
  354. commit_date="$(_safe_download "${commit_check_url}" /dev/stdout | python3 -c "${python_version_check}")"
  355. fi
  356. if [ -z "${commit_date}" ] ; then
  357. return 0
  358. elif [ "$(uname)" = "Linux" ]; then
  359. commit_date="$(date -d "${commit_date}" +%s)"
  360. else # assume BSD-style `date` if we are not on Linux
  361. commit_date="$(/bin/date -j -f "%Y-%m-%dT%H:%M:%SZ" "${commit_date}" +%s 2>/dev/null)"
  362. if [ -z "${commit_date}" ]; then
  363. return 0
  364. fi
  365. fi
  366. if [ -e "${script_source}" ]; then
  367. script_date="$(date -r "${script_source}" +%s)"
  368. else
  369. script_date="$(date +%s)"
  370. fi
  371. [ "${commit_date}" -ge "${script_date}" ]
  372. }
  373. self_update() {
  374. if [ -z "${NETDATA_NO_UPDATER_SELF_UPDATE}" ] && newer_commit_date; then
  375. info "Downloading newest version of updater script."
  376. ndtmpdir=$(create_tmp_directory)
  377. cd "$ndtmpdir" || exit 1
  378. if _safe_download "https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/netdata-updater.sh" ./netdata-updater.sh; then
  379. chmod +x ./netdata-updater.sh || exit 1
  380. export ENVIRONMENT_FILE="${ENVIRONMENT_FILE}"
  381. force_update=""
  382. [ "$NETDATA_FORCE_UPDATE" = "1" ] && force_update="--force-update"
  383. exec ./netdata-updater.sh --not-running-from-cron --no-updater-self-update "$force_update" --tmpdir-path "$(pwd)"
  384. else
  385. error "Failed to download newest version of updater script, continuing with current version."
  386. fi
  387. fi
  388. }
  389. parse_version() {
  390. r="${1}"
  391. if [ "${r}" = "latest" ]; then
  392. # If we get ‘latest’ as a version, return the largest possible
  393. # version value.
  394. printf "99999999999999"
  395. return 0
  396. elif echo "${r}" | grep -q '^v.*'; then
  397. # shellcheck disable=SC2001
  398. # XXX: Need a regex group substitution here.
  399. r="$(echo "${r}" | sed -e 's/^v\(.*\)/\1/')"
  400. fi
  401. tmpfile="$(mktemp)"
  402. echo "${r}" | tr '-' ' ' > "${tmpfile}"
  403. read -r v b _ < "${tmpfile}"
  404. if echo "${b}" | grep -vEq "^[0-9]+$"; then
  405. b="0"
  406. fi
  407. echo "${v}" | tr '.' ' ' > "${tmpfile}"
  408. read -r maj min patch _ < "${tmpfile}"
  409. rm -f "${tmpfile}"
  410. printf "%03d%03d%03d%05d" "${maj}" "${min}" "${patch}" "${b}"
  411. }
  412. get_latest_version() {
  413. if [ "${RELEASE_CHANNEL}" = "stable" ]; then
  414. get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout
  415. else
  416. get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout
  417. fi
  418. }
  419. validate_environment_file() {
  420. if [ -n "${NETDATA_PREFIX+SET_BUT_NULL}" ] && [ -n "${REINSTALL_OPTIONS+SET_BUT_NULL}" ]; then
  421. return 0
  422. else
  423. fatal "Environment file located at ${ENVIRONMENT_FILE} is not valid, unable to update." U0007
  424. fi
  425. }
  426. update_available() {
  427. if [ "$NETDATA_FORCE_UPDATE" = "1" ]; then
  428. info "Force update requested"
  429. return 0
  430. fi
  431. basepath="$(dirname "$(dirname "$(dirname "${NETDATA_LIB_DIR}")")")"
  432. searchpath="${basepath}/bin:${basepath}/sbin:${basepath}/usr/bin:${basepath}/usr/sbin:${PATH}"
  433. searchpath="${basepath}/netdata/bin:${basepath}/netdata/sbin:${basepath}/netdata/usr/bin:${basepath}/netdata/usr/sbin:${searchpath}"
  434. ndbinary="$(PATH="${searchpath}" command -v netdata 2>/dev/null)"
  435. if [ -z "${ndbinary}" ]; then
  436. current_version=0
  437. else
  438. current_version="$(parse_version "$(${ndbinary} -v | cut -f 2 -d ' ')")"
  439. fi
  440. latest_tag="$(get_latest_version)"
  441. latest_version="$(parse_version "${latest_tag}")"
  442. path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")"
  443. # If we can't get the current version for some reason assume `0`
  444. current_version="${current_version:-0}"
  445. # If we can't get the latest version for some reason assume `0`
  446. latest_version="${latest_version:-0}"
  447. info "Current Version: ${current_version}"
  448. info "Latest Version: ${latest_version}"
  449. if [ "${latest_version}" -gt 0 ] && [ "${current_version}" -gt 0 ] && [ "${current_version}" -ge "${latest_version}" ]; then
  450. info "Newest version (current=${current_version} >= latest=${latest_version}) is already installed"
  451. return 1
  452. else
  453. info "Update available"
  454. return 0
  455. fi
  456. }
  457. set_tarball_urls() {
  458. filename="netdata-latest.tar.gz"
  459. if [ "$2" = "yes" ]; then
  460. if [ -e /opt/netdata/etc/netdata/.install-type ]; then
  461. # shellcheck disable=SC1091
  462. . /opt/netdata/etc/netdata/.install-type
  463. filename="netdata-${PREBUILT_ARCH}-latest.gz.run"
  464. else
  465. filename="netdata-x86_64-latest.gz.run"
  466. fi
  467. fi
  468. if [ "$1" = "stable" ]; then
  469. latest="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout)"
  470. export NETDATA_TARBALL_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/${filename}"
  471. export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/sha256sums.txt"
  472. else
  473. tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout)"
  474. export NETDATA_TARBALL_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/${filename}"
  475. export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/sha256sums.txt"
  476. fi
  477. }
  478. update_build() {
  479. [ -z "${logfile}" ] && info "Running on a terminal - (this script also supports running headless from crontab)"
  480. RUN_INSTALLER=0
  481. ndtmpdir=$(create_tmp_directory)
  482. cd "$ndtmpdir" || fatal "Failed to change current working directory to ${ndtmpdir}" U0016
  483. install_build_dependencies
  484. if update_available; then
  485. download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" >&3 2>&3
  486. download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz"
  487. if [ -n "${NETDATA_TARBALL_CHECKSUM}" ] &&
  488. grep "${NETDATA_TARBALL_CHECKSUM}" sha256sum.txt >&3 2>&3 &&
  489. [ "$NETDATA_FORCE_UPDATE" != "1" ]; then
  490. info "Newest version is already installed"
  491. else
  492. if ! grep netdata-latest.tar.gz sha256sum.txt | safe_sha256sum -c - >&3 2>&3; then
  493. fatal "Tarball checksum validation failed. Stopping netdata upgrade and leaving tarball in ${ndtmpdir}\nUsually this is a result of an older copy of the tarball or checksum file being cached somewhere upstream and can be resolved by retrying in an hour." U0008
  494. fi
  495. NEW_CHECKSUM="$(safe_sha256sum netdata-latest.tar.gz 2> /dev/null | cut -d' ' -f1)"
  496. tar -xf netdata-latest.tar.gz >&3 2>&3
  497. rm netdata-latest.tar.gz >&3 2>&3
  498. if [ -z "$path_version" ]; then
  499. latest_tag="$(get_latest_version)"
  500. path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")"
  501. fi
  502. cd "$(find . -maxdepth 1 -type d -name "netdata-${path_version}*" | head -n 1)" || fatal "Failed to switch to build directory" U0017
  503. RUN_INSTALLER=1
  504. fi
  505. fi
  506. # We got the sources, run the update now
  507. if [ ${RUN_INSTALLER} -eq 1 ]; then
  508. # signal netdata to start saving its database
  509. # this is handy if your database is big
  510. possible_pids=$(pidof netdata)
  511. do_not_start=
  512. if [ -n "${possible_pids}" ]; then
  513. # shellcheck disable=SC2086
  514. kill -USR1 ${possible_pids}
  515. else
  516. # netdata is currently not running, so do not start it after updating
  517. do_not_start="--dont-start-it"
  518. fi
  519. env="env TMPDIR=${TMPDIR}"
  520. if [ -n "${NETDATA_SELECTED_DASHBOARD}" ]; then
  521. env="${env} NETDATA_SELECTED_DASHBOARD=${NETDATA_SELECTED_DASHBOARD}"
  522. fi
  523. if [ ! -x ./netdata-installer.sh ]; then
  524. if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -x "$(find . -mindepth 1 -maxdepth 1 -type d)/netdata-installer.sh" ]; then
  525. cd "$(find . -mindepth 1 -maxdepth 1 -type d)" || fatal "Failed to switch to build directory" U0018
  526. fi
  527. fi
  528. if [ -e "${NETDATA_PREFIX}/etc/netdata/.install-type" ] ; then
  529. install_type="$(cat "${NETDATA_PREFIX}"/etc/netdata/.install-type)"
  530. else
  531. install_type="INSTALL_TYPE='legacy-build'"
  532. fi
  533. if [ "${INSTALL_TYPE}" = "custom" ] && [ -f "${NETDATA_PREFIX}" ]; then
  534. install_type="INSTALL_TYPE='legacy-build'"
  535. fi
  536. info "Re-installing netdata..."
  537. export NETDATA_SAVE_WARNINGS=1
  538. export NETDATA_PROPAGATE_WARNINGS=1
  539. export NETDATA_WARNINGS="${NETDATA_WARNINGS}"
  540. export NETDATA_SCRIPT_STATUS_PATH="${NETDATA_SCRIPT_STATUS_PATH}"
  541. # shellcheck disable=SC2086
  542. if ! ${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start} >&3 2>&3; then
  543. if [ -r "${NETDATA_SCRIPT_STATUS_PATH}" ]; then
  544. # shellcheck disable=SC1090
  545. . "${NETDATA_SCRIPT_STATUS_PATH}"
  546. rm -f "${NETDATA_SCRIPT_STATUS_PATH}"
  547. fi
  548. if [ -n "${EXIT_REASON}" ]; then
  549. fatal "Failed to rebuild existing netdata install: ${EXIT_REASON}" "U${EXIT_CODE}"
  550. else
  551. fatal "Failed to rebuild existing netdata reinstall." UI0000
  552. fi
  553. fi
  554. # We no longer store checksum info here. but leave this so that we clean up all environment files upon next update.
  555. sed -i '/NETDATA_TARBALL/d' "${ENVIRONMENT_FILE}"
  556. info "Updating tarball checksum info"
  557. echo "${NEW_CHECKSUM}" > "${NETDATA_LIB_DIR}/netdata.tarball.checksum"
  558. echo "${install_type}" > "${NETDATA_PREFIX}/etc/netdata/.install-type"
  559. fi
  560. rm -rf "${ndtmpdir}" >&3 2>&3
  561. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  562. return 0
  563. }
  564. update_static() {
  565. ndtmpdir="$(create_tmp_directory)"
  566. PREVDIR="$(pwd)"
  567. info "Entering ${ndtmpdir}"
  568. cd "${ndtmpdir}" || fatal "Failed to change current working directory to ${ndtmpdir}" U0019
  569. if update_available; then
  570. sysarch="${PREBUILT_ARCH}"
  571. [ -z "$sysarch" ] && sysarch="$(uname -m)"
  572. download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt"
  573. download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-${sysarch}-latest.gz.run"
  574. if ! grep "netdata-${sysarch}-latest.gz.run" "${ndtmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
  575. fatal "Static binary checksum validation failed. Stopping netdata installation and leaving binary in ${ndtmpdir}\nUsually this is a result of an older copy of the file being cached somewhere and can be resolved by simply retrying in an hour." U000A
  576. fi
  577. if [ -e /opt/netdata/etc/netdata/.install-type ] ; then
  578. install_type="$(cat /opt/netdata/etc/netdata/.install-type)"
  579. else
  580. install_type="INSTALL_TYPE='legacy-static'"
  581. fi
  582. # Do not pass any options other than the accept, for now
  583. # shellcheck disable=SC2086
  584. if sh "${ndtmpdir}/netdata-${sysarch}-latest.gz.run" --accept -- ${REINSTALL_OPTIONS} >&3 2>&3; then
  585. rm -r "${ndtmpdir}"
  586. else
  587. info "NOTE: did not remove: ${ndtmpdir}"
  588. fi
  589. echo "${install_type}" > /opt/netdata/etc/netdata/.install-type
  590. fi
  591. if [ -e "${PREVDIR}" ]; then
  592. info "Switching back to ${PREVDIR}"
  593. cd "${PREVDIR}"
  594. fi
  595. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  596. exit 0
  597. }
  598. update_binpkg() {
  599. os_release_file=
  600. if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then
  601. os_release_file="/etc/os-release"
  602. elif [ -s "/usr/lib/os-release" ] && [ -r "/usr/lib/os-release" ]; then
  603. os_release_file="/usr/lib/os-release"
  604. else
  605. fatal "Cannot find an os-release file ..." U000B
  606. fi
  607. # shellcheck disable=SC1090
  608. . "${os_release_file}"
  609. DISTRO="${ID}"
  610. supported_compat_names="debian ubuntu centos fedora opensuse ol amzn"
  611. if str_in_list "${DISTRO}" "${supported_compat_names}"; then
  612. DISTRO_COMPAT_NAME="${DISTRO}"
  613. else
  614. case "${DISTRO}" in
  615. opensuse-leap|opensuse-tumbleweed)
  616. DISTRO_COMPAT_NAME="opensuse"
  617. ;;
  618. cloudlinux|almalinux|centos-stream|rocky|rhel)
  619. DISTRO_COMPAT_NAME="centos"
  620. ;;
  621. *)
  622. DISTRO_COMPAT_NAME="unknown"
  623. ;;
  624. esac
  625. fi
  626. interactive_opts=""
  627. env=""
  628. case "${DISTRO_COMPAT_NAME}" in
  629. debian|ubuntu)
  630. if [ "${INTERACTIVE}" = "0" ]; then
  631. upgrade_subcmd="-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold --only-upgrade install"
  632. interactive_opts="-y"
  633. env="DEBIAN_FRONTEND=noninteractive"
  634. else
  635. upgrade_subcmd="--only-upgrade install"
  636. fi
  637. pm_cmd="apt-get"
  638. repo_subcmd="update"
  639. install_subcmd="install"
  640. mark_auto_cmd="apt-mark auto"
  641. pkg_install_opts="${interactive_opts}"
  642. repo_update_opts="${interactive_opts}"
  643. pkg_installed_check="dpkg-query -s"
  644. INSTALL_TYPE="binpkg-deb"
  645. ;;
  646. centos|fedora|ol|amzn)
  647. if [ "${INTERACTIVE}" = "0" ]; then
  648. interactive_opts="-y"
  649. fi
  650. if command -v dnf > /dev/null; then
  651. pm_cmd="dnf"
  652. repo_subcmd="makecache"
  653. mark_auto_cmd="dnf mark remove"
  654. else
  655. pm_cmd="yum"
  656. mark_auto_cmd="yumdb set reason dep"
  657. fi
  658. upgrade_subcmd="upgrade"
  659. install_subcmd="install"
  660. pkg_install_opts="${interactive_opts}"
  661. repo_update_opts="${interactive_opts}"
  662. pkg_installed_check="rpm -q"
  663. INSTALL_TYPE="binpkg-rpm"
  664. ;;
  665. opensuse)
  666. if [ "${INTERACTIVE}" = "0" ]; then
  667. upgrade_subcmd="--non-interactive update"
  668. else
  669. upgrade_subcmd="update"
  670. fi
  671. pm_cmd="zypper"
  672. repo_subcmd="--gpg-auto-import-keys refresh"
  673. install_subcmd="install"
  674. mark_auto_cmd=""
  675. pkg_install_opts=""
  676. repo_update_opts=""
  677. pkg_installed_check="rpm -q"
  678. INSTALL_TYPE="binpkg-rpm"
  679. ;;
  680. *)
  681. warning "We do not provide native packages for ${DISTRO}."
  682. return 2
  683. ;;
  684. esac
  685. if [ -n "${repo_subcmd}" ]; then
  686. # shellcheck disable=SC2086
  687. env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000C
  688. fi
  689. for repopkg in netdata-repo netdata-repo-edge; do
  690. if ${pkg_installed_check} ${repopkg} > /dev/null 2>&1; then
  691. # shellcheck disable=SC2086
  692. env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} ${repopkg} >&3 2>&3 || fatal "Failed to update Netdata repository config." U000D
  693. # shellcheck disable=SC2086
  694. if [ -n "${repo_subcmd}" ]; then
  695. env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000E
  696. fi
  697. fi
  698. done
  699. # shellcheck disable=SC2086
  700. env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F
  701. if ${pkg_installed_check} systemd > /dev/null 2>&1; then
  702. if [ "${NETDATA_NO_SYSTEMD_JOURNAL}" -eq 0 ]; then
  703. if ! ${pkg_installed_check} netdata-plugin-systemd-journal > /dev/null 2>&1; then
  704. env ${env} ${pm_cmd} ${install_subcmd} ${pkg_install_opts} netdata-plugin-systemd-journal >&3 2>&3
  705. if [ -n "${mark_auto_cmd}" ]; then
  706. # shellcheck disable=SC2086
  707. env ${env} ${mark_auto_cmd} netdata-plugin-systemd-journal >&3 2>&3
  708. fi
  709. fi
  710. fi
  711. fi
  712. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  713. return 0
  714. }
  715. # Simple function to encapsulate original updater behavior.
  716. update_legacy() {
  717. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  718. case "${IS_NETDATA_STATIC_BINARY}" in
  719. yes) update_static && exit 0 ;;
  720. *) update_build && exit 0 ;;
  721. esac
  722. }
  723. logfile=
  724. ndtmpdir=
  725. trap cleanup EXIT
  726. if [ -t 2 ] || [ "${GITHUB_ACTIONS}" ]; then
  727. # we are running on a terminal or under CI
  728. # open fd 3 and send it to stderr
  729. exec 3>&2
  730. else
  731. # we are headless
  732. # create a temporary file for the log
  733. logfile="$(mktemp -t netdata-updater.log.XXXXXX)"
  734. # open fd 3 and send it to logfile
  735. exec 3> "${logfile}"
  736. fi
  737. : "${ENVIRONMENT_FILE:=THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT}"
  738. if [ "${ENVIRONMENT_FILE}" = "THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT" ]; then
  739. if [ -r "${script_dir}/../../../etc/netdata/.environment" ] || [ -r "${script_dir}/../../../etc/netdata/.install-type" ]; then
  740. ENVIRONMENT_FILE="${script_dir}/../../../etc/netdata/.environment"
  741. elif [ -r "/etc/netdata/.environment" ] || [ -r "/etc/netdata/.install-type" ]; then
  742. ENVIRONMENT_FILE="/etc/netdata/.environment"
  743. elif [ -r "/opt/netdata/etc/netdata/.environment" ] || [ -r "/opt/netdata/etc/netdata/.install-type" ]; then
  744. ENVIRONMENT_FILE="/opt/netdata/etc/netdata/.environment"
  745. else
  746. envpath="$(find / -type d \( -path /sys -o -path /proc -o -path /dev \) -prune -false -o -path '*netdata/.environment' -type f 2> /dev/null | head -n 1)"
  747. itpath="$(find / -type d \( -path /sys -o -path /proc -o -path /dev \) -prune -false -o -path '*netdata/.install-type' -type f 2> /dev/null | head -n 1)"
  748. if [ -r "${envpath}" ]; then
  749. ENVIRONMENT_FILE="${envpath}"
  750. elif [ -r "${itpath}" ]; then
  751. ENVIRONMENT_FILE="$(dirname "${itpath}")/.environment"
  752. else
  753. fatal "Cannot find environment file or install type file, unable to update." U0010
  754. fi
  755. fi
  756. fi
  757. if [ -r "${ENVIRONMENT_FILE}" ] ; then
  758. # shellcheck source=/dev/null
  759. . "${ENVIRONMENT_FILE}" || fatal "Failed to source ${ENVIRONMENT_FILE}" U0014
  760. fi
  761. if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then
  762. # shellcheck source=/dev/null
  763. . "$(dirname "${ENVIRONMENT_FILE}")/.install-type" || fatal "Failed to source $(dirname "${ENVIRONMENT_FILE}")/.install-type" U0015
  764. fi
  765. if [ -r "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf" ]; then
  766. # shellcheck source=/dev/null
  767. . "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
  768. fi
  769. while [ -n "${1}" ]; do
  770. case "${1}" in
  771. --not-running-from-cron) NETDATA_NOT_RUNNING_FROM_CRON=1 ;;
  772. --no-updater-self-update) NETDATA_NO_UPDATER_SELF_UPDATE=1 ;;
  773. --force-update) NETDATA_FORCE_UPDATE=1 ;;
  774. --non-interactive) INTERACTIVE=0 ;;
  775. --interactive) INTERACTIVE=1 ;;
  776. --tmpdir-path)
  777. NETDATA_TMPDIR_PATH="${2}"
  778. shift 1
  779. ;;
  780. --enable-auto-updates)
  781. enable_netdata_updater "${2}"
  782. exit $?
  783. ;;
  784. --disable-auto-updates)
  785. disable_netdata_updater
  786. exit $?
  787. ;;
  788. *) fatal "Unrecognized option ${1}" U001A ;;
  789. esac
  790. shift 1
  791. done
  792. # Random sleep to alleviate stampede effect of Agents upgrading
  793. # and disconnecting/reconnecting at the same time (or near to).
  794. # But only we're not a controlling terminal (tty)
  795. # Randomly sleep between 1s and 60m
  796. if [ ! -t 1 ] && \
  797. [ -z "${GITHUB_ACTIONS}" ] && \
  798. [ -z "${NETDATA_NOT_RUNNING_FROM_CRON}" ] && \
  799. is_integer "${NETDATA_UPDATER_JITTER}" && \
  800. [ "${NETDATA_UPDATER_JITTER}" -gt 1 ]; then
  801. rnd="$(awk "
  802. BEGIN { srand()
  803. printf(\"%d\\n\", ${NETDATA_UPDATER_JITTER} * rand())
  804. }")"
  805. sleep $(((rnd % NETDATA_UPDATER_JITTER) + 1))
  806. fi
  807. # We dont expect to find lib dir variable on older installations, so load this path if none found
  808. export NETDATA_LIB_DIR="${NETDATA_LIB_DIR:-${NETDATA_PREFIX}/var/lib/netdata}"
  809. # Source the tarball checksum, if not already available from environment (for existing installations with the old logic)
  810. [ -z "${NETDATA_TARBALL_CHECKSUM}" ] && [ -f "${NETDATA_LIB_DIR}/netdata.tarball.checksum" ] && NETDATA_TARBALL_CHECKSUM="$(cat "${NETDATA_LIB_DIR}/netdata.tarball.checksum")"
  811. if echo "$INSTALL_TYPE" | grep -qv ^binpkg && [ "${INSTALL_UID}" != "$(id -u)" ]; then
  812. fatal "You are running this script as user with uid $(id -u). We recommend to run this script as root (user with uid 0)" U0011
  813. fi
  814. self_update
  815. # shellcheck disable=SC2153
  816. case "${INSTALL_TYPE}" in
  817. *-build)
  818. validate_environment_file
  819. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  820. update_build && exit 0
  821. ;;
  822. *-static*)
  823. validate_environment_file
  824. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  825. update_static && exit 0
  826. ;;
  827. *binpkg*) update_binpkg && exit 0 ;;
  828. "") # Fallback case for no `.install-type` file. This just works like the old install type detection.
  829. validate_environment_file
  830. update_legacy
  831. ;;
  832. custom)
  833. # At this point, we _should_ have a valid `.environment` file, but it's best to just check.
  834. # If we do, then behave like the legacy updater.
  835. if validate_environment_file && [ -n "${IS_NETDATA_STATIC_BINARY}" ]; then
  836. update_legacy
  837. else
  838. fatal "This script does not support updating custom installations without valid environment files." U0012
  839. fi
  840. ;;
  841. oci) fatal "This script does not support updating Netdata inside our official Docker containers, please instead update the container itself." U0013 ;;
  842. *) fatal "Unrecognized installation type (${INSTALL_TYPE}), unable to update." U0014 ;;
  843. esac