netdata-updater.sh 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  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: U001A
  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 sha256sum > /dev/null 2>&1; then
  226. sha256sum "$@"
  227. elif command -v shasum > /dev/null 2>&1; then
  228. shasum -a 256 "$@"
  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. exec ./netdata-updater.sh --not-running-from-cron --no-updater-self-update --tmpdir-path "$(pwd)"
  355. else
  356. error "Failed to download newest version of updater script, continuing with current version."
  357. fi
  358. fi
  359. }
  360. parse_version() {
  361. r="${1}"
  362. if echo "${r}" | grep -q '^v.*'; then
  363. # shellcheck disable=SC2001
  364. # XXX: Need a regex group substitution here.
  365. r="$(echo "${r}" | sed -e 's/^v\(.*\)/\1/')"
  366. fi
  367. tmpfile="$(mktemp)"
  368. echo "${r}" | tr '-' ' ' > "${tmpfile}"
  369. read -r v b _ < "${tmpfile}"
  370. if echo "${b}" | grep -vEq "^[0-9]+$"; then
  371. b="0"
  372. fi
  373. echo "${v}" | tr '.' ' ' > "${tmpfile}"
  374. read -r maj min patch _ < "${tmpfile}"
  375. rm -f "${tmpfile}"
  376. printf "%03d%03d%03d%05d" "${maj}" "${min}" "${patch}" "${b}"
  377. }
  378. get_latest_version() {
  379. if [ "${RELEASE_CHANNEL}" = "stable" ]; then
  380. get_netdata_latest_tag /dev/stdout
  381. else
  382. download "$NETDATA_NIGHTLIES_BASEURL/latest-version.txt" /dev/stdout
  383. fi
  384. }
  385. validate_environment_file() {
  386. if [ -n "${NETDATA_PREFIX+SET_BUT_NULL}" ] && [ -n "${REINSTALL_OPTIONS+SET_BUT_NULL}" ]; then
  387. return 0
  388. else
  389. fatal "Environment file located at ${ENVIRONMENT_FILE} is not valid, unable to update." U0007
  390. fi
  391. }
  392. update_available() {
  393. if [ "$NETDATA_FORCE_UPDATE" = "1" ]; then
  394. info "Force update requested"
  395. return 0
  396. fi
  397. basepath="$(dirname "$(dirname "$(dirname "${NETDATA_LIB_DIR}")")")"
  398. searchpath="${basepath}/bin:${basepath}/sbin:${basepath}/usr/bin:${basepath}/usr/sbin:${PATH}"
  399. searchpath="${basepath}/netdata/bin:${basepath}/netdata/sbin:${basepath}/netdata/usr/bin:${basepath}/netdata/usr/sbin:${searchpath}"
  400. ndbinary="$(PATH="${searchpath}" command -v netdata 2>/dev/null)"
  401. if [ -z "${ndbinary}" ]; then
  402. current_version=0
  403. else
  404. current_version="$(parse_version "$(${ndbinary} -v | cut -f 2 -d ' ')")"
  405. fi
  406. latest_tag="$(get_latest_version)"
  407. latest_version="$(parse_version "${latest_tag}")"
  408. path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")"
  409. # If we can't get the current version for some reason assume `0`
  410. current_version="${current_version:-0}"
  411. # If we can't get the latest version for some reason assume `0`
  412. latest_version="${latest_version:-0}"
  413. info "Current Version: ${current_version}"
  414. info "Latest Version: ${latest_version}"
  415. if [ "${latest_version}" -gt 0 ] && [ "${current_version}" -gt 0 ] && [ "${current_version}" -ge "${latest_version}" ]; then
  416. info "Newest version (current=${current_version} >= latest=${latest_version}) is already installed"
  417. return 1
  418. else
  419. info "Update available"
  420. return 0
  421. fi
  422. }
  423. set_tarball_urls() {
  424. filename="netdata-latest.tar.gz"
  425. if [ "$2" = "yes" ]; then
  426. if [ -e /opt/netdata/etc/netdata/.install-type ]; then
  427. # shellcheck disable=SC1091
  428. . /opt/netdata/etc/netdata/.install-type
  429. filename="netdata-${PREBUILT_ARCH}-latest.gz.run"
  430. else
  431. filename="netdata-x86_64-latest.gz.run"
  432. fi
  433. fi
  434. if [ "$1" = "stable" ]; then
  435. latest="$(get_netdata_latest_tag /dev/stdout)"
  436. export NETDATA_TARBALL_URL="https://github.com/netdata/netdata/releases/download/$latest/${filename}"
  437. export NETDATA_TARBALL_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/$latest/sha256sums.txt"
  438. else
  439. export NETDATA_TARBALL_URL="$NETDATA_NIGHTLIES_BASEURL/${filename}"
  440. export NETDATA_TARBALL_CHECKSUM_URL="$NETDATA_NIGHTLIES_BASEURL/sha256sums.txt"
  441. fi
  442. }
  443. update_build() {
  444. [ -z "${logfile}" ] && info "Running on a terminal - (this script also supports running headless from crontab)"
  445. RUN_INSTALLER=0
  446. ndtmpdir=$(create_tmp_directory)
  447. cd "$ndtmpdir" || fatal "Failed to change current working directory to ${ndtmpdir}" U0016
  448. install_build_dependencies
  449. if update_available; then
  450. download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" >&3 2>&3
  451. download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz"
  452. if [ -n "${NETDATA_TARBALL_CHECKSUM}" ] &&
  453. grep "${NETDATA_TARBALL_CHECKSUM}" sha256sum.txt >&3 2>&3 &&
  454. [ "$NETDATA_FORCE_UPDATE" != "1" ]; then
  455. info "Newest version is already installed"
  456. else
  457. if ! grep netdata-latest.tar.gz sha256sum.txt | safe_sha256sum -c - >&3 2>&3; then
  458. 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
  459. fi
  460. NEW_CHECKSUM="$(safe_sha256sum netdata-latest.tar.gz 2> /dev/null | cut -d' ' -f1)"
  461. tar -xf netdata-latest.tar.gz >&3 2>&3
  462. rm netdata-latest.tar.gz >&3 2>&3
  463. cd "$(find . -maxdepth 1 -name "netdata-${path_version}*" | head -n 1)" || fatal "Failed to switch to build directory" U0017
  464. RUN_INSTALLER=1
  465. fi
  466. fi
  467. # We got the sources, run the update now
  468. if [ ${RUN_INSTALLER} -eq 1 ]; then
  469. # signal netdata to start saving its database
  470. # this is handy if your database is big
  471. possible_pids=$(pidof netdata)
  472. do_not_start=
  473. if [ -n "${possible_pids}" ]; then
  474. # shellcheck disable=SC2086
  475. kill -USR1 ${possible_pids}
  476. else
  477. # netdata is currently not running, so do not start it after updating
  478. do_not_start="--dont-start-it"
  479. fi
  480. env="env TMPDIR=${TMPDIR}"
  481. if [ -n "${NETDATA_SELECTED_DASHBOARD}" ]; then
  482. env="${env} NETDATA_SELECTED_DASHBOARD=${NETDATA_SELECTED_DASHBOARD}"
  483. fi
  484. if [ ! -x ./netdata-installer.sh ]; then
  485. if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -x "$(find . -mindepth 1 -maxdepth 1 -type d)/netdata-installer.sh" ]; then
  486. cd "$(find . -mindepth 1 -maxdepth 1 -type d)" || fatal "Failed to switch to build directory" U0018
  487. fi
  488. fi
  489. if [ -e "${NETDATA_PREFIX}/etc/netdata/.install-type" ] ; then
  490. install_type="$(cat "${NETDATA_PREFIX}"/etc/netdata/.install-type)"
  491. else
  492. install_type="INSTALL_TYPE='legacy-build'"
  493. fi
  494. if [ "${INSTALL_TYPE}" = "custom" ] && [ -f "${NETDATA_PREFIX}" ]; then
  495. install_type="INSTALL_TYPE='legacy-build'"
  496. fi
  497. info "Re-installing netdata..."
  498. export NETDATA_SAVE_WARNINGS=1
  499. export NETDATA_PROPAGATE_WARNINGS=1
  500. export NETDATA_WARNINGS="${NETDATA_WARNINGS}"
  501. # shellcheck disable=SC2086
  502. if ! ${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start} >&3 2>&3; then
  503. if [ -n "${EXIT_REASON}" ]; then
  504. fatal "Failed to rebuild existing netdata install: ${EXIT_REASON}" "U${EXIT_CODE}"
  505. else
  506. fatal "Failed to rebuild existing netdata reinstall." UI0000
  507. fi
  508. fi
  509. eval "${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start}" >&3 2>&3 || fatal "FAILED TO COMPILE/INSTALL NETDATA" U0009
  510. # We no longer store checksum info here. but leave this so that we clean up all environment files upon next update.
  511. sed -i '/NETDATA_TARBALL/d' "${ENVIRONMENT_FILE}"
  512. info "Updating tarball checksum info"
  513. echo "${NEW_CHECKSUM}" > "${NETDATA_LIB_DIR}/netdata.tarball.checksum"
  514. echo "${install_type}" > "${NETDATA_PREFIX}/etc/netdata/.install-type"
  515. fi
  516. rm -rf "${ndtmpdir}" >&3 2>&3
  517. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  518. return 0
  519. }
  520. update_static() {
  521. ndtmpdir="$(create_tmp_directory)"
  522. PREVDIR="$(pwd)"
  523. info "Entering ${ndtmpdir}"
  524. cd "${ndtmpdir}" || fatal "Failed to change current working directory to ${ndtmpdir}" U0019
  525. if update_available; then
  526. sysarch="$(uname -m)"
  527. download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt"
  528. download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-${sysarch}-latest.gz.run"
  529. if ! grep "netdata-${sysarch}-latest.gz.run" "${ndtmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
  530. 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
  531. fi
  532. if [ -e /opt/netdata/etc/netdata/.install-type ] ; then
  533. install_type="$(cat /opt/netdata/etc/netdata/.install-type)"
  534. else
  535. install_type="INSTALL_TYPE='legacy-static'"
  536. fi
  537. # Do not pass any options other than the accept, for now
  538. # shellcheck disable=SC2086
  539. if sh "${ndtmpdir}/netdata-${sysarch}-latest.gz.run" --accept -- ${REINSTALL_OPTIONS}; then
  540. rm -r "${ndtmpdir}"
  541. else
  542. info "NOTE: did not remove: ${ndtmpdir}"
  543. fi
  544. echo "${install_type}" > /opt/netdata/etc/netdata/.install-type
  545. fi
  546. if [ -e "${PREVDIR}" ]; then
  547. info "Switching back to ${PREVDIR}"
  548. cd "${PREVDIR}"
  549. fi
  550. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  551. exit 0
  552. }
  553. update_binpkg() {
  554. os_release_file=
  555. if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then
  556. os_release_file="/etc/os-release"
  557. elif [ -s "/usr/lib/os-release" ] && [ -r "/usr/lib/os-release" ]; then
  558. os_release_file="/usr/lib/os-release"
  559. else
  560. fatal "Cannot find an os-release file ..." U000B
  561. fi
  562. # shellcheck disable=SC1090
  563. . "${os_release_file}"
  564. DISTRO="${ID}"
  565. supported_compat_names="debian ubuntu centos fedora opensuse"
  566. if str_in_list "${DISTRO}" "${supported_compat_names}"; then
  567. DISTRO_COMPAT_NAME="${DISTRO}"
  568. else
  569. case "${DISTRO}" in
  570. opensuse-leap)
  571. DISTRO_COMPAT_NAME="opensuse"
  572. ;;
  573. almalinux|rocky|rhel)
  574. DISTRO_COMPAT_NAME="centos"
  575. ;;
  576. *)
  577. DISTRO_COMPAT_NAME="unknown"
  578. ;;
  579. esac
  580. fi
  581. if [ "${INTERACTIVE}" = "0" ]; then
  582. interactive_opts="-y"
  583. env="DEBIAN_FRONTEND=noninteractive"
  584. else
  585. interactive_opts=""
  586. env=""
  587. fi
  588. case "${DISTRO_COMPAT_NAME}" in
  589. debian)
  590. pm_cmd="apt-get"
  591. repo_subcmd="update"
  592. upgrade_cmd="--only-upgrade install"
  593. pkg_install_opts="${interactive_opts}"
  594. repo_update_opts="${interactive_opts}"
  595. pkg_installed_check="dpkg -s"
  596. INSTALL_TYPE="binpkg-deb"
  597. ;;
  598. ubuntu)
  599. pm_cmd="apt-get"
  600. repo_subcmd="update"
  601. upgrade_cmd="--only-upgrade install"
  602. pkg_install_opts="${interactive_opts}"
  603. repo_update_opts="${interactive_opts}"
  604. pkg_installed_check="dpkg -s"
  605. INSTALL_TYPE="binpkg-deb"
  606. ;;
  607. centos)
  608. if command -v dnf > /dev/null; then
  609. pm_cmd="dnf"
  610. repo_subcmd="makecache"
  611. else
  612. pm_cmd="yum"
  613. fi
  614. upgrade_cmd="upgrade"
  615. pkg_install_opts="${interactive_opts}"
  616. repo_update_opts="${interactive_opts}"
  617. pkg_installed_check="rpm -q"
  618. INSTALL_TYPE="binpkg-rpm"
  619. ;;
  620. fedora)
  621. if command -v dnf > /dev/null; then
  622. pm_cmd="dnf"
  623. repo_subcmd="makecache"
  624. else
  625. pm_cmd="yum"
  626. fi
  627. upgrade_cmd="upgrade"
  628. pkg_install_opts="${interactive_opts}"
  629. repo_update_opts="${interactive_opts}"
  630. pkg_installed_check="rpm -q"
  631. INSTALL_TYPE="binpkg-rpm"
  632. ;;
  633. opensuse)
  634. pm_cmd="zypper"
  635. repo_subcmd="--gpg-auto-import-keys refresh"
  636. upgrade_cmd="upgrade"
  637. pkg_install_opts="${interactive_opts} --allow-unsigned-rpm"
  638. repo_update_opts=""
  639. pkg_installed_check="rpm -q"
  640. INSTALL_TYPE="binpkg-rpm"
  641. ;;
  642. *)
  643. warning "We do not provide native packages for ${DISTRO}."
  644. return 2
  645. ;;
  646. esac
  647. if [ -n "${repo_subcmd}" ]; then
  648. # shellcheck disable=SC2086
  649. env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000C
  650. fi
  651. for repopkg in netdata-repo netdata-repo-edge; do
  652. if ${pkg_installed_check} ${repopkg} > /dev/null 2>&1; then
  653. # shellcheck disable=SC2086
  654. env ${env} ${pm_cmd} ${upgrade_cmd} ${pkg_install_opts} ${repopkg} >&3 2>&3 || fatal "Failed to update Netdata repository config." U000D
  655. # shellcheck disable=SC2086
  656. if [ -n "${repo_subcmd}" ]; then
  657. env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000E
  658. fi
  659. fi
  660. done
  661. # shellcheck disable=SC2086
  662. env ${env} ${pm_cmd} ${upgrade_cmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F
  663. [ -n "${logfile}" ] && rm "${logfile}" && logfile=
  664. return 0
  665. }
  666. # Simple function to encapsulate original updater behavior.
  667. update_legacy() {
  668. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  669. if [ "${IS_NETDATA_STATIC_BINARY}" = "yes" ]; then
  670. update_static && exit 0
  671. else
  672. update_build && exit 0
  673. fi
  674. }
  675. logfile=
  676. ndtmpdir=
  677. trap cleanup EXIT
  678. if [ -t 2 ]; then
  679. # we are running on a terminal
  680. # open fd 3 and send it to stderr
  681. exec 3>&2
  682. else
  683. # we are headless
  684. # create a temporary file for the log
  685. logfile="$(mktemp -t netdata-updater.log.XXXXXX)"
  686. # open fd 3 and send it to logfile
  687. exec 3> "${logfile}"
  688. fi
  689. : "${ENVIRONMENT_FILE:=THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT}"
  690. if [ "${ENVIRONMENT_FILE}" = "THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT" ]; then
  691. if [ -r "${script_dir}/../../../etc/netdata/.environment" ] || [ -r "${script_dir}/../../../etc/netdata/.install-type" ]; then
  692. ENVIRONMENT_FILE="${script_dir}/../../../etc/netdata/.environment"
  693. elif [ -r "/etc/netdata/.environment" ] || [ -r "/etc/netdata/.install-type" ]; then
  694. ENVIRONMENT_FILE="/etc/netdata/.environment"
  695. elif [ -r "/opt/netdata/etc/netdata/.environment" ] || [ -r "/opt/netdata/etc/netdata/.install-type" ]; then
  696. ENVIRONMENT_FILE="/opt/netdata/etc/netdata/.environment"
  697. else
  698. 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)"
  699. 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)"
  700. if [ -r "${envpath}" ]; then
  701. ENVIRONMENT_FILE="${envpath}"
  702. elif [ -r "${itpath}" ]; then
  703. ENVIRONMENT_FILE="$(dirname "${itpath}")/.environment"
  704. else
  705. fatal "Cannot find environment file or install type file, unable to update." U0010
  706. fi
  707. fi
  708. fi
  709. if [ -r "${ENVIRONMENT_FILE}" ] ; then
  710. # shellcheck source=/dev/null
  711. . "${ENVIRONMENT_FILE}" || fatal "Failed to source ${ENVIRONMENT_FILE}" U0014
  712. fi
  713. if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then
  714. # shellcheck source=/dev/null
  715. . "$(dirname "${ENVIRONMENT_FILE}")/.install-type" || fatal "Failed to source $(dirname "${ENVIRONMENT_FILE}")/.install-type" U0015
  716. fi
  717. while [ -n "${1}" ]; do
  718. if [ "${1}" = "--not-running-from-cron" ]; then
  719. NETDATA_NOT_RUNNING_FROM_CRON=1
  720. shift 1
  721. elif [ "${1}" = "--no-updater-self-update" ]; then
  722. NETDATA_NO_UPDATER_SELF_UPDATE=1
  723. shift 1
  724. elif [ "${1}" = "--force-update" ]; then
  725. NETDATA_FORCE_UPDATE=1
  726. shift 1
  727. elif [ "${1}" = "--tmpdir-path" ]; then
  728. NETDATA_TMPDIR_PATH="${2}"
  729. shift 2
  730. elif [ "${1}" = "--enable-auto-updates" ]; then
  731. enable_netdata_updater "${2}"
  732. exit $?
  733. elif [ "${1}" = "--disable-auto-updates" ]; then
  734. disable_netdata_updater
  735. exit $?
  736. else
  737. break
  738. fi
  739. done
  740. # Random sleep to alleviate stampede effect of Agents upgrading
  741. # and disconnecting/reconnecting at the same time (or near to).
  742. # But only we're not a controlling terminal (tty)
  743. # Randomly sleep between 1s and 60m
  744. if [ ! -t 1 ] && [ -z "${NETDATA_NOT_RUNNING_FROM_CRON}" ]; then
  745. rnd="$(awk '
  746. BEGIN { srand()
  747. printf("%d\n", 3600 * rand())
  748. }')"
  749. sleep $(((rnd % 3600) + 1))
  750. fi
  751. # We dont expect to find lib dir variable on older installations, so load this path if none found
  752. export NETDATA_LIB_DIR="${NETDATA_LIB_DIR:-${NETDATA_PREFIX}/var/lib/netdata}"
  753. # Source the tarball checksum, if not already available from environment (for existing installations with the old logic)
  754. [ -z "${NETDATA_TARBALL_CHECKSUM}" ] && [ -f "${NETDATA_LIB_DIR}/netdata.tarball.checksum" ] && NETDATA_TARBALL_CHECKSUM="$(cat "${NETDATA_LIB_DIR}/netdata.tarball.checksum")"
  755. # Grab the nightlies baseurl (defaulting to our Google Storage bucket)
  756. export NETDATA_NIGHTLIES_BASEURL="${NETDATA_NIGHTLIES_BASEURL:-https://storage.googleapis.com/netdata-nightlies}"
  757. if echo "$INSTALL_TYPE" | grep -qv ^binpkg && [ "${INSTALL_UID}" != "$(id -u)" ]; then
  758. 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
  759. fi
  760. self_update
  761. # shellcheck disable=SC2153
  762. case "${INSTALL_TYPE}" in
  763. *-build)
  764. validate_environment_file
  765. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  766. update_build && exit 0
  767. ;;
  768. *-static*)
  769. validate_environment_file
  770. set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
  771. update_static && exit 0
  772. ;;
  773. *binpkg*)
  774. update_binpkg && exit 0
  775. ;;
  776. "") # Fallback case for no `.install-type` file. This just works like the old install type detection.
  777. validate_environment_file
  778. update_legacy
  779. ;;
  780. custom)
  781. # At this point, we _should_ have a valid `.environment` file, but it's best to just check.
  782. # If we do, then behave like the legacy updater.
  783. if validate_environment_file && [ -n "${IS_NETDATA_STATIC_BINARY}" ]; then
  784. update_legacy
  785. else
  786. fatal "This script does not support updating custom installations without valid environment files." U0012
  787. fi
  788. ;;
  789. oci)
  790. fatal "This script does not support updating Netdata inside our official Docker containers, please instead update the container itself." U0013
  791. ;;
  792. *)
  793. fatal "Unrecognized installation type (${INSTALL_TYPE}), unable to update." U0014
  794. ;;
  795. esac