netdata-updater.sh 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  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}" -fsSL --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. [ -z "${PREBUILT_ARCH:-}" ] && PREBUILT_ARCH="$(uname -m)"
  464. filename="netdata-${PREBUILT_ARCH}-latest.gz.run"
  465. else
  466. filename="netdata-x86_64-latest.gz.run"
  467. fi
  468. fi
  469. if [ "$1" = "stable" ]; then
  470. latest="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout)"
  471. export NETDATA_TARBALL_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/${filename}"
  472. export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/sha256sums.txt"
  473. else
  474. tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout)"
  475. export NETDATA_TARBALL_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/${filename}"
  476. export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/sha256sums.txt"
  477. fi
  478. }
  479. update_build() {
  480. [ -z "${logfile}" ] && info "Running on a terminal - (this script also supports running headless from crontab)"
  481. RUN_INSTALLER=0
  482. ndtmpdir=$(create_tmp_directory)
  483. cd "$ndtmpdir" || fatal "Failed to change current working directory to ${ndtmpdir}" U0016
  484. install_build_dependencies
  485. if update_available; then
  486. download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" >&3 2>&3
  487. download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz"
  488. if [ -n "${NETDATA_TARBALL_CHECKSUM}" ] &&
  489. grep "${NETDATA_TARBALL_CHECKSUM}" sha256sum.txt >&3 2>&3 &&
  490. [ "$NETDATA_FORCE_UPDATE" != "1" ]; then
  491. info "Newest version is already installed"
  492. else
  493. if ! grep netdata-latest.tar.gz sha256sum.txt | safe_sha256sum -c - >&3 2>&3; then
  494. 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
  495. fi
  496. NEW_CHECKSUM="$(safe_sha256sum netdata-latest.tar.gz 2> /dev/null | cut -d' ' -f1)"
  497. tar -xf netdata-latest.tar.gz >&3 2>&3
  498. rm netdata-latest.tar.gz >&3 2>&3
  499. if [ -z "$path_version" ]; then
  500. latest_tag="$(get_latest_version)"
  501. path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")"
  502. fi
  503. cd "$(find . -maxdepth 1 -type d -name "netdata-${path_version}*" | head -n 1)" || fatal "Failed to switch to build directory" U0017
  504. RUN_INSTALLER=1
  505. fi
  506. fi
  507. # We got the sources, run the update now
  508. if [ ${RUN_INSTALLER} -eq 1 ]; then
  509. # signal netdata to start saving its database
  510. # this is handy if your database is big
  511. possible_pids=$(pidof netdata)
  512. do_not_start=
  513. if [ -n "${possible_pids}" ]; then
  514. # shellcheck disable=SC2086
  515. kill -USR1 ${possible_pids}
  516. else
  517. # netdata is currently not running, so do not start it after updating
  518. do_not_start="--dont-start-it"
  519. fi
  520. env="env TMPDIR=${TMPDIR}"
  521. if [ -n "${NETDATA_SELECTED_DASHBOARD}" ]; then
  522. env="${env} NETDATA_SELECTED_DASHBOARD=${NETDATA_SELECTED_DASHBOARD}"
  523. fi
  524. if [ ! -x ./netdata-installer.sh ]; then
  525. if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -x "$(find . -mindepth 1 -maxdepth 1 -type d)/netdata-installer.sh" ]; then
  526. cd "$(find . -mindepth 1 -maxdepth 1 -type d)" || fatal "Failed to switch to build directory" U0018
  527. fi
  528. fi
  529. if [ -e "${NETDATA_PREFIX}/etc/netdata/.install-type" ] ; then
  530. install_type="$(cat "${NETDATA_PREFIX}"/etc/netdata/.install-type)"
  531. else
  532. install_type="INSTALL_TYPE='legacy-build'"
  533. fi
  534. if [ "${INSTALL_TYPE}" = "custom" ] && [ -f "${NETDATA_PREFIX}" ]; then
  535. install_type="INSTALL_TYPE='legacy-build'"
  536. fi
  537. info "Re-installing netdata..."
  538. export NETDATA_SAVE_WARNINGS=1
  539. export NETDATA_PROPAGATE_WARNINGS=1
  540. export NETDATA_WARNINGS="${NETDATA_WARNINGS}"
  541. export NETDATA_SCRIPT_STATUS_PATH="${NETDATA_SCRIPT_STATUS_PATH}"
  542. # shellcheck disable=SC2086
  543. if ! ${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start} >&3 2>&3; then
  544. if [ -r "${NETDATA_SCRIPT_STATUS_PATH}" ]; then
  545. # shellcheck disable=SC1090
  546. . "${NETDATA_SCRIPT_STATUS_PATH}"
  547. rm -f "${NETDATA_SCRIPT_STATUS_PATH}"
  548. fi
  549. if [ -n "${EXIT_REASON}" ]; then
  550. fatal "Failed to rebuild existing netdata install: ${EXIT_REASON}" "U${EXIT_CODE}"
  551. else
  552. fatal "Failed to rebuild existing netdata reinstall." UI0000
  553. fi
  554. fi
  555. # We no longer store checksum info here. but leave this so that we clean up all environment files upon next update.
  556. sed -i '/NETDATA_TARBALL/d' "${ENVIRONMENT_FILE}"
  557. info "Updating tarball checksum info"
  558. echo "${NEW_CHECKSUM}" > "${NETDATA_LIB_DIR}/netdata.tarball.checksum"
  559. echo "${install_type}" > "${NETDATA_PREFIX}/etc/netdata/.install-type"
  560. fi
  561. rm -rf "${ndtmpdir}" >&3 2>&3
  562. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  563. return 0
  564. }
  565. update_static() {
  566. ndtmpdir="$(create_tmp_directory)"
  567. PREVDIR="$(pwd)"
  568. info "Entering ${ndtmpdir}"
  569. cd "${ndtmpdir}" || fatal "Failed to change current working directory to ${ndtmpdir}" U0019
  570. if update_available; then
  571. sysarch="${PREBUILT_ARCH}"
  572. [ -z "$sysarch" ] && sysarch="$(uname -m)"
  573. download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt"
  574. download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-${sysarch}-latest.gz.run"
  575. if ! grep "netdata-${sysarch}-latest.gz.run" "${ndtmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
  576. 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
  577. fi
  578. if [ -e /opt/netdata/etc/netdata/.install-type ] ; then
  579. install_type="$(cat /opt/netdata/etc/netdata/.install-type)"
  580. else
  581. install_type="INSTALL_TYPE='legacy-static'"
  582. fi
  583. # Do not pass any options other than the accept, for now
  584. # shellcheck disable=SC2086
  585. if sh "${ndtmpdir}/netdata-${sysarch}-latest.gz.run" --accept -- ${REINSTALL_OPTIONS} >&3 2>&3; then
  586. rm -r "${ndtmpdir}"
  587. else
  588. info "NOTE: did not remove: ${ndtmpdir}"
  589. fi
  590. echo "${install_type}" > /opt/netdata/etc/netdata/.install-type
  591. fi
  592. if [ -e "${PREVDIR}" ]; then
  593. info "Switching back to ${PREVDIR}"
  594. cd "${PREVDIR}"
  595. fi
  596. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  597. exit 0
  598. }
  599. update_binpkg() {
  600. os_release_file=
  601. if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then
  602. os_release_file="/etc/os-release"
  603. elif [ -s "/usr/lib/os-release" ] && [ -r "/usr/lib/os-release" ]; then
  604. os_release_file="/usr/lib/os-release"
  605. else
  606. fatal "Cannot find an os-release file ..." U000B
  607. fi
  608. # shellcheck disable=SC1090
  609. . "${os_release_file}"
  610. DISTRO="${ID}"
  611. supported_compat_names="debian ubuntu centos fedora opensuse ol amzn"
  612. if str_in_list "${DISTRO}" "${supported_compat_names}"; then
  613. DISTRO_COMPAT_NAME="${DISTRO}"
  614. else
  615. case "${DISTRO}" in
  616. opensuse-leap|opensuse-tumbleweed)
  617. DISTRO_COMPAT_NAME="opensuse"
  618. ;;
  619. cloudlinux|almalinux|centos-stream|rocky|rhel)
  620. DISTRO_COMPAT_NAME="centos"
  621. ;;
  622. *)
  623. DISTRO_COMPAT_NAME="unknown"
  624. ;;
  625. esac
  626. fi
  627. interactive_opts=""
  628. env=""
  629. case "${DISTRO_COMPAT_NAME}" in
  630. debian|ubuntu)
  631. if [ "${INTERACTIVE}" = "0" ]; then
  632. upgrade_subcmd="-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold --only-upgrade install"
  633. interactive_opts="-y"
  634. env="DEBIAN_FRONTEND=noninteractive"
  635. else
  636. upgrade_subcmd="--only-upgrade install"
  637. fi
  638. pm_cmd="apt-get"
  639. repo_subcmd="update"
  640. install_subcmd="install"
  641. mark_auto_cmd="apt-mark auto"
  642. pkg_install_opts="${interactive_opts}"
  643. repo_update_opts="${interactive_opts}"
  644. pkg_installed_check="dpkg-query -s"
  645. INSTALL_TYPE="binpkg-deb"
  646. ;;
  647. centos|fedora|ol|amzn)
  648. if [ "${INTERACTIVE}" = "0" ]; then
  649. interactive_opts="-y"
  650. fi
  651. if command -v dnf > /dev/null; then
  652. pm_cmd="dnf"
  653. repo_subcmd="makecache"
  654. mark_auto_cmd="dnf mark remove"
  655. else
  656. pm_cmd="yum"
  657. mark_auto_cmd="yumdb set reason dep"
  658. fi
  659. upgrade_subcmd="upgrade"
  660. install_subcmd="install"
  661. pkg_install_opts="${interactive_opts}"
  662. repo_update_opts="${interactive_opts}"
  663. pkg_installed_check="rpm -q"
  664. INSTALL_TYPE="binpkg-rpm"
  665. ;;
  666. opensuse)
  667. if [ "${INTERACTIVE}" = "0" ]; then
  668. upgrade_subcmd="--non-interactive update"
  669. else
  670. upgrade_subcmd="update"
  671. fi
  672. pm_cmd="zypper"
  673. repo_subcmd="--gpg-auto-import-keys refresh"
  674. install_subcmd="install"
  675. mark_auto_cmd=""
  676. pkg_install_opts=""
  677. repo_update_opts=""
  678. pkg_installed_check="rpm -q"
  679. INSTALL_TYPE="binpkg-rpm"
  680. ;;
  681. *)
  682. warning "We do not provide native packages for ${DISTRO}."
  683. return 2
  684. ;;
  685. esac
  686. if [ -n "${repo_subcmd}" ]; then
  687. # shellcheck disable=SC2086
  688. env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000C
  689. fi
  690. for repopkg in netdata-repo netdata-repo-edge; do
  691. if ${pkg_installed_check} ${repopkg} > /dev/null 2>&1; then
  692. # shellcheck disable=SC2086
  693. env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} ${repopkg} >&3 2>&3 || fatal "Failed to update Netdata repository config." U000D
  694. # shellcheck disable=SC2086
  695. if [ -n "${repo_subcmd}" ]; then
  696. env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000E
  697. fi
  698. fi
  699. done
  700. # shellcheck disable=SC2086
  701. env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F
  702. if ${pkg_installed_check} systemd > /dev/null 2>&1; then
  703. if [ "${NETDATA_NO_SYSTEMD_JOURNAL}" -eq 0 ]; then
  704. if ! ${pkg_installed_check} netdata-plugin-systemd-journal > /dev/null 2>&1; then
  705. env ${env} ${pm_cmd} ${install_subcmd} ${pkg_install_opts} netdata-plugin-systemd-journal >&3 2>&3
  706. if [ -n "${mark_auto_cmd}" ]; then
  707. # shellcheck disable=SC2086
  708. env ${env} ${mark_auto_cmd} netdata-plugin-systemd-journal >&3 2>&3
  709. fi
  710. fi
  711. fi
  712. fi
  713. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  714. return 0
  715. }
  716. # Simple function to encapsulate original updater behavior.
  717. update_legacy() {
  718. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  719. case "${IS_NETDATA_STATIC_BINARY}" in
  720. yes) update_static && exit 0 ;;
  721. *) update_build && exit 0 ;;
  722. esac
  723. }
  724. logfile=
  725. ndtmpdir=
  726. trap cleanup EXIT
  727. if [ -t 2 ] || [ "${GITHUB_ACTIONS}" ]; then
  728. # we are running on a terminal or under CI
  729. # open fd 3 and send it to stderr
  730. exec 3>&2
  731. else
  732. # we are headless
  733. # create a temporary file for the log
  734. logfile="$(mktemp -t netdata-updater.log.XXXXXX)"
  735. # open fd 3 and send it to logfile
  736. exec 3> "${logfile}"
  737. fi
  738. : "${ENVIRONMENT_FILE:=THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT}"
  739. if [ "${ENVIRONMENT_FILE}" = "THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT" ]; then
  740. if [ -r "${script_dir}/../../../etc/netdata/.environment" ] || [ -r "${script_dir}/../../../etc/netdata/.install-type" ]; then
  741. ENVIRONMENT_FILE="${script_dir}/../../../etc/netdata/.environment"
  742. elif [ -r "/etc/netdata/.environment" ] || [ -r "/etc/netdata/.install-type" ]; then
  743. ENVIRONMENT_FILE="/etc/netdata/.environment"
  744. elif [ -r "/opt/netdata/etc/netdata/.environment" ] || [ -r "/opt/netdata/etc/netdata/.install-type" ]; then
  745. ENVIRONMENT_FILE="/opt/netdata/etc/netdata/.environment"
  746. else
  747. 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)"
  748. 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)"
  749. if [ -r "${envpath}" ]; then
  750. ENVIRONMENT_FILE="${envpath}"
  751. elif [ -r "${itpath}" ]; then
  752. ENVIRONMENT_FILE="$(dirname "${itpath}")/.environment"
  753. else
  754. fatal "Cannot find environment file or install type file, unable to update." U0010
  755. fi
  756. fi
  757. fi
  758. if [ -r "${ENVIRONMENT_FILE}" ] ; then
  759. # shellcheck source=/dev/null
  760. . "${ENVIRONMENT_FILE}" || fatal "Failed to source ${ENVIRONMENT_FILE}" U0014
  761. fi
  762. if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then
  763. # shellcheck source=/dev/null
  764. . "$(dirname "${ENVIRONMENT_FILE}")/.install-type" || fatal "Failed to source $(dirname "${ENVIRONMENT_FILE}")/.install-type" U0015
  765. fi
  766. if [ -r "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf" ]; then
  767. # shellcheck source=/dev/null
  768. . "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
  769. fi
  770. while [ -n "${1}" ]; do
  771. case "${1}" in
  772. --not-running-from-cron) NETDATA_NOT_RUNNING_FROM_CRON=1 ;;
  773. --no-updater-self-update) NETDATA_NO_UPDATER_SELF_UPDATE=1 ;;
  774. --force-update) NETDATA_FORCE_UPDATE=1 ;;
  775. --non-interactive) INTERACTIVE=0 ;;
  776. --interactive) INTERACTIVE=1 ;;
  777. --tmpdir-path)
  778. NETDATA_TMPDIR_PATH="${2}"
  779. shift 1
  780. ;;
  781. --enable-auto-updates)
  782. enable_netdata_updater "${2}"
  783. exit $?
  784. ;;
  785. --disable-auto-updates)
  786. disable_netdata_updater
  787. exit $?
  788. ;;
  789. *) fatal "Unrecognized option ${1}" U001A ;;
  790. esac
  791. shift 1
  792. done
  793. # Random sleep to alleviate stampede effect of Agents upgrading
  794. # and disconnecting/reconnecting at the same time (or near to).
  795. # But only we're not a controlling terminal (tty)
  796. # Randomly sleep between 1s and 60m
  797. if [ ! -t 1 ] && \
  798. [ -z "${GITHUB_ACTIONS}" ] && \
  799. [ -z "${NETDATA_NOT_RUNNING_FROM_CRON}" ] && \
  800. is_integer "${NETDATA_UPDATER_JITTER}" && \
  801. [ "${NETDATA_UPDATER_JITTER}" -gt 1 ]; then
  802. rnd="$(awk "
  803. BEGIN { srand()
  804. printf(\"%d\\n\", ${NETDATA_UPDATER_JITTER} * rand())
  805. }")"
  806. sleep $(((rnd % NETDATA_UPDATER_JITTER) + 1))
  807. fi
  808. # We dont expect to find lib dir variable on older installations, so load this path if none found
  809. export NETDATA_LIB_DIR="${NETDATA_LIB_DIR:-${NETDATA_PREFIX}/var/lib/netdata}"
  810. # Source the tarball checksum, if not already available from environment (for existing installations with the old logic)
  811. [ -z "${NETDATA_TARBALL_CHECKSUM}" ] && [ -f "${NETDATA_LIB_DIR}/netdata.tarball.checksum" ] && NETDATA_TARBALL_CHECKSUM="$(cat "${NETDATA_LIB_DIR}/netdata.tarball.checksum")"
  812. if echo "$INSTALL_TYPE" | grep -qv ^binpkg && [ "${INSTALL_UID}" != "$(id -u)" ]; then
  813. 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
  814. fi
  815. self_update
  816. # shellcheck disable=SC2153
  817. case "${INSTALL_TYPE}" in
  818. *-build)
  819. validate_environment_file
  820. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  821. update_build && exit 0
  822. ;;
  823. *-static*)
  824. validate_environment_file
  825. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  826. update_static && exit 0
  827. ;;
  828. *binpkg*) update_binpkg && exit 0 ;;
  829. "") # Fallback case for no `.install-type` file. This just works like the old install type detection.
  830. validate_environment_file
  831. update_legacy
  832. ;;
  833. custom)
  834. # At this point, we _should_ have a valid `.environment` file, but it's best to just check.
  835. # If we do, then behave like the legacy updater.
  836. if validate_environment_file && [ -n "${IS_NETDATA_STATIC_BINARY}" ]; then
  837. update_legacy
  838. else
  839. fatal "This script does not support updating custom installations without valid environment files." U0012
  840. fi
  841. ;;
  842. oci) fatal "This script does not support updating Netdata inside our official Docker containers, please instead update the container itself." U0013 ;;
  843. *) fatal "Unrecognized installation type (${INSTALL_TYPE}), unable to update." U0014 ;;
  844. esac