netdata-updater.sh 30 KB

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