netdata-updater.sh 30 KB

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