summaryrefslogtreecommitdiffstats
path: root/packaging/installer/netdata-updater.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xpackaging/installer/netdata-updater.sh990
1 files changed, 990 insertions, 0 deletions
diff --git a/packaging/installer/netdata-updater.sh b/packaging/installer/netdata-updater.sh
new file mode 100755
index 00000000..80faea0a
--- /dev/null
+++ b/packaging/installer/netdata-updater.sh
@@ -0,0 +1,990 @@
+#!/bin/sh
+
+# Netdata updater utility
+#
+# Variables needed by script:
+# - PATH
+# - CFLAGS
+# - LDFLAGS
+# - MAKEOPTS
+# - IS_NETDATA_STATIC_BINARY
+# - NETDATA_CONFIGURE_OPTIONS
+# - REINSTALL_OPTIONS
+# - NETDATA_TARBALL_URL
+# - NETDATA_TARBALL_CHECKSUM_URL
+# - NETDATA_TARBALL_CHECKSUM
+# - NETDATA_PREFIX
+# - NETDATA_LIB_DIR
+#
+# Optional environment options:
+#
+# - TMPDIR (set to a usable temporary directory)
+# - NETDATA_NIGHTLIES_BASEURL (set the base url for downloading the dist tarball)
+#
+# Copyright: 2018-2023 Netdata Inc.
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# Author: Paweł Krupa <paulfantom@gmail.com>
+# Author: Pavlos Emm. Katsoulakis <paul@netdata.cloud>
+# Author: Austin S. Hemmelgarn <austin@netdata.cloud>
+
+# Next unused error code: U001B
+
+set -e
+
+PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/install-required-packages.sh"
+
+NETDATA_STABLE_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata/releases}"
+NETDATA_NIGHTLY_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata-nightlies/releases}"
+
+# Following variables are intended to be overridden by the updater config file.
+NETDATA_UPDATER_JITTER=3600
+NETDATA_NO_SYSTEMD_JOURNAL=0
+
+script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)"
+
+if [ -x "${script_dir}/netdata-updater" ]; then
+ script_source="${script_dir}/netdata-updater"
+else
+ script_source="${script_dir}/netdata-updater.sh"
+fi
+
+PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
+
+if [ ! -t 1 ]; then
+ INTERACTIVE=0
+else
+ INTERACTIVE=1
+fi
+
+if [ -n "${script_source}" ]; then
+ script_name="$(basename "${script_source}")"
+else
+ script_name="netdata-updater.sh"
+fi
+
+info() {
+ echo >&3 "$(date) : INFO: ${script_name}: " "${1}"
+}
+
+warning() {
+ echo >&3 "$(date) : WARNING: ${script_name}: " "${@}"
+}
+
+error() {
+ echo >&3 "$(date) : ERROR: ${script_name}: " "${1}"
+ if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
+ NETDATA_WARNINGS="${NETDATA_WARNINGS}\n - ${1}"
+ fi
+}
+
+fatal() {
+ echo >&3 "$(date) : FATAL: ${script_name}: FAILED TO UPDATE NETDATA: " "${1}"
+ if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
+ NETDATA_WARNINGS="${NETDATA_WARNINGS}\n - ${1}"
+ fi
+ exit_reason "${1}" "${2}"
+ exit 1
+}
+
+exit_reason() {
+ if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then
+ EXIT_REASON="${1}"
+ EXIT_CODE="${2}"
+ if [ -n "${NETDATA_PROPAGATE_WARNINGS}" ]; then
+ if [ -n "${NETDATA_SCRIPT_STATUS_PATH}" ]; then
+ {
+ echo "EXIT_REASON=\"${EXIT_REASON}\""
+ echo "EXIT_CODE=\"${EXIT_CODE}\""
+ echo "NETDATA_WARNINGS=\"${NETDATA_WARNINGS}\""
+ } >> "${NETDATA_SCRIPT_STATUS_PATH}"
+ else
+ export EXIT_REASON
+ export EXIT_CODE
+ export NETDATA_WARNINGS
+ fi
+ fi
+ fi
+}
+
+is_integer () {
+ case "${1#[+-]}" in
+ *[!0123456789]*) return 1 ;;
+ '') return 1 ;;
+ *) return 0 ;;
+ esac
+}
+
+issystemd() {
+ # if the directory /lib/systemd/system OR /usr/lib/systemd/system (SLES 12.x) does not exit, it is not systemd
+ if [ ! -d /lib/systemd/system ] && [ ! -d /usr/lib/systemd/system ]; then
+ return 1
+ fi
+
+ # if there is no systemctl command, it is not systemd
+ systemctl=$(command -v systemctl 2> /dev/null)
+ if [ -z "${systemctl}" ] || [ ! -x "${systemctl}" ]; then
+ return 1
+ fi
+
+ # if pid 1 is systemd, it is systemd
+ [ "$(basename "$(readlink /proc/1/exe)" 2> /dev/null)" = "systemd" ] && return 0
+
+ # if systemd is not running, it is not systemd
+ pids=$(safe_pidof systemd 2> /dev/null)
+ [ -z "${pids}" ] && return 1
+
+ # check if the running systemd processes are not in our namespace
+ myns="$(readlink /proc/self/ns/pid 2> /dev/null)"
+ for p in ${pids}; do
+ ns="$(readlink "/proc/${p}/ns/pid" 2> /dev/null)"
+
+ # if pid of systemd is in our namespace, it is systemd
+ [ -n "${myns}" ] && [ "${myns}" = "${ns}" ] && return 0
+ done
+
+ # else, it is not systemd
+ return 1
+}
+
+_get_intervaldir() {
+ if [ -d /etc/cron.daily ]; then
+ echo /etc/cron.daily
+ elif [ -d /etc/periodic/daily ]; then
+ echo /etc/periodic/daily
+ else
+ return 1
+ fi
+
+ return 0
+}
+
+_get_scheduler_type() {
+ if _get_intervaldir > /dev/null ; then
+ echo 'interval'
+ elif issystemd ; then
+ echo 'systemd'
+ elif [ -d /etc/cron.d ] ; then
+ echo 'crontab'
+ else
+ echo 'none'
+ fi
+}
+
+install_build_dependencies() {
+ bash="$(command -v bash 2> /dev/null)"
+
+ if [ -z "${bash}" ] || [ ! -x "${bash}" ]; then
+ error "Unable to find a usable version of \`bash\` (required for local build)."
+ return 1
+ fi
+
+ info "Fetching dependency handling script..."
+ download "${PACKAGES_SCRIPT}" "./install-required-packages.sh" || true
+
+ if [ ! -s "./install-required-packages.sh" ]; then
+ error "Downloaded dependency installation script is empty."
+ else
+ info "Running dependency handling script..."
+
+ opts="--dont-wait --non-interactive"
+
+ # shellcheck disable=SC2086
+ if ! "${bash}" "./install-required-packages.sh" ${opts} netdata >&3 2>&3; then
+ error "Installing build dependencies failed. The update should still work, but you might be missing some features."
+ fi
+ fi
+}
+
+enable_netdata_updater() {
+ updater_type="$(echo "${1}" | tr '[:upper:]' '[:lower:]')"
+ case "${updater_type}" in
+ systemd|interval|crontab)
+ updater_type="${1}"
+ ;;
+ "")
+ updater_type="$(_get_scheduler_type)"
+ ;;
+ *)
+ fatal "Unrecognized updater type ${updater_type} requested. Supported types are 'systemd', 'interval', and 'crontab'." U0001
+ ;;
+ esac
+
+ case "${updater_type}" in
+ "systemd")
+ if issystemd; then
+ systemctl enable netdata-updater.timer
+
+ info "Auto-updating has been ENABLED using a systemd timer unit.\n"
+ info "If the update process fails, the failure will be logged to the systemd journal just like a regular service failure."
+ info "Successful updates should produce empty logs."
+ else
+ error "Systemd-based auto-update scheduling requested, but this does not appear to be a systemd system. Auto-updates have NOT been enabled."
+ return 1
+ fi
+ ;;
+ "interval")
+ if _get_intervaldir > /dev/null; then
+ ln -sf "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh" "$(_get_intervaldir)/netdata-updater"
+
+ info "Auto-updating has been ENABLED through cron, updater script linked to $(_get_intervaldir)/netdata-updater\n"
+ 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."
+ info "Successful updates will not send an email."
+ else
+ error "Interval-based auto-update scheduling requested, but I could not find an interval scheduling directory. Auto-updates have NOT been enabled."
+ return 1
+ fi
+ ;;
+ "crontab")
+ if [ -d "/etc/cron.d" ]; then
+ [ -f "/etc/cron.d/netdata-updater" ] && rm -f "/etc/cron.d/netdata-updater"
+ install -p -m 0644 -o 0 -g 0 "${NETDATA_PREFIX}/usr/lib/system/cron/netdata-updater-daily" "/etc/cron.d/netdata-updater-daily"
+
+ info "Auto-updating has been ENABLED through cron, using a crontab at /etc/cron.d/netdata-updater\n"
+ 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."
+ info "Successful updates will not send an email."
+ else
+ error "Crontab-based auto-update scheduling requested, but there is no '/etc/cron.d'. Auto-updates have NOT been enabled."
+ return 1
+ fi
+ ;;
+ *)
+ error "Unable to determine what type of auto-update scheduling to use. Auto-updates have NOT been enabled."
+ return 1
+ esac
+
+ return 0
+}
+
+disable_netdata_updater() {
+ if issystemd && ( systemctl list-units --full -all | grep -Fq "netdata-updater.timer" ) ; then
+ systemctl disable netdata-updater.timer
+ fi
+
+ if [ -d /etc/cron.daily ]; then
+ rm -f /etc/cron.daily/netdata-updater.sh
+ rm -f /etc/cron.daily/netdata-updater
+ fi
+
+ if [ -d /etc/periodic/daily ]; then
+ rm -f /etc/periodic/daily/netdata-updater.sh
+ rm -f /etc/periodic/daily/netdata-updater
+ fi
+
+ if [ -d /etc/cron.d ]; then
+ rm -f /etc/cron.d/netdata-updater
+ rm -f /etc/cron.d/netdata-updater-daily
+ fi
+
+ info "Auto-updates have been DISABLED."
+
+ return 0
+}
+
+str_in_list() {
+ printf "%s\n" "${2}" | tr ' ' "\n" | grep -qE "^${1}\$"
+ return $?
+}
+
+safe_sha256sum() {
+ # Within the context of the installer, we only use -c option that is common between the two commands
+ # We will have to reconsider if we start non-common options
+ if command -v shasum > /dev/null 2>&1; then
+ shasum -a 256 "$@"
+ elif command -v sha256sum > /dev/null 2>&1; then
+ sha256sum "$@"
+ else
+ fatal "I could not find a suitable checksum binary to use" U0002
+ fi
+}
+
+cleanup() {
+ if [ -n "${logfile}" ]; then
+ cat >&2 "${logfile}"
+ rm "${logfile}"
+ fi
+
+ if [ -n "$ndtmpdir" ] && [ -d "$ndtmpdir" ]; then
+ rm -rf "$ndtmpdir"
+ fi
+}
+
+_cannot_use_tmpdir() {
+ testfile="$(TMPDIR="${1}" mktemp -q -t netdata-test.XXXXXXXXXX)"
+ ret=0
+
+ if [ -z "${testfile}" ] ; then
+ return "${ret}"
+ fi
+
+ if printf '#!/bin/sh\necho SUCCESS\n' > "${testfile}" ; then
+ if chmod +x "${testfile}" ; then
+ if [ "$("${testfile}" 2>/dev/null)" = "SUCCESS" ] ; then
+ ret=1
+ fi
+ fi
+ fi
+
+ rm -f "${testfile}"
+ return "${ret}"
+}
+
+create_tmp_directory() {
+ if [ -n "${NETDATA_TMPDIR_PATH}" ]; then
+ echo "${NETDATA_TMPDIR_PATH}"
+ else
+ if [ -z "${NETDATA_TMPDIR}" ] || _cannot_use_tmpdir "${NETDATA_TMPDIR}" ; then
+ if [ -z "${TMPDIR}" ] || _cannot_use_tmpdir "${TMPDIR}" ; then
+ if _cannot_use_tmpdir /tmp ; then
+ if _cannot_use_tmpdir "${PWD}" ; then
+ 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
+ else
+ TMPDIR="${PWD}"
+ fi
+ else
+ TMPDIR="/tmp"
+ fi
+ fi
+ else
+ TMPDIR="${NETDATA_TMPDIR}"
+ fi
+
+ mktemp -d -t netdata-updater-XXXXXXXXXX
+ fi
+}
+
+check_for_curl() {
+ if [ -z "${curl}" ]; then
+ curl="$(PATH="${PATH}:/opt/netdata/bin" command -v curl 2>/dev/null && true)"
+ fi
+}
+
+_safe_download() {
+ url="${1}"
+ dest="${2}"
+
+ check_for_curl
+
+ if [ -n "${curl}" ]; then
+ "${curl}" -sSL --connect-timeout 10 --retry 3 "${url}" > "${dest}"
+ return $?
+ elif command -v wget > /dev/null 2>&1; then
+ wget -T 15 -O - "${url}" > "${dest}"
+ return $?
+ else
+ return 255
+ fi
+}
+
+download() {
+ url="${1}"
+ dest="${2}"
+
+ _safe_download "${url}" "${dest}"
+ ret=$?
+
+ if [ ${ret} -eq 0 ]; then
+ return 0
+ elif [ ${ret} -eq 255 ]; then
+ fatal "I need curl or wget to proceed, but neither is available on this system." U0004
+ else
+ fatal "Cannot download ${url}" U0005
+ fi
+}
+
+get_netdata_latest_tag() {
+ url="${1}/latest"
+ dest="${2}"
+
+ check_for_curl
+
+ if [ -n "${curl}" ]; then
+ tag=$("${curl}" "${url}" -s -L -I -o /dev/null -w '%{url_effective}' | grep -m 1 -o '[^/]*$')
+ elif command -v wget >/dev/null 2>&1; then
+ tag=$(wget -S -O /dev/null "${url}" 2>&1 | grep -m 1 Location | grep -o '[^/]*$')
+ else
+ fatal "I need curl or wget to proceed, but neither of them are available on this system." U0006
+ fi
+
+ echo "${tag}" >"${dest}"
+}
+
+newer_commit_date() {
+ info "Checking if a newer version of the updater script is available."
+
+ commit_check_url="https://api.github.com/repos/netdata/netdata/commits?path=packaging%2Finstaller%2Fnetdata-updater.sh&page=1&per_page=1"
+ 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 '')"
+
+ if command -v jq > /dev/null 2>&1; then
+ commit_date="$(_safe_download "${commit_check_url}" /dev/stdout | jq '.[0].commit.committer.date' 2>/dev/null | tr -d '"')"
+ elif command -v python > /dev/null 2>&1;then
+ commit_date="$(_safe_download "${commit_check_url}" /dev/stdout | python -c "${python_version_check}")"
+ elif command -v python3 > /dev/null 2>&1;then
+ commit_date="$(_safe_download "${commit_check_url}" /dev/stdout | python3 -c "${python_version_check}")"
+ fi
+
+ if [ -z "${commit_date}" ] ; then
+ return 0
+ elif [ "$(uname)" = "Linux" ]; then
+ commit_date="$(date -d "${commit_date}" +%s)"
+ else # assume BSD-style `date` if we are not on Linux
+ commit_date="$(/bin/date -j -f "%Y-%m-%dT%H:%M:%SZ" "${commit_date}" +%s 2>/dev/null)"
+
+ if [ -z "${commit_date}" ]; then
+ return 0
+ fi
+ fi
+
+ if [ -e "${script_source}" ]; then
+ script_date="$(date -r "${script_source}" +%s)"
+ else
+ script_date="$(date +%s)"
+ fi
+
+ [ "${commit_date}" -ge "${script_date}" ]
+}
+
+self_update() {
+ if [ -z "${NETDATA_NO_UPDATER_SELF_UPDATE}" ] && newer_commit_date; then
+ info "Downloading newest version of updater script."
+
+ ndtmpdir=$(create_tmp_directory)
+ cd "$ndtmpdir" || exit 1
+
+ if _safe_download "https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/netdata-updater.sh" ./netdata-updater.sh; then
+ chmod +x ./netdata-updater.sh || exit 1
+ export ENVIRONMENT_FILE="${ENVIRONMENT_FILE}"
+ force_update=""
+ [ "$NETDATA_FORCE_UPDATE" = "1" ] && force_update="--force-update"
+ exec ./netdata-updater.sh --not-running-from-cron --no-updater-self-update "$force_update" --tmpdir-path "$(pwd)"
+ else
+ error "Failed to download newest version of updater script, continuing with current version."
+ fi
+ fi
+}
+
+parse_version() {
+ r="${1}"
+ if [ "${r}" = "latest" ]; then
+ # If we get ‘latest’ as a version, return the largest possible
+ # version value.
+ printf "99999999999999"
+ return 0
+ elif echo "${r}" | grep -q '^v.*'; then
+ # shellcheck disable=SC2001
+ # XXX: Need a regex group substitution here.
+ r="$(echo "${r}" | sed -e 's/^v\(.*\)/\1/')"
+ fi
+
+ tmpfile="$(mktemp)"
+ echo "${r}" | tr '-' ' ' > "${tmpfile}"
+ read -r v b _ < "${tmpfile}"
+
+ if echo "${b}" | grep -vEq "^[0-9]+$"; then
+ b="0"
+ fi
+
+ echo "${v}" | tr '.' ' ' > "${tmpfile}"
+ read -r maj min patch _ < "${tmpfile}"
+
+ rm -f "${tmpfile}"
+
+ printf "%03d%03d%03d%05d" "${maj}" "${min}" "${patch}" "${b}"
+}
+
+get_latest_version() {
+ if [ "${RELEASE_CHANNEL}" = "stable" ]; then
+ get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout
+ else
+ get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout
+ fi
+}
+
+validate_environment_file() {
+ if [ -n "${NETDATA_PREFIX+SET_BUT_NULL}" ] && [ -n "${REINSTALL_OPTIONS+SET_BUT_NULL}" ]; then
+ return 0
+ else
+ fatal "Environment file located at ${ENVIRONMENT_FILE} is not valid, unable to update." U0007
+ fi
+}
+
+update_available() {
+ if [ "$NETDATA_FORCE_UPDATE" = "1" ]; then
+ info "Force update requested"
+ return 0
+ fi
+ basepath="$(dirname "$(dirname "$(dirname "${NETDATA_LIB_DIR}")")")"
+ searchpath="${basepath}/bin:${basepath}/sbin:${basepath}/usr/bin:${basepath}/usr/sbin:${PATH}"
+ searchpath="${basepath}/netdata/bin:${basepath}/netdata/sbin:${basepath}/netdata/usr/bin:${basepath}/netdata/usr/sbin:${searchpath}"
+ ndbinary="$(PATH="${searchpath}" command -v netdata 2>/dev/null)"
+
+ if [ -z "${ndbinary}" ]; then
+ current_version=0
+ else
+ current_version="$(parse_version "$(${ndbinary} -v | cut -f 2 -d ' ')")"
+ fi
+
+ latest_tag="$(get_latest_version)"
+ latest_version="$(parse_version "${latest_tag}")"
+ path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")"
+
+ # If we can't get the current version for some reason assume `0`
+ current_version="${current_version:-0}"
+
+ # If we can't get the latest version for some reason assume `0`
+ latest_version="${latest_version:-0}"
+
+ info "Current Version: ${current_version}"
+ info "Latest Version: ${latest_version}"
+
+ if [ "${latest_version}" -gt 0 ] && [ "${current_version}" -gt 0 ] && [ "${current_version}" -ge "${latest_version}" ]; then
+ info "Newest version (current=${current_version} >= latest=${latest_version}) is already installed"
+ return 1
+ else
+ info "Update available"
+ return 0
+ fi
+}
+
+set_tarball_urls() {
+ filename="netdata-latest.tar.gz"
+
+ if [ "$2" = "yes" ]; then
+ if [ -e /opt/netdata/etc/netdata/.install-type ]; then
+ # shellcheck disable=SC1091
+ . /opt/netdata/etc/netdata/.install-type
+ filename="netdata-${PREBUILT_ARCH}-latest.gz.run"
+ else
+ filename="netdata-x86_64-latest.gz.run"
+ fi
+ fi
+
+ if [ "$1" = "stable" ]; then
+ latest="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout)"
+ export NETDATA_TARBALL_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/${filename}"
+ export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/sha256sums.txt"
+ else
+ tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout)"
+ export NETDATA_TARBALL_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/${filename}"
+ export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/sha256sums.txt"
+ fi
+}
+
+update_build() {
+ [ -z "${logfile}" ] && info "Running on a terminal - (this script also supports running headless from crontab)"
+
+ RUN_INSTALLER=0
+ ndtmpdir=$(create_tmp_directory)
+ cd "$ndtmpdir" || fatal "Failed to change current working directory to ${ndtmpdir}" U0016
+
+ install_build_dependencies
+
+ if update_available; then
+ download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" >&3 2>&3
+ download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz"
+ if [ -n "${NETDATA_TARBALL_CHECKSUM}" ] &&
+ grep "${NETDATA_TARBALL_CHECKSUM}" sha256sum.txt >&3 2>&3 &&
+ [ "$NETDATA_FORCE_UPDATE" != "1" ]; then
+ info "Newest version is already installed"
+ else
+ if ! grep netdata-latest.tar.gz sha256sum.txt | safe_sha256sum -c - >&3 2>&3; then
+ 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
+ fi
+ NEW_CHECKSUM="$(safe_sha256sum netdata-latest.tar.gz 2> /dev/null | cut -d' ' -f1)"
+ tar -xf netdata-latest.tar.gz >&3 2>&3
+ rm netdata-latest.tar.gz >&3 2>&3
+ if [ -z "$path_version" ]; then
+ latest_tag="$(get_latest_version)"
+ path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")"
+ fi
+ cd "$(find . -maxdepth 1 -type d -name "netdata-${path_version}*" | head -n 1)" || fatal "Failed to switch to build directory" U0017
+ RUN_INSTALLER=1
+ fi
+ fi
+
+ # We got the sources, run the update now
+ if [ ${RUN_INSTALLER} -eq 1 ]; then
+ # signal netdata to start saving its database
+ # this is handy if your database is big
+ possible_pids=$(pidof netdata)
+ do_not_start=
+ if [ -n "${possible_pids}" ]; then
+ # shellcheck disable=SC2086
+ kill -USR1 ${possible_pids}
+ else
+ # netdata is currently not running, so do not start it after updating
+ do_not_start="--dont-start-it"
+ fi
+
+ env="env TMPDIR=${TMPDIR}"
+
+ if [ -n "${NETDATA_SELECTED_DASHBOARD}" ]; then
+ env="${env} NETDATA_SELECTED_DASHBOARD=${NETDATA_SELECTED_DASHBOARD}"
+ fi
+
+ if [ ! -x ./netdata-installer.sh ]; then
+ if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -x "$(find . -mindepth 1 -maxdepth 1 -type d)/netdata-installer.sh" ]; then
+ cd "$(find . -mindepth 1 -maxdepth 1 -type d)" || fatal "Failed to switch to build directory" U0018
+ fi
+ fi
+
+ if [ -e "${NETDATA_PREFIX}/etc/netdata/.install-type" ] ; then
+ install_type="$(cat "${NETDATA_PREFIX}"/etc/netdata/.install-type)"
+ else
+ install_type="INSTALL_TYPE='legacy-build'"
+ fi
+
+ if [ "${INSTALL_TYPE}" = "custom" ] && [ -f "${NETDATA_PREFIX}" ]; then
+ install_type="INSTALL_TYPE='legacy-build'"
+ fi
+
+ info "Re-installing netdata..."
+ export NETDATA_SAVE_WARNINGS=1
+ export NETDATA_PROPAGATE_WARNINGS=1
+ export NETDATA_WARNINGS="${NETDATA_WARNINGS}"
+ export NETDATA_SCRIPT_STATUS_PATH="${NETDATA_SCRIPT_STATUS_PATH}"
+ # shellcheck disable=SC2086
+ if ! ${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start} >&3 2>&3; then
+ if [ -r "${NETDATA_SCRIPT_STATUS_PATH}" ]; then
+ # shellcheck disable=SC1090
+ . "${NETDATA_SCRIPT_STATUS_PATH}"
+ rm -f "${NETDATA_SCRIPT_STATUS_PATH}"
+ fi
+ if [ -n "${EXIT_REASON}" ]; then
+ fatal "Failed to rebuild existing netdata install: ${EXIT_REASON}" "U${EXIT_CODE}"
+ else
+ fatal "Failed to rebuild existing netdata reinstall." UI0000
+ fi
+ fi
+
+ # We no longer store checksum info here. but leave this so that we clean up all environment files upon next update.
+ sed -i '/NETDATA_TARBALL/d' "${ENVIRONMENT_FILE}"
+
+ info "Updating tarball checksum info"
+ echo "${NEW_CHECKSUM}" > "${NETDATA_LIB_DIR}/netdata.tarball.checksum"
+
+ echo "${install_type}" > "${NETDATA_PREFIX}/etc/netdata/.install-type"
+ fi
+
+ rm -rf "${ndtmpdir}" >&3 2>&3
+ [ -n "${logfile}" ] && rm "${logfile}" && logfile=
+
+ return 0
+}
+
+update_static() {
+ ndtmpdir="$(create_tmp_directory)"
+ PREVDIR="$(pwd)"
+
+ info "Entering ${ndtmpdir}"
+ cd "${ndtmpdir}" || fatal "Failed to change current working directory to ${ndtmpdir}" U0019
+
+ if update_available; then
+ sysarch="${PREBUILT_ARCH}"
+ [ -z "$sysarch" ] && sysarch="$(uname -m)"
+ download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt"
+ download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-${sysarch}-latest.gz.run"
+ if ! grep "netdata-${sysarch}-latest.gz.run" "${ndtmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
+ 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
+ fi
+
+ if [ -e /opt/netdata/etc/netdata/.install-type ] ; then
+ install_type="$(cat /opt/netdata/etc/netdata/.install-type)"
+ else
+ install_type="INSTALL_TYPE='legacy-static'"
+ fi
+
+ # Do not pass any options other than the accept, for now
+ # shellcheck disable=SC2086
+ if sh "${ndtmpdir}/netdata-${sysarch}-latest.gz.run" --accept -- ${REINSTALL_OPTIONS} >&3 2>&3; then
+ rm -r "${ndtmpdir}"
+ else
+ info "NOTE: did not remove: ${ndtmpdir}"
+ fi
+
+ echo "${install_type}" > /opt/netdata/etc/netdata/.install-type
+ fi
+
+ if [ -e "${PREVDIR}" ]; then
+ info "Switching back to ${PREVDIR}"
+ cd "${PREVDIR}"
+ fi
+ [ -n "${logfile}" ] && rm "${logfile}" && logfile=
+ exit 0
+}
+
+update_binpkg() {
+ os_release_file=
+ if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then
+ os_release_file="/etc/os-release"
+ elif [ -s "/usr/lib/os-release" ] && [ -r "/usr/lib/os-release" ]; then
+ os_release_file="/usr/lib/os-release"
+ else
+ fatal "Cannot find an os-release file ..." U000B
+ fi
+
+ # shellcheck disable=SC1090
+ . "${os_release_file}"
+
+ DISTRO="${ID}"
+
+ supported_compat_names="debian ubuntu centos fedora opensuse ol amzn"
+
+ if str_in_list "${DISTRO}" "${supported_compat_names}"; then
+ DISTRO_COMPAT_NAME="${DISTRO}"
+ else
+ case "${DISTRO}" in
+ opensuse-leap|opensuse-tumbleweed)
+ DISTRO_COMPAT_NAME="opensuse"
+ ;;
+ cloudlinux|almalinux|centos-stream|rocky|rhel)
+ DISTRO_COMPAT_NAME="centos"
+ ;;
+ *)
+ DISTRO_COMPAT_NAME="unknown"
+ ;;
+ esac
+ fi
+
+ interactive_opts=""
+ env=""
+
+ case "${DISTRO_COMPAT_NAME}" in
+ debian|ubuntu)
+ if [ "${INTERACTIVE}" = "0" ]; then
+ upgrade_subcmd="-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold --only-upgrade install"
+ interactive_opts="-y"
+ env="DEBIAN_FRONTEND=noninteractive"
+ else
+ upgrade_subcmd="--only-upgrade install"
+ fi
+ pm_cmd="apt-get"
+ repo_subcmd="update"
+ install_subcmd="install"
+ mark_auto_cmd="apt-mark auto"
+ pkg_install_opts="${interactive_opts}"
+ repo_update_opts="${interactive_opts}"
+ pkg_installed_check="dpkg-query -s"
+ INSTALL_TYPE="binpkg-deb"
+ ;;
+ centos|fedora|ol|amzn)
+ if [ "${INTERACTIVE}" = "0" ]; then
+ interactive_opts="-y"
+ fi
+ if command -v dnf > /dev/null; then
+ pm_cmd="dnf"
+ repo_subcmd="makecache"
+ mark_auto_cmd="dnf mark remove"
+ else
+ pm_cmd="yum"
+ mark_auto_cmd="yumdb set reason dep"
+ fi
+ upgrade_subcmd="upgrade"
+ install_subcmd="install"
+ pkg_install_opts="${interactive_opts}"
+ repo_update_opts="${interactive_opts}"
+ pkg_installed_check="rpm -q"
+ INSTALL_TYPE="binpkg-rpm"
+ ;;
+ opensuse)
+ if [ "${INTERACTIVE}" = "0" ]; then
+ upgrade_subcmd="--non-interactive update"
+ else
+ upgrade_subcmd="update"
+ fi
+ pm_cmd="zypper"
+ repo_subcmd="--gpg-auto-import-keys refresh"
+ install_subcmd="install"
+ mark_auto_cmd=""
+ pkg_install_opts=""
+ repo_update_opts=""
+ pkg_installed_check="rpm -q"
+ INSTALL_TYPE="binpkg-rpm"
+ ;;
+ *)
+ warning "We do not provide native packages for ${DISTRO}."
+ return 2
+ ;;
+ esac
+
+ if [ -n "${repo_subcmd}" ]; then
+ # shellcheck disable=SC2086
+ env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000C
+ fi
+
+ for repopkg in netdata-repo netdata-repo-edge; do
+ if ${pkg_installed_check} ${repopkg} > /dev/null 2>&1; then
+ # shellcheck disable=SC2086
+ env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} ${repopkg} >&3 2>&3 || fatal "Failed to update Netdata repository config." U000D
+ # shellcheck disable=SC2086
+ if [ -n "${repo_subcmd}" ]; then
+ env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000E
+ fi
+ fi
+ done
+
+ # shellcheck disable=SC2086
+ env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F
+
+ if ${pkg_installed_check} systemd > /dev/null 2>&1; then
+ if [ "${NETDATA_NO_SYSTEMD_JOURNAL}" -eq 0 ]; then
+ if ! ${pkg_installed_check} netdata-plugin-systemd-journal > /dev/null 2>&1; then
+ env ${env} ${pm_cmd} ${install_subcmd} ${pkg_install_opts} netdata-plugin-systemd-journal >&3 2>&3
+
+ if [ -n "${mark_auto_cmd}" ]; then
+ # shellcheck disable=SC2086
+ env ${env} ${mark_auto_cmd} netdata-plugin-systemd-journal >&3 2>&3
+ fi
+ fi
+ fi
+ fi
+
+ [ -n "${logfile}" ] && rm "${logfile}" && logfile=
+ return 0
+}
+
+# Simple function to encapsulate original updater behavior.
+update_legacy() {
+ set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
+ case "${IS_NETDATA_STATIC_BINARY}" in
+ yes) update_static && exit 0 ;;
+ *) update_build && exit 0 ;;
+ esac
+}
+
+logfile=
+ndtmpdir=
+
+trap cleanup EXIT
+
+if [ -t 2 ] || [ "${GITHUB_ACTIONS}" ]; then
+ # we are running on a terminal or under CI
+ # open fd 3 and send it to stderr
+ exec 3>&2
+else
+ # we are headless
+ # create a temporary file for the log
+ logfile="$(mktemp -t netdata-updater.log.XXXXXX)"
+ # open fd 3 and send it to logfile
+ exec 3> "${logfile}"
+fi
+
+: "${ENVIRONMENT_FILE:=THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT}"
+
+if [ "${ENVIRONMENT_FILE}" = "THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT" ]; then
+ if [ -r "${script_dir}/../../../etc/netdata/.environment" ] || [ -r "${script_dir}/../../../etc/netdata/.install-type" ]; then
+ ENVIRONMENT_FILE="${script_dir}/../../../etc/netdata/.environment"
+ elif [ -r "/etc/netdata/.environment" ] || [ -r "/etc/netdata/.install-type" ]; then
+ ENVIRONMENT_FILE="/etc/netdata/.environment"
+ elif [ -r "/opt/netdata/etc/netdata/.environment" ] || [ -r "/opt/netdata/etc/netdata/.install-type" ]; then
+ ENVIRONMENT_FILE="/opt/netdata/etc/netdata/.environment"
+ else
+ 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)"
+ 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)"
+ if [ -r "${envpath}" ]; then
+ ENVIRONMENT_FILE="${envpath}"
+ elif [ -r "${itpath}" ]; then
+ ENVIRONMENT_FILE="$(dirname "${itpath}")/.environment"
+ else
+ fatal "Cannot find environment file or install type file, unable to update." U0010
+ fi
+ fi
+fi
+
+if [ -r "${ENVIRONMENT_FILE}" ] ; then
+ # shellcheck source=/dev/null
+ . "${ENVIRONMENT_FILE}" || fatal "Failed to source ${ENVIRONMENT_FILE}" U0014
+fi
+
+if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then
+ # shellcheck source=/dev/null
+ . "$(dirname "${ENVIRONMENT_FILE}")/.install-type" || fatal "Failed to source $(dirname "${ENVIRONMENT_FILE}")/.install-type" U0015
+fi
+
+if [ -r "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf" ]; then
+ # shellcheck source=/dev/null
+ . "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
+fi
+
+while [ -n "${1}" ]; do
+ case "${1}" in
+ --not-running-from-cron) NETDATA_NOT_RUNNING_FROM_CRON=1 ;;
+ --no-updater-self-update) NETDATA_NO_UPDATER_SELF_UPDATE=1 ;;
+ --force-update) NETDATA_FORCE_UPDATE=1 ;;
+ --non-interactive) INTERACTIVE=0 ;;
+ --interactive) INTERACTIVE=1 ;;
+ --tmpdir-path)
+ NETDATA_TMPDIR_PATH="${2}"
+ shift 1
+ ;;
+ --enable-auto-updates)
+ enable_netdata_updater "${2}"
+ exit $?
+ ;;
+ --disable-auto-updates)
+ disable_netdata_updater
+ exit $?
+ ;;
+ *) fatal "Unrecognized option ${1}" U001A ;;
+ esac
+
+ shift 1
+done
+
+# Random sleep to alleviate stampede effect of Agents upgrading
+# and disconnecting/reconnecting at the same time (or near to).
+# But only we're not a controlling terminal (tty)
+# Randomly sleep between 1s and 60m
+if [ ! -t 1 ] && \
+ [ -z "${GITHUB_ACTIONS}" ] && \
+ [ -z "${NETDATA_NOT_RUNNING_FROM_CRON}" ] && \
+ is_integer "${NETDATA_UPDATER_JITTER}" && \
+ [ "${NETDATA_UPDATER_JITTER}" -gt 1 ]; then
+ rnd="$(awk "
+ BEGIN { srand()
+ printf(\"%d\\n\", ${NETDATA_UPDATER_JITTER} * rand())
+ }")"
+ sleep $(((rnd % NETDATA_UPDATER_JITTER) + 1))
+fi
+
+# We dont expect to find lib dir variable on older installations, so load this path if none found
+export NETDATA_LIB_DIR="${NETDATA_LIB_DIR:-${NETDATA_PREFIX}/var/lib/netdata}"
+
+# Source the tarball checksum, if not already available from environment (for existing installations with the old logic)
+[ -z "${NETDATA_TARBALL_CHECKSUM}" ] && [ -f "${NETDATA_LIB_DIR}/netdata.tarball.checksum" ] && NETDATA_TARBALL_CHECKSUM="$(cat "${NETDATA_LIB_DIR}/netdata.tarball.checksum")"
+
+if echo "$INSTALL_TYPE" | grep -qv ^binpkg && [ "${INSTALL_UID}" != "$(id -u)" ]; then
+ 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
+fi
+
+self_update
+
+# shellcheck disable=SC2153
+case "${INSTALL_TYPE}" in
+ *-build)
+ validate_environment_file
+ set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
+ update_build && exit 0
+ ;;
+ *-static*)
+ validate_environment_file
+ set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
+ update_static && exit 0
+ ;;
+ *binpkg*) update_binpkg && exit 0 ;;
+ "") # Fallback case for no `.install-type` file. This just works like the old install type detection.
+ validate_environment_file
+ update_legacy
+ ;;
+ custom)
+ # At this point, we _should_ have a valid `.environment` file, but it's best to just check.
+ # If we do, then behave like the legacy updater.
+ if validate_environment_file && [ -n "${IS_NETDATA_STATIC_BINARY}" ]; then
+ update_legacy
+ else
+ fatal "This script does not support updating custom installations without valid environment files." U0012
+ fi
+ ;;
+ oci) fatal "This script does not support updating Netdata inside our official Docker containers, please instead update the container itself." U0013 ;;
+ *) fatal "Unrecognized installation type (${INSTALL_TYPE}), unable to update." U0014 ;;
+esac