summaryrefslogtreecommitdiffstats
path: root/packaging/installer/netdata-updater.sh
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/installer/netdata-updater.sh')
-rwxr-xr-xpackaging/installer/netdata-updater.sh243
1 files changed, 223 insertions, 20 deletions
diff --git a/packaging/installer/netdata-updater.sh b/packaging/installer/netdata-updater.sh
index 80faea0a0..fc8b39cdd 100755
--- a/packaging/installer/netdata-updater.sh
+++ b/packaging/installer/netdata-updater.sh
@@ -28,7 +28,7 @@
# Author: Pavlos Emm. Katsoulakis <paul@netdata.cloud>
# Author: Austin S. Hemmelgarn <austin@netdata.cloud>
-# Next unused error code: U001B
+# Next unused error code: U001D
set -e
@@ -36,10 +36,12 @@ PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packag
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}"
+NETDATA_DEFAULT_ACCEPT_MAJOR_VERSIONS="1 2"
# Following variables are intended to be overridden by the updater config file.
NETDATA_UPDATER_JITTER=3600
NETDATA_NO_SYSTEMD_JOURNAL=0
+NETDATA_ACCEPT_MAJOR_VERSIONS=''
script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)"
@@ -147,6 +149,43 @@ issystemd() {
return 1
}
+# shellcheck disable=SC2009
+running_under_anacron() {
+ pid="${1:-$$}"
+ iter="${2:-0}"
+
+ [ "${iter}" -gt 50 ] && return 1
+
+ if [ "$(uname -s)" = "Linux" ] && [ -r "/proc/${pid}/stat" ]; then
+ ppid="$(cut -f 4 -d ' ' "/proc/${pid}/stat")"
+ if [ -n "${ppid}" ]; then
+ # The below case accounts for the hidepid mount option for procfs, as well as setups with LSM
+ [ ! -r "/proc/${ppid}/comm" ] && return 1
+
+ [ "${ppid}" -eq "${pid}" ] && return 1
+
+ grep -q anacron "/proc/${ppid}/comm" && return 0
+
+ running_under_anacron "${ppid}" "$((iter + 1))"
+
+ return "$?"
+ fi
+ else
+ ppid="$(ps -o pid= -o ppid= 2>/dev/null | grep -e "^ *${pid}" | xargs | cut -f 2 -d ' ')"
+ if [ -n "${ppid}" ]; then
+ [ "${ppid}" -eq "${pid}" ] && return 1
+
+ ps -o pid= -o command= 2>/dev/null | grep -e "^ *${ppid}" | grep -q anacron && return 0
+
+ running_under_anacron "${ppid}" "$((iter + 1))"
+
+ return "$?"
+ fi
+ fi
+
+ return 1
+}
+
_get_intervaldir() {
if [ -d /etc/cron.daily ]; then
echo /etc/cron.daily
@@ -171,6 +210,38 @@ _get_scheduler_type() {
fi
}
+confirm() {
+ prompt="${1} [y/n]"
+
+ while true; do
+ echo "${prompt}"
+ read -r yn
+
+ case "$yn" in
+ [Yy]*) return 0;;
+ [Nn]*) return 1;;
+ *) echo "Please answer yes or no.";;
+ esac
+ done
+}
+
+warn_major_update() {
+ nmv_suffix="New major versions generally involve breaking changes, and may not work in the same way as older versions."
+
+ if [ "${INTERACTIVE}" -eq 0 ]; then
+ warning "Would update to a new major version of Netdata. ${nmv_suffix}"
+ warning "To install the new major version anyway, either run the updater interactively, or include the new major version number in the NETDATA_ACCEPT_MAJOR_VERSIONS variable in ${UPDATER_CONFIG_PATH}."
+ fatal "Aborting update to new major version to avoid breaking things." U001B
+ else
+ warning "This update will install a new major version of Netdata. ${nmv_suffix}"
+ if confirm "Are you sure you want to update to a new major version of Netdata?"; then
+ notice "User accepted update to new major version of Netdata."
+ else
+ fatal "Aborting update to new major version at user request." U001C
+ fi
+ fi
+}
+
install_build_dependencies() {
bash="$(command -v bash 2> /dev/null)"
@@ -362,15 +433,42 @@ check_for_curl() {
_safe_download() {
url="${1}"
dest="${2}"
+ succeeded=0
+ checked=0
+
+ if echo "${url}" | grep -Eq "^file:///"; then
+ run cp "${url#file://}" "${dest}" || return 1
+ return 0
+ fi
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 $?
+ checked=1
+
+ if "${curl}" -fsSL --connect-timeout 10 --retry 3 "${url}" > "${dest}"; then
+ succeeded=1
+ else
+ rm -f "${dest}"
+ fi
+ fi
+
+ if [ "${succeeded}" -eq 0 ]; then
+ if command -v wget > /dev/null 2>&1; then
+ checked=1
+
+ if wget -T 15 -O - "${url}" > "${dest}"; then
+ succeeded=1
+ else
+ rm -f "${dest}"
+ fi
+ fi
+ fi
+
+ if [ "${succeeded}" -eq 1 ]; then
+ return 0
+ elif [ "${checked}" -eq 1 ]; then
+ return 1
else
return 255
fi
@@ -394,26 +492,58 @@ download() {
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
+ tag=$("${curl}" "${url}" -s -L -I -o /dev/null -w '%{url_effective}')
+ fi
+
+ if [ -z "${tag}" ]; then
+ if command -v wget >/dev/null 2>&1; then
+ tag=$(wget -S -O /dev/null "${url}" 2>&1 | grep Location)
+ fi
+ fi
+
+ if [ -z "${tag}" ]; then
fatal "I need curl or wget to proceed, but neither of them are available on this system." U0006
fi
- echo "${tag}" >"${dest}"
+ tag="$(echo "${tag}" | grep -Eom 1 '[^/]*/?$')"
+
+ # Fallback case for simpler local testing.
+ if echo "${tag}" | grep -Eq 'latest/?$'; then
+ if _safe_download "${url}/latest-version.txt" ./ndupdate-version.txt; then
+ tag="$(cat ./ndupdate-version.txt)"
+
+ if grep -q 'Not Found' ./ndupdate-version.txt; then
+ tag="latest"
+ fi
+
+ rm -f ./ndupdate-version.txt
+ else
+ tag="latest"
+ fi
+ fi
+
+ echo "${tag}"
}
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 '')"
+ python_version_check="
+from __future__ import print_function
+import sys, json
+
+try:
+ data = json.load(sys.stdin)
+except:
+ print('')
+else:
+ print(data[0]['commit']['committer']['date'] if isinstance(data, list) and data 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 '"')"
@@ -494,9 +624,9 @@ parse_version() {
get_latest_version() {
if [ "${RELEASE_CHANNEL}" = "stable" ]; then
- get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout
+ get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}"
else
- get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout
+ get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}"
fi
}
@@ -513,6 +643,7 @@ update_available() {
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}"
@@ -542,6 +673,27 @@ update_available() {
return 1
else
info "Update available"
+
+ if [ "${current_version}" -ne 0 ] && [ "${latest_version}" -ne 0 ]; then
+ current_major="$(${ndbinary} -v | cut -f 2 -d ' ' | cut -f 1 -d '.' | tr -d 'v')"
+ latest_major="$(echo "${latest_tag}" | cut -f 1 -d '.' | tr -d 'v')"
+
+ if [ "${current_major}" -ne "${latest_major}" ]; then
+ update_safe=0
+
+ for v in ${NETDATA_ACCEPT_MAJOR_VERSIONS}; do
+ if [ "${latest_major}" -eq "${v}" ]; then
+ update_safe=1
+ break
+ fi
+ done
+
+ if [ "${update_safe}" -eq 0 ]; then
+ warn_major_update
+ fi
+ fi
+ fi
+
return 0
fi
}
@@ -553,18 +705,23 @@ set_tarball_urls() {
if [ -e /opt/netdata/etc/netdata/.install-type ]; then
# shellcheck disable=SC1091
. /opt/netdata/etc/netdata/.install-type
+ [ -z "${PREBUILT_ARCH:-}" ] && PREBUILT_ARCH="$(uname -m)"
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)"
+ if [ -n "${NETDATA_OFFLINE_INSTALL_SOURCE}" ]; then
+ path="$(cd "${NETDATA_OFFLINE_INSTALL_SOURCE}" || exit 1; pwd)"
+ export NETDATA_TARBALL_URL="file://${path}/${filename}"
+ export NETDATA_TARBALL_CHECKSUM_URL="file://${path}/sha256sums.txt"
+ elif [ "$1" = "stable" ]; then
+ latest="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}")"
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)"
+ tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}")"
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
@@ -713,6 +870,15 @@ update_static() {
exit 0
}
+get_new_binpkg_major() {
+ case "${pm_cmd}" in
+ apt-get) apt-get --just-print upgrade 2>&1 | grep Inst | grep ' netdata ' | cut -f 3 -d ' ' | tr -d '[]' | cut -f 1 -d '.' ;;
+ yum) yum check-update netdata | grep -E '^netdata ' | awk '{print $2}' | cut -f 1 -d '.' ;;
+ dnf) dnf check-update netdata | grep -E '^netdata ' | awk '{print $2}' | cut -f 1 -d '.' ;;
+ zypper) zypper list-updates | grep '| netdata |' | cut -f 5 -d '|' | tr -d ' ' | cut -f 1 -d '.' ;;
+ esac
+}
+
update_binpkg() {
os_release_file=
if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then
@@ -823,6 +989,24 @@ update_binpkg() {
fi
done
+ current_major="$(netdata -v | cut -f 2 -d ' ' | cut -f 1 -d '.' | tr -d 'v')"
+ latest_major="$(get_new_binpkg_major)"
+
+ if [ -n "${latest_major}" ] && [ "${latest_major}" -ne "${current_major}" ]; then
+ update_safe=0
+
+ for v in ${NETDATA_ACCEPT_MAJOR_VERSIONS}; do
+ if [ "${latest_major}" -eq "${v}" ]; then
+ update_safe=1
+ break
+ fi
+ done
+
+ if [ "${update_safe}" -eq 0 ]; then
+ warn_major_update
+ fi
+ fi
+
# shellcheck disable=SC2086
env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F
@@ -901,11 +1085,14 @@ if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then
. "$(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
+UPDATER_CONFIG_PATH="$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
+if [ -r "${UPDATER_CONFIG_PATH}" ]; then
# shellcheck source=/dev/null
- . "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
+ . "${UPDATER_CONFIG_PATH}"
fi
+[ -z "${NETDATA_ACCEPT_MAJOR_VERSIONS}" ] && NETDATA_ACCEPT_MAJOR_VERSIONS="${NETDATA_DEFAULT_ACCEPT_MAJOR_VERSIONS}"
+
while [ -n "${1}" ]; do
case "${1}" in
--not-running-from-cron) NETDATA_NOT_RUNNING_FROM_CRON=1 ;;
@@ -913,6 +1100,10 @@ while [ -n "${1}" ]; do
--force-update) NETDATA_FORCE_UPDATE=1 ;;
--non-interactive) INTERACTIVE=0 ;;
--interactive) INTERACTIVE=1 ;;
+ --offline-install-source)
+ NETDATA_OFFLINE_INSTALL_SOURCE="${2}"
+ shift 1
+ ;;
--tmpdir-path)
NETDATA_TMPDIR_PATH="${2}"
shift 1
@@ -931,6 +1122,18 @@ while [ -n "${1}" ]; do
shift 1
done
+if [ -n "${NETDATA_OFFLINE_INSTALL_SOURCE}" ]; then
+ NETDATA_NO_UPDATER_SELF_UPDATE=1
+ NETDATA_UPDATER_JITTER=0
+ NETDATA_FORCE_UPDATE=1
+fi
+
+# If we seem to be running under anacron, act as if we’re not running from cron.
+# This is mostly to disable jitter, which should not be needed when run from anacron.
+if running_under_anacron; then
+ NETDATA_NOT_RUNNING_FROM_CRON="${NETDATA_NOT_RUNNING_FROM_CRON:-1}"
+fi
+
# 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)