netdata-updater.sh 30 KB

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