netdata-updater.sh 28 KB

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