netdata-updater.sh 30 KB

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