summaryrefslogtreecommitdiffstats
path: root/packaging/installer/netdata-updater.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xpackaging/installer/netdata-updater.sh428
1 files changed, 428 insertions, 0 deletions
diff --git a/packaging/installer/netdata-updater.sh b/packaging/installer/netdata-updater.sh
new file mode 100755
index 0000000..10835cd
--- /dev/null
+++ b/packaging/installer/netdata-updater.sh
@@ -0,0 +1,428 @@
+#!/usr/bin/env bash
+
+# Netdata updater utility
+#
+# Variables needed by script:
+# - PATH
+# - CFLAGS
+# - LDFLAGS
+# - IS_NETDATA_STATIC_BINARY
+# - NETDATA_CONFIGURE_OPTIONS
+# - REINSTALL_OPTIONS
+# - NETDATA_TARBALL_URL
+# - NETDATA_TARBALL_CHECKSUM_URL
+# - NETDATA_TARBALL_CHECKSUM
+# - NETDATA_PREFIX / NETDATA_LIB_DIR (After 1.16.1 we will only depend on 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-2020 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>
+
+set -e
+
+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
+
+info() {
+ echo >&3 "$(date) : INFO: " "${@}"
+}
+
+error() {
+ echo >&3 "$(date) : ERROR: " "${@}"
+}
+
+: "${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" ]; then
+ ENVIRONMENT_FILE="${script_dir}/../../../etc/netdata/.environment"
+ elif [ -r "/etc/netdata/.environment" ]; then
+ ENVIRONMENT_FILE="/etc/netdata/.environment"
+ elif [ -r "/opt/netdata/etc/netdata/.environment" ]; 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)"
+ if [ -r "${envpath}" ]; then
+ ENVIRONMENT_FILE="${envpath}"
+ else
+ error "Cannot find environment file, unable to update."
+ exit 1
+ fi
+ fi
+fi
+
+safe_sha256sum() {
+ # Within the contexct 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 sha256sum > /dev/null 2>&1; then
+ sha256sum "$@"
+ elif command -v shasum > /dev/null 2>&1; then
+ shasum -a 256 "$@"
+ else
+ fatal "I could not find a suitable checksum binary to use"
+ fi
+}
+
+# this is what we will do if it fails (head-less only)
+fatal() {
+ error "FAILED TO UPDATE NETDATA : ${1}"
+ exit 1
+}
+
+cleanup() {
+ if [ -n "${logfile}" ]; then
+ cat >&2 "${logfile}"
+ rm "${logfile}"
+ fi
+
+ if [ -n "$ndtmpdir" ] && [ -d "$ndtmpdir" ]; then
+ rm -rf "$ndtmpdir"
+ fi
+}
+
+_cannot_use_tmpdir() {
+ local testfile ret
+ 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}")" = "SUCCESS" ] ; then
+ ret=1
+ fi
+ fi
+ fi
+
+ rm -f "${testfile}"
+ return "${ret}"
+}
+
+create_tmp_directory() {
+ if [ -n "${NETDATA_TMPDIR_PATH}" ]; then
+ TMPDIR="${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
+ echo >&2
+ echo >&2 "Unable to find a usable temprorary directory. Please set \$TMPDIR to a path that is both writable and allows execution of files and try again."
+ exit 1
+ else
+ TMPDIR="${PWD}"
+ fi
+ else
+ TMPDIR="/tmp"
+ fi
+ fi
+ else
+ TMPDIR="${NETDATA_TMPDIR}"
+ fi
+
+ mktemp -d -t netdata-updater-XXXXXXXXXX
+ fi
+}
+
+_safe_download() {
+ url="${1}"
+ dest="${2}"
+ if command -v curl > /dev/null 2>&1; 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."
+ else
+ fatal "Cannot download ${url}"
+ fi
+}
+
+newer_commit_date() {
+ echo >&3 "Checking if a newer version of the updater script is available."
+
+ if command -v jq > /dev/null 2>&1; then
+ commit_date="$(_safe_download "https://api.github.com/repos/netdata/netdata/commits?path=packaging%2Finstaller%2Fnetdata-updater.sh&page=1&per_page=1" /dev/stdout | jq '.[0].commit.committer.date' | tr -d '"')"
+ elif command -v python > /dev/null 2>&1;then
+ commit_date="$(_safe_download "https://api.github.com/repos/netdata/netdata/commits?path=packaging%2Finstaller%2Fnetdata-updater.sh&page=1&per_page=1" /dev/stdout | python -c 'from __future__ import print_function;import sys,json;print(json.load(sys.stdin)[0]["commit"]["committer"]["date"])')"
+ elif command -v python3 > /dev/null 2>&1;then
+ commit_date="$(_safe_download "https://api.github.com/repos/netdata/netdata/commits?path=packaging%2Finstaller%2Fnetdata-updater.sh&page=1&per_page=1" /dev/stdout | python3 -c 'from __future__ import print_function;import sys,json;print(json.load(sys.stdin)[0]["commit"]["committer"]["date"])')"
+ fi
+
+ if [ -z "${commit_date}" ] ; then
+ commit_date="9999-12-31T23:59:59Z"
+ fi
+
+ if [ -e "${script_source}" ]; then
+ script_date="$(date -r "${script_source}" +%s)"
+ else
+ script_date="$(date +%s)"
+ fi
+
+ [ "$(date -d "${commit_date}" +%s)" -ge "${script_date}" ]
+}
+
+self_update() {
+ if [ -z "${NETDATA_NO_UPDATER_SELF_UPDATE}" ] && newer_commit_date; then
+ echo >&3 "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}"
+ exec ./netdata-updater.sh --not-running-from-cron --no-self-update --tmpdir-path "$(pwd)"
+ else
+ echo >&3 "Failed to download newest version of updater script, continuing with current version."
+ fi
+ fi
+}
+
+parse_version() {
+ r="${1}"
+ if echo "${r}" | grep -q '^v.*'; then
+ # shellcheck disable=SC2001
+ # XXX: Need a regex group subsitutation here.
+ r="$(echo "${r}" | sed -e 's/^v\(.*\)/\1/')"
+ fi
+
+ read -r -a p <<< "$(echo "${r}" | tr '-' ' ')"
+
+ v="${p[0]}"
+ b="${p[1]}"
+ _="${p[2]}" # ignore the SHA
+
+ if [[ ! "${b}" =~ ^[0-9]+$ ]]; then
+ b="0"
+ fi
+
+ read -r -a pp <<< "$(echo "${v}" | tr '.' ' ')"
+ printf "%03d%03d%03d%05d" "${pp[0]}" "${pp[1]}" "${pp[2]}" "${b}"
+}
+
+get_latest_version() {
+ local latest
+ if [ "${RELEASE_CHANNEL}" == "stable" ]; then
+ latest="$(download "https://api.github.com/repos/netdata/netdata/releases/latest" /dev/stdout | grep tag_name | cut -d'"' -f4)"
+ else
+ latest="$(download "$NETDATA_NIGHTLIES_BASEURL/latest-version.txt" /dev/stdout)"
+ fi
+ parse_version "$latest"
+}
+
+set_tarball_urls() {
+ local extension="tar.gz"
+
+ if [ "$2" == "yes" ]; then
+ extension="gz.run"
+ fi
+
+ if [ "$1" = "stable" ]; then
+ local latest
+ # Simple version
+ latest="$(download "https://api.github.com/repos/netdata/netdata/releases/latest" /dev/stdout | grep tag_name | cut -d'"' -f4)"
+ export NETDATA_TARBALL_URL="https://github.com/netdata/netdata/releases/download/$latest/netdata-$latest.${extension}"
+ export NETDATA_TARBALL_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/$latest/sha256sums.txt"
+ else
+ export NETDATA_TARBALL_URL="$NETDATA_NIGHTLIES_BASEURL/netdata-latest.${extension}"
+ export NETDATA_TARBALL_CHECKSUM_URL="$NETDATA_NIGHTLIES_BASEURL/sha256sums.txt"
+ fi
+}
+
+update() {
+ [ -z "${logfile}" ] && info "Running on a terminal - (this script also supports running headless from crontab)"
+
+ RUN_INSTALLER=0
+ ndtmpdir=$(create_tmp_directory)
+ cd "$ndtmpdir" || exit 1
+
+ download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" >&3 2>&3
+
+ current_version="$(command -v netdata > /dev/null && parse_version "$(netdata -v | cut -f 2 -d ' ')")"
+ latest_version="$(get_latest_version)"
+
+ # 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"
+ elif [ -n "${NETDATA_TARBALL_CHECKSUM}" ] && grep "${NETDATA_TARBALL_CHECKSUM}" sha256sum.txt >&3 2>&3; then
+ info "Newest version is already installed"
+ else
+ download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz"
+ 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."
+ 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
+ cd netdata-* || exit 1
+ RUN_INSTALLER=1
+ cd "${NETDATA_LOCAL_TARBAL_OVERRIDE}" || exit 1
+ 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
+ read -r -a pids_to_kill <<< "${possible_pids}"
+ kill -USR1 "${pids_to_kill[@]}"
+ else
+ # netdata is currently not running, so do not start it after updating
+ do_not_start="--dont-start-it"
+ fi
+
+ if [ -n "${NETDATA_SELECTED_DASHBOARD}" ]; then
+ 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)" || exit 1
+ fi
+ fi
+
+ info "Re-installing netdata..."
+ eval "${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start}" >&3 2>&3 || fatal "FAILED TO COMPILE/INSTALL NETDATA"
+
+ # 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"
+ fi
+
+ rm -rf "${ndtmpdir}" >&3 2>&3
+ [ -n "${logfile}" ] && rm "${logfile}" && logfile=
+
+ return 0
+}
+
+logfile=
+ndtmpdir=
+
+trap cleanup EXIT
+
+while [ -n "${1}" ]; do
+ if [ "${1}" = "--not-running-from-cron" ]; then
+ NETDATA_NOT_RUNNING_FROM_CRON=1
+ shift 1
+ elif [ "${1}" = "--no-updater-self-update" ]; then
+ NETDATA_NO_UPDATER_SELF_UPDATE=1
+ shift 1
+ elif [ "${1}" = "--tmpdir-path" ]; then
+ NETDATA_TMPDIR_PATH="${2}"
+ shift 2
+ else
+ break
+ fi
+done
+
+# Random sleep to aileviate 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 "${NETDATA_NOT_RUNNING_FROM_CRON}" ]; then
+ sleep $(((RANDOM % 3600) + 1))
+fi
+
+# shellcheck source=/dev/null
+source "${ENVIRONMENT_FILE}" || exit 1
+
+# 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 tarbal 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")"
+
+# Grab the nightlies baseurl (defaulting to our Google Storage bucket)
+export NETDATA_NIGHTLIES_BASEURL="${NETDATA_NIGHTLIES_BASEURL:-https://storage.googleapis.com/netdata-nightlies}"
+
+if [ "${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)"
+fi
+
+if [ -t 2 ]; then
+ # we are running on a terminal
+ # open fd 3 and send it to stderr
+ exec 3>&2
+else
+ # we are headless
+ # create a temporary file for the log
+ logfile="$(mktemp "${logfile}"/netdata-updater.log.XXXXXX)"
+ # open fd 3 and send it to logfile
+ exec 3> "${logfile}"
+fi
+
+self_update
+
+set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}"
+
+if [ "${IS_NETDATA_STATIC_BINARY}" == "yes" ]; then
+ ndtmpdir="$(create_tmp_directory)"
+ PREVDIR="$(pwd)"
+
+ echo >&2 "Entering ${ndtmpdir}"
+ cd "${ndtmpdir}" || exit 1
+
+ download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt"
+ download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.gz.run"
+ if ! grep netdata-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 somehere and can be resolved by simply retrying in an hour."
+ fi
+
+ # Do not pass any options other than the accept, for now
+ # shellcheck disable=SC2086
+ if sh "${ndtmpdir}/netdata-latest.gz.run" --accept -- ${REINSTALL_OPTIONS}; then
+ rm -r "${ndtmpdir}"
+ else
+ echo >&2 "NOTE: did not remove: ${ndtmpdir}"
+ fi
+ echo >&2 "Switching back to ${PREVDIR}"
+ cd "${PREVDIR}" || exit 1
+else
+ # the installer updates this script - so we run and exit in a single line
+ update && exit 0
+fi