From 112b5b91647c3dea45cc1c9bc364df526c8012f1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 26 Jan 2022 19:05:15 +0100 Subject: Merging upstream version 1.33.0. Signed-off-by: Daniel Baumann --- packaging/installer/kickstart.sh | 1495 ++++++++++++++++++++++++++++---------- 1 file changed, 1114 insertions(+), 381 deletions(-) (limited to 'packaging/installer/kickstart.sh') diff --git a/packaging/installer/kickstart.sh b/packaging/installer/kickstart.sh index 2fa762968..2fe627022 100755 --- a/packaging/installer/kickstart.sh +++ b/packaging/installer/kickstart.sh @@ -1,91 +1,105 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Run me with: -# -# bash <(curl -Ss https://my-netdata.io/kickstart.sh) -# -# or (to install all netdata dependencies): -# -# bash <(curl -Ss https://my-netdata.io/kickstart.sh) all -# -# Other options: -# --dont-wait do not prompt for user input -# --non-interactive do not prompt for user input -# --no-updates do not install script for daily updates -# --local-files set the full path of the desired tarball to run install with -# --allow-duplicate-install do not bail if we detect a duplicate install -# --reinstall if an existing install would be updated, reinstall instead -# --disable-telemetry opt out of anonymous statistics -# --claim-token specify a token to use for claiming the newly installed instance -# --claim-url specify a URL to use for claiming the newly installed isntance -# --claim-rooms specify a list of rooms to claim the newly installed instance to -# --claim-proxy specify a proxy to use while claiming the newly installed instance -# -# Environment options: +#!/bin/sh # -# TMPDIR specify where to save temporary files -# NETDATA_TARBALL_BASEURL set the base url for downloading the dist tarball -# -# This script will: -# -# 1. install all netdata compilation dependencies -# using the package manager of the system -# -# 2. download netdata nightly package to temporary directory -# -# 3. install netdata +# SPDX-License-Identifier: GPL-3.0-or-later -# shellcheck disable=SC2039,SC2059,SC2086 +# ====================================================================== +# Constants -# External files +KICKSTART_OPTIONS="${*}" PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/install-required-packages.sh" - -# Netdata Tarball Base URL (defaults to our Google Storage Bucket) -[ -z "$NETDATA_TARBALL_BASEURL" ] && NETDATA_TARBALL_BASEURL=https://storage.googleapis.com/netdata-nightlies - +PATH="${PATH}:/usr/local/bin:/usr/local/sbin" +REPOCONFIG_URL_PREFIX="https://packagecloud.io/netdata/netdata-repoconfig/packages" +REPOCONFIG_VERSION="1-1" TELEMETRY_URL="https://posthog.netdata.cloud/capture/" -TELEMETRY_API_KEY="${NETDATA_POSTHOG_API_KEY:-mqkwGT0JNFqO-zX2t0mW6Tec9yooaVu7xCBlXtHnt5Y}" -KICKSTART_OPTIONS="${*}" - -# --------------------------------------------------------------------------------------------------------------------- -# library functions copied from packaging/installer/functions.sh +START_TIME="$(date +%s)" + +# ====================================================================== +# Defaults for environment variables + +SELECTED_INSTALL_METHOD="none" +INSTALL_TYPE="unknown" +INSTALL_PREFIX="" +NETDATA_AUTO_UPDATES="1" +NETDATA_CLAIM_ONLY=0 +NETDATA_CLAIM_URL="https://app.netdata.cloud" +NETDATA_DISABLE_CLOUD=0 +NETDATA_ONLY_BUILD=0 +NETDATA_ONLY_NATIVE=0 +NETDATA_ONLY_STATIC=0 +NETDATA_REQUIRE_CLOUD=1 +RELEASE_CHANNEL="nightly" -setup_terminal() { - TPUT_RESET="" - TPUT_YELLOW="" - TPUT_WHITE="" - TPUT_BGRED="" - TPUT_BGGREEN="" - TPUT_BOLD="" - TPUT_DIM="" +NETDATA_DISABLE_TELEMETRY="${DO_NOT_TRACK:-0}" +NETDATA_TARBALL_BASEURL="${NETDATA_TARBALL_BASEURL:-https://storage.googleapis.com/netdata-nightlies}" +NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS:-""}" +TELEMETRY_API_KEY="${NETDATA_POSTHOG_API_KEY:-mqkwGT0JNFqO-zX2t0mW6Tec9yooaVu7xCBlXtHnt5Y}" - # Is stderr on the terminal? If not, then fail - test -t 2 || return 1 +if echo "${0}" | grep -q 'kickstart-static64'; then + NETDATA_ONLY_STATIC=1 +fi - if command -v tput > /dev/null 2>&1; then - if [ $(($(tput colors 2> /dev/null))) -ge 8 ]; then - # Enable colors - TPUT_RESET="$(tput sgr 0)" - TPUT_YELLOW="$(tput setaf 3)" - TPUT_WHITE="$(tput setaf 7)" - TPUT_BGRED="$(tput setab 1)" - TPUT_BGGREEN="$(tput setab 2)" - TPUT_BOLD="$(tput bold)" - TPUT_DIM="$(tput dim)" - fi - fi +if [ ! -t 1 ]; then + INTERACTIVE=0 +else + INTERACTIVE=1 +fi - return 0 +# ====================================================================== +# Usage info + +usage() { + cat << HEREDOC +USAGE: kickstart.sh [options] + where options include: + + --non-interactive Do not prompt for user input. (default: prompt if there is a controlling terminal) + --interactive Prompt for user input even if there is no controlling terminal. + --dont-start-it Do not start the agent by default (only for static installs or local builds) + --stable-channel Install a stable version instead of a nightly build (default: install a nightly build) + --nightly-channel Install a nightly build instead of a stable version + --no-updates Do not enable automatic updates (default: enable automatic updates) + --auto-update Enable automatic updates. + --disable-telemetry Opt-out of anonymous statistics. + --native-only Only install if native binary packages are available. + --static-only Only install if a static build is available. + --build-only Only install using a local build. + --reinstall Explicitly reinstall instead of updating any existing install. + --reinstall-even-if-unsafe Even try to reinstall if we don't think we can do so safely (implies --reinstall). + --disable-cloud Disable support for Netdata Cloud (default: detect) + --require-cloud Only install if Netdata Cloud can be enabled. Overrides --disable-cloud. + --install Specify an installation prefix for local builds (default: autodetect based on system type). + --claim-token Use a specified token for claiming to Netdata Cloud. + --claim-rooms When claiming, add the node to the specified rooms. + --claim-only If there is an existing install, only try to claim it, not update it. + --claim-* Specify other options for the claiming script. + --no-cleanup Don't do any cleanup steps. This is intended to help with debugging the installer. + +Additionally, this script may use the following environment variables: + + TMPDIR: Used to specify where to put temporary files. On most systems, the default we select + automatically should be fine. The user running the script needs to both be able to + write files to the temporary directory, and run files from that location. + ROOTCMD: Used to specify a command to use to run another command with root privileges if needed. By + default we try to use sudo, doas, or pkexec (in that order of preference), but if + you need special options for one of those to work, or have a different tool to do + the same thing on your system, you can specify it here. + DO_NOT_TRACK If set to a value other than 0, behave as if \`--disable-telemetry\` was specified. + NETDATA_INSTALLER_OPTIONS: Specifies extra options to pass to the static installer or local build script. + +HEREDOC } -setup_terminal || echo > /dev/null -# ----------------------------------------------------------------------------- +# ====================================================================== +# Telemetry functions + telemetry_event() { - if [ -n "${NETDATA_DISABLE_TELEMETRY}" ]; then + if [ "${NETDATA_DISABLE_TELEMETRY}" -eq 1 ]; then return 0 fi + now="$(date +%s)" + total_duration="$((now - START_TIME))" + if [ -e "/etc/os-release" ]; then eval "$(grep -E "^(NAME|ID|ID_LIKE|VERSION|VERSION_ID)=" < /etc/os-release | sed 's/^/HOST_/')" fi @@ -115,7 +129,7 @@ telemetry_event() { if [ -f /etc/machine-id ]; then DISTINCT_ID="$(cat /etc/machine-id)" - elif command -v uuidgen 2> /dev/null; then + elif command -v uuidgen > /dev/null 2>&1; then DISTINCT_ID="$(uuidgen)" else DISTINCT_ID="null" @@ -132,12 +146,14 @@ telemetry_event() { "\$pathname": "netdata-installer", "\$host": "installer.netdata.io", "\$ip": "127.0.0.1", - "script_variant": "legacy-kickstart", - "error_code": "${2}", - "error_message": "${3}", + "script_variant": "kickstart-ng", + "error_code": "${3}", + "error_message": "${2}", "install_options": "${KICKSTART_OPTIONS}", + "total_runtime": "${total_duration}", + "selected_install_method": "${SELECTED_INSTALL_METHOD}", "netdata_release_channel": "${RELEASE_CHANNEL:-null}", - "netdata_install_type": "kickstart-build", + "netdata_install_type": "${INSTALL_TYPE}", "host_os_name": "${HOST_NAME:-unknown}", "host_os_id": "${HOST_ID:-unknown}", "host_os_id_like": "${HOST_ID_LIKE:-unknown}", @@ -152,39 +168,102 @@ telemetry_event() { EOF )" -if [ -n "$(command -v curl 2> /dev/null)" ]; then - curl --silent -o /dev/null --write-out '%{http_code}' -X POST --max-time 2 --header "Content-Type: application/json" -d "${REQ_BODY}" "${TELEMETRY_URL}" -else - wget -q -O - --no-check-certificate \ - --server-response \ - --method POST \ - --timeout=1 \ - --header 'Content-Type: application/json' \ - --body-data "${REQ_BODY}" \ - "${TELEMETRY_URL}" 2>&1 | awk '/^ HTTP/{print $2}' -fi + if command -v curl > /dev/null 2>&1; then + curl --silent -o /dev/null -X POST --max-time 2 --header "Content-Type: application/json" -d "${REQ_BODY}" "${TELEMETRY_URL}" > /dev/null + elif command -v wget > /dev/null 2>&1; then + wget -q -O - --no-check-certificate \ + --method POST \ + --timeout=1 \ + --header 'Content-Type: application/json' \ + --body-data "${REQ_BODY}" \ + "${TELEMETRY_URL}" > /dev/null + fi +} + +trap_handler() { + code="${1}" + lineno="${2}" + + printf >&2 "%s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} ERROR ${TPUT_RESET} Installer exited unexpectedly (${code}-${lineno})" + + telemetry_event INSTALL_CRASH "Installer exited unexpectedly (${code}-${lineno})" "E${code}-${lineno}" + + trap - EXIT + + cleanup + + exit 1 +} + +trap 'trap_handler 0 ${LINENO}' EXIT +trap 'trap_handler 1 0' HUP +trap 'trap_handler 2 0' INT +trap 'trap_handler 3 0' QUIT +trap 'trap_handler 13 0' PIPE +trap 'trap_handler 15 0' TERM + +# ====================================================================== +# Utility functions + +setup_terminal() { + TPUT_RESET="" + TPUT_WHITE="" + TPUT_BGRED="" + TPUT_BGGREEN="" + TPUT_BOLD="" + TPUT_DIM="" + + # Is stderr on the terminal? If not, then fail + test -t 2 || return 1 + + if command -v tput > /dev/null 2>&1; then + if [ $(($(tput colors 2> /dev/null))) -ge 8 ]; then + # Enable colors + TPUT_RESET="$(tput sgr 0)" + TPUT_WHITE="$(tput setaf 7)" + TPUT_BGRED="$(tput setab 1)" + TPUT_BGGREEN="$(tput setab 2)" + TPUT_BOLD="$(tput bold)" + TPUT_DIM="$(tput dim)" + fi + fi + + echo "${TPUT_RESET}" + + return 0 +} + +cleanup() { + if [ -z "${NO_CLEANUP}" ]; then + ${ROOTCMD} rm -rf "${tmpdir}" + fi } fatal() { - printf >&2 "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} ABORTED ${TPUT_RESET} ${1} \n\n" + printf >&2 "%s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} ABORTED ${TPUT_RESET} ${1}" telemetry_event "INSTALL_FAILED" "${1}" "${2}" + cleanup + trap - EXIT exit 1 } run_ok() { - printf >&2 "${TPUT_BGGREEN}${TPUT_WHITE}${TPUT_BOLD} OK ${TPUT_RESET} \n\n" + printf >&2 "%s\n\n" "${TPUT_BGGREEN}${TPUT_WHITE}${TPUT_BOLD} OK ${TPUT_RESET}" } run_failed() { - printf >&2 "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} FAILED ${TPUT_RESET} \n\n" + printf >&2 "%s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} FAILED ${TPUT_RESET}" } ESCAPED_PRINT_METHOD= +# shellcheck disable=SC3050 if printf "%q " test > /dev/null 2>&1; then ESCAPED_PRINT_METHOD="printfq" fi + escaped_print() { if [ "${ESCAPED_PRINT_METHOD}" = "printfq" ]; then + # shellcheck disable=SC3050 printf "%q " "${@}" else printf "%s" "${*}" @@ -193,14 +272,15 @@ escaped_print() { } progress() { - echo >&2 " --- ${TPUT_DIM}${TPUT_BOLD}${*}${TPUT_RESET} --- " + echo >&2 " --- ${TPUT_BOLD}${*}${TPUT_RESET} --- " } run_logfile="/dev/null" run() { - local user="${USER--}" dir="${PWD}" info info_console + user="${USER--}" + dir="${PWD}" - if [ "${UID}" = "0" ]; then + if [ "$(id -u)" = "0" ]; then info="[root ${dir}]# " info_console="[${TPUT_DIM}${dir}${TPUT_RESET}]# " else @@ -209,51 +289,44 @@ run() { fi { - printf "${info}" + printf "%s" "${info}" escaped_print "${@}" printf " ... " } >> "${run_logfile}" - printf >&2 "${info_console}${TPUT_BOLD}${TPUT_YELLOW}" + printf >&2 "%s" "${info_console}${TPUT_BOLD}" escaped_print >&2 "${@}" - printf >&2 "${TPUT_RESET}" + printf >&2 "%s\n" "${TPUT_RESET}" "${@}" - local ret=$? + ret=$? if [ ${ret} -ne 0 ]; then run_failed - printf >> "${run_logfile}" "FAILED with exit code ${ret}\n" + printf "%s\n" "FAILED with exit code ${ret}" >> "${run_logfile}" else run_ok - printf >> "${run_logfile}" "OK\n" + printf "OK\n" >> "${run_logfile}" fi return ${ret} } warning() { - printf >&2 "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} WARNING ${TPUT_RESET} ${*} \n\n" - if [ "${INTERACTIVE}" = "0" ]; then - fatal "Stopping due to non-interactive mode. Fix the issue or retry installation in an interactive mode." F0001 - else - read -r -p "Press ENTER to attempt netdata installation > " - progress "OK, let's give it a try..." - fi + printf >&2 "%s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} WARNING ${TPUT_RESET} ${*}" } _cannot_use_tmpdir() { - local testfile ret testfile="$(TMPDIR="${1}" mktemp -q -t netdata-test.XXXXXXXXXX)" ret=0 - if [ -z "${testfile}" ] ; then + 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 + if printf '#!/bin/sh\necho SUCCESS\n' > "${testfile}"; then + if chmod +x "${testfile}"; then + if [ "$("${testfile}")" = "SUCCESS" ]; then ret=1 fi fi @@ -264,12 +337,10 @@ _cannot_use_tmpdir() { } create_tmp_directory() { - 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 temporary directory. Please set \$TMPDIR to a path that is both writable and allows execution of files and try again." - exit 1 + 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." F0400 else TMPDIR="${PWD}" fi @@ -285,346 +356,771 @@ download() { url="${1}" dest="${2}" if command -v curl > /dev/null 2>&1; then - run curl -q -sSL --connect-timeout 10 --retry 3 --output "${dest}" "${url}" || fatal "Cannot download ${url}" F0002 + run curl --fail -q -sSL --connect-timeout 10 --retry 3 --output "${dest}" "${url}" || return 1 elif command -v wget > /dev/null 2>&1; then - run wget -T 15 -O "${dest}" "${url}" || fatal "Cannot download ${url}" F0002 + run wget -T 15 -O "${dest}" "${url}" || return 1 else - fatal "I need curl or wget to proceed, but neither is available on this system." F0003 + fatal "I need curl or wget to proceed, but neither of them are available on this system." F0003 fi } -set_tarball_urls() { - if [ -n "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ]; then - progress "Not fetching remote tarballs, local override was given" - return - fi +get_redirect() { + url="${1}" - 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.tar.gz" - export NETDATA_TARBALL_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/$latest/sha256sums.txt" + if command -v curl > /dev/null 2>&1; then + run sh -c "curl ${url} -s -L -I -o /dev/null -w '%{url_effective}' | grep -o '[^/]*$'" || return 1 + elif command -v wget > /dev/null 2>&1; then + run sh -c "wget --max-redirect=0 ${url} 2>&1 | grep Location | cut -d ' ' -f2 | grep -o '[^/]*$'" || return 1 else - export NETDATA_TARBALL_URL="$NETDATA_TARBALL_BASEURL/netdata-latest.tar.gz" - export NETDATA_TARBALL_CHECKSUM_URL="$NETDATA_TARBALL_BASEURL/sha256sums.txt" + fatal "I need curl or wget to proceed, but neither of them are available on this system." F0003 fi } -detect_bash4() { - bash="${1}" - if [ -z "${BASH_VERSION}" ]; then - # we don't run under bash - if [ -n "${bash}" ] && [ -x "${bash}" ]; then - # shellcheck disable=SC2016 - BASH_MAJOR_VERSION=$(${bash} -c 'echo "${BASH_VERSINFO[0]}"') - fi +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 using 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 - # we run under bash - BASH_MAJOR_VERSION="${BASH_VERSINFO[0]}" + fatal "I could not find a suitable checksum binary to use" F0004 fi +} - if [ -z "${BASH_MAJOR_VERSION}" ]; then - echo >&2 "No BASH is available on this system" - return 1 - elif [ $((BASH_MAJOR_VERSION)) -lt 4 ]; then - echo >&2 "No BASH v4+ is available on this system (installed bash is v${BASH_MAJOR_VERSION})" - return 1 +get_system_info() { + case "$(uname -s)" in + Linux) + SYSTYPE="Linux" + + 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 ..." F0401 + fi + + # shellcheck disable=SC1090 + . "${os_release_file}" + + DISTRO="${ID}" + SYSVERSION="${VERSION_ID}" + SYSCODENAME="${VERSION_CODENAME}" + SYSARCH="$(uname -m)" + + supported_compat_names="debian ubuntu centos fedora opensuse" + + if str_in_list "${DISTRO}" "${supported_compat_names}"; then + DISTRO_COMPAT_NAME="${DISTRO}" + else + case "${DISTRO}" in + opensuse-leap) + DISTRO_COMPAT_NAME="opensuse" + ;; + rhel) + DISTRO_COMPAT_NAME="centos" + ;; + *) + DISTRO_COMPAT_NAME="unknown" + ;; + esac + fi + ;; + Darwin) + SYSTYPE="Darwin" + SYSVERSION="$(sw_vers -buildVersion)" + SYSARCH="$(uname -m)" + ;; + FreeBSD) + SYSTYPE="FreeBSD" + SYSVERSION="$(uname -K)" + SYSARCH="$(uname -m)" + ;; + *) + fatal "Unsupported system type detected. Netdata cannot be installed on this system using this script." F0200 + ;; + esac +} + +str_in_list() { + printf "%s\n" "${2}" | tr ' ' "\n" | grep -qE "^${1}\$" + return $? +} + +confirm_root_support() { + if [ "$(id -u)" -ne "0" ]; then + if [ -z "${ROOTCMD}" ] && command -v sudo > /dev/null; then + ROOTCMD="sudo" + fi + + if [ -z "${ROOTCMD}" ] && command -v doas > /dev/null; then + ROOTCMD="doas" + fi + + if [ -z "${ROOTCMD}" ] && command -v pkexec > /dev/null; then + ROOTCMD="pkexec" + fi + + if [ -z "${ROOTCMD}" ]; then + fatal "We need root privileges to continue, but cannot find a way to gain them. Either re-run this script as root, or set \$ROOTCMD to a command that can be used to gain root privileges" F0201 + fi fi - return 0 } -dependencies() { - SYSTEM="$(uname -s 2> /dev/null || uname -v)" - OS="$(uname -o 2> /dev/null || uname -rs)" - MACHINE="$(uname -m 2> /dev/null)" +confirm() { + prompt="${1} [y/n]" - echo "System : ${SYSTEM}" - echo "Operating System : ${OS}" - echo "Machine : ${MACHINE}" - echo "BASH major version: ${BASH_MAJOR_VERSION}" + while true; do + echo "${prompt}" + read -r yn - bash="$(command -v bash 2> /dev/null)" - if ! detect_bash4 "${bash}"; then - warning "Cannot detect packages to be installed in this system, without BASH v4+." + case "$yn" in + [Yy]*) return 0;; + [Nn]*) return 1;; + *) echo "Please answer yes or no.";; + esac + done +} + +# ====================================================================== +# Existing install handling code + +update() { + updater="${ndprefix}/usr/libexec/netdata/netdata-updater.sh" + + if [ -x "${updater}" ]; then + if run ${ROOTCMD} "${updater}" --not-running-from-cron; then + progress "Updated existing install at ${ndprefix}" + return 0 + else + fatal "Failed to update existing Netdata install at ${ndprefix}" F0100 + fi else - progress "Fetching script to detect required packages..." - if [ -n "${NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT}" ]; then - if [ -f "${NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT}" ]; then - run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT}" "${ndtmpdir}/install-required-packages.sh" - else - fatal "Invalid given dependency file, please check your --local-files parameter options and try again" F1001 - fi + return 1 + fi +} + +handle_existing_install() { + if pkg_installed netdata; then + ndprefix="/" + else + if [ -n "${INSTALL_PREFIX}" ]; then + searchpath="${INSTALL_PREFIX}/bin:${INSTALL_PREFIX}/sbin:${INSTALL_PREFIX}/usr/bin:${INSTALL_PREFIX}/usr/sbin:${PATH}" + searchpath="${INSTALL_PREFIX}/netdata/bin:${INSTALL_PREFIX}/netdata/sbin:${INSTALL_PREFIX}/netdata/usr/bin:${INSTALL_PREFIX}/netdata/usr/sbin:${searchpath}" else - download "${PACKAGES_SCRIPT}" "${ndtmpdir}/install-required-packages.sh" + searchpath="${PATH}" + fi + + ndpath="$(PATH="${searchpath}" command -v netdata 2>/dev/null)" + + if [ -z "$ndpath" ] && [ -x /opt/netdata/bin/netdata ]; then + ndpath="/opt/netdata/bin/netdata" + fi + + if [ -n "${ndpath}" ]; then + ndprefix="$(dirname "$(dirname "${ndpath}")")" + fi + + if echo "${ndprefix}" | grep -Eq '/usr$'; then + ndprefix="$(dirname "${ndprefix}")" fi + fi - if [ ! -s "${ndtmpdir}/install-required-packages.sh" ]; then - warning "Downloaded dependency installation script is empty." + if [ -n "${ndprefix}" ]; then + typefile="${ndprefix}/etc/netdata/.install-type" + if [ -r "${typefile}" ]; then + ${ROOTCMD} sh -c "cat \"${typefile}\" > \"${tmpdir}/install-type\"" + # shellcheck disable=SC1091 + . "${tmpdir}/install-type" else - progress "Running downloaded script to detect required packages..." - run ${sudo} "${bash}" "${ndtmpdir}/install-required-packages.sh" ${PACKAGES_INSTALLER_OPTIONS} - # shellcheck disable=SC2181 - if [ $? -ne 0 ]; then - warning "It failed to install all the required packages, but installation might still be possible." - fi + INSTALL_TYPE="unknown" fi + fi + if [ -z "${ndprefix}" ]; then + progress "No existing installations of netdata found, assuming this is a fresh install." + return 0 fi + + case "${INSTALL_TYPE}" in + kickstart-*|legacy-*|binpkg-*|manual-static|unknown) + if [ "${INSTALL_TYPE}" = "unknown" ]; then + warning "Found an existing netdata install at ${ndprefix}, but could not determine the install type." + else + progress "Found an existing netdata install at ${ndprefix}, with installation type '${INSTALL_TYPE}'." + fi + + if [ -n "${NETDATA_REINSTALL}" ] || [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then + progress "Found an existing netdata install at ${ndprefix}, but user requested reinstall, continuing." + + case "${INSTALL_TYPE}" in + binpkg-*) NETDATA_ONLY_NATIVE=1 ;; + *-build) NETDATA_ONLY_BUILD=1 ;; + *-static) NETDATA_ONLY_STATIC=1 ;; + *) + if [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then + warning "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, but the user has requested we proceed." + elif [ "${INTERACTIVE}" -eq 0 ]; then + fatal "User requested reinstall, but we cannot safely reinstall over top of a ${INSTALL_TYPE} installation, exiting." F0104 + else + if confirm "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, do you want to continue?"; then + progress "OK, continuing." + else + fatal "Cancelling reinstallation at user request." F0105 + fi + fi + ;; + esac + + return 0 + fi + + ret=0 + + if [ "${NETDATA_CLAIM_ONLY}" -eq 0 ] && echo "${INSTALL_TYPE}" | grep -vq "binpkg-*"; then + if ! update; then + warning "Unable to find usable updater script, not updating existing install at ${ndprefix}." + fi + else + warning "Not updating existing install at ${ndprefix}." + fi + + if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then + progress "Attempting to claim existing install at ${ndprefix}." + INSTALL_PREFIX="${ndprefix}" + claim + ret=$? + elif [ "${NETDATA_CLAIM_ONLY}" -eq 1 ]; then + fatal "User asked to claim, but did not proide a claiming token." F0202 + else + progress "Not attempting to claim existing install at ${ndprefix} (no claiming token provided)." + fi + + cleanup + trap - EXIT + exit $ret + ;; + oci) + fatal "This is an OCI container, use the regular image lifecycle management commands in your container instead of this script for managing it." F0203 + ;; + *) + if [ -n "${NETDATA_REINSTALL}" ] || [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then + if [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then + warning "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, but the user has requested we proceed." + elif [ "${INTERACTIVE}" -eq 0 ]; then + fatal "User requested reinstall, but we cannot safely reinstall over top of a ${INSTALL_TYPE} installation, exiting." F0104 + else + if confirm "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, do you want to continue?"; then + progress "OK, continuing." + else + fatal "Cancelling reinstallation at user request." F0105 + fi + fi + else + fatal "Found an existing netdata install at ${ndprefix}, but the install type is '${INSTALL_TYPE}', which is not supported, refusing to proceed." F0103 + fi + ;; + esac } -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 sha256sum > /dev/null 2>&1; then - sha256sum "$@" - elif command -v shasum > /dev/null 2>&1; then - shasum -a 256 "$@" +soft_disable_cloud() { + cloud_prefix="${INSTALL_PREFIX}/var/lib/netdata/cloud.d" + + run ${ROOTCMD} mkdir -p "${cloud_prefix}" + + cat > "${tmpdir}/cloud.conf" << EOF +[global] + enabled = no +EOF + + run ${ROOTCMD} cp "${tmpdir}/cloud.conf" "${cloud_prefix}/cloud.conf" + + if [ -z "${NETDATA_NO_START}" ]; then + case "${SYSTYPE}" in + Darwin) run ${ROOTCMD} launchctl kickstart -k com.github.netdata ;; + FreeBSD) run ${ROOTCMD} service netdata restart ;; + Linux) + initpath="$(${ROOTCMD} readlink /proc/1/exe)" + + if command -v service > /dev/null 2>&1; then + run ${ROOTCMD} service netdata restart + elif command -v rc-service > /dev/null 2>&1; then + run ${ROOTCMD} rc-service netdata restart + elif [ "$(basename "${initpath}" 2> /dev/null)" = "systemd" ]; then + run ${ROOTCMD} systemctl restart netdata + elif [ -f /etc/init.d/netdata ]; then + run ${ROOTCMD} /etc/init.d/netdata restart + fi + ;; + esac + fi +} + +confirm_install_prefix() { + if [ -n "${INSTALL_PREFIX}" ] && [ "${NETDATA_ONLY_BUILD}" -ne 1 ]; then + fatal "The \`--install\` option is only supported together with the \`--only-build\` option." F0204 + fi + + if [ -n "${INSTALL_PREFIX}" ]; then + NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --install ${INSTALL_PREFIX}" else - fatal "I could not find a suitable checksum binary to use" F0004 + case "${SYSTYPE}" in + Darwin) + INSTALL_PREFIX="/usr/local/netdata" + NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --install-no-prefix ${INSTALL_PREFIX}" + ;; + FreeBSD) + INSTALL_PREFIX="/usr/local" + NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --install-no-prefix ${INSTALL_PREFIX}" + ;; + esac + fi +} + +# ====================================================================== +# Claiming support code + +check_claim_opts() { +# shellcheck disable=SC2235,SC2030 + if [ -z "${NETDATA_CLAIM_TOKEN}" ] && [ -n "${NETDATA_CLAIM_ROOMS}" ]; then + fatal "Invalid claiming options, claim rooms may only be specified when a token and URL are specified." F0204 + elif [ -z "${NETDATA_CLAIM_TOKEN}" ] && [ -n "${NETDATA_CLAIM_EXTRA}" ]; then + fatal "Invalid claiming options, a claiming token must be specified." F0204 + elif [ "${NETDATA_DISABLE_CLOUD}" -eq 1 ] && [ -n "${NETDATA_CLAIM_TOKEN}" ]; then + fatal "Cloud explicitly disabled, but automatic claiming requested. Either enable Netdata Cloud, or remove the --claim-* options." F0204 + fi +} + +is_netdata_running() { + if command -v pgrep > /dev/null 2>&1; then + if pgrep netdata; then + return 0 + else + return 1 + fi + else + if [ -z "${INSTALL_PREFIX}" ]; then + NETDATACLI_PATH=/usr/sbin/netdatacli + elif [ "${INSTALL_PREFIX}" = "/opt/netdata" ]; then + NETDATACLI_PATH="/opt/netdata/bin/netdatacli" + else + NETDATACLI_PATH="${INSTALL_PREFIX}/netdata/usr/sbin/netdatacli" + fi + + if "${NETDATACLI_PATH}" ping > /dev/null 2>&1; then + return 0 + else + return 1 + fi fi } claim() { progress "Attempting to claim agent to ${NETDATA_CLAIM_URL}" - if [ -z "${NETDATA_PREFIX}" ] ; then + if [ -z "${INSTALL_PREFIX}" ] || [ "${INSTALL_PREFIX}" = "/" ]; then NETDATA_CLAIM_PATH=/usr/sbin/netdata-claim.sh + elif [ "${INSTALL_PREFIX}" = "/opt/netdata" ]; then + NETDATA_CLAIM_PATH="/opt/netdata/bin/netdata-claim.sh" else - NETDATA_CLAIM_PATH="${NETDATA_PREFIX}/netdata/usr/sbin/netdata-claim.sh" + NETDATA_CLAIM_PATH="${INSTALL_PREFIX}/netdata/usr/sbin/netdata-claim.sh" + fi + + if ! is_netdata_running; then + NETDATA_CLAIM_EXTRA="${NETDATA_CLAIM_EXTRA} -daemon-not-running" fi - if ${sudo} "${NETDATA_CLAIM_PATH}" -token=${NETDATA_CLAIM_TOKEN} -rooms=${NETDATA_CLAIM_ROOMS} -url=${NETDATA_CLAIM_URL} ${NETDATA_CLAIM_EXTRA}; then + # shellcheck disable=SC2086 + if ${ROOTCMD} "${NETDATA_CLAIM_PATH}" -token="${NETDATA_CLAIM_TOKEN}" -rooms="${NETDATA_CLAIM_ROOMS}" -url="${NETDATA_CLAIM_URL}" ${NETDATA_CLAIM_EXTRA}; then progress "Successfully claimed node" - return 0 else - run_failed "Unable to claim node, you must do so manually." - return 1 + warning "Unable to claim node, you must do so manually." + if [ -z "${NETDATA_NEW_INSTALL}" ]; then + cleanup + trap - EXIT + exit 1 + fi fi } -# --------------------------------------------------------------------------------------------------------------------- -umask 022 - -sudo="" -[ -z "${UID}" ] && UID="$(id -u)" -[ "${UID}" -ne "0" ] && sudo="sudo" -export PATH="${PATH}:/usr/local/bin:/usr/local/sbin" +# ====================================================================== +# Native package install code. - -# --------------------------------------------------------------------------------------------------------------------- - -INTERACTIVE=1 -PACKAGES_INSTALLER_OPTIONS="netdata" -NETDATA_INSTALLER_OPTIONS="" -NETDATA_UPDATES="--auto-update" -RELEASE_CHANNEL="nightly" -while [ -n "${1}" ]; do - case "${1}" in - "all") PACKAGES_INSTALLER_OPTIONS="netdata-all" ;; - "--dont-wait") INTERACTIVE=0 ;; - "--non-interactive") INTERACTIVE=0 ;; - "--no-updates") NETDATA_UPDATES= ;; - "--stable-channel") - RELEASE_CHANNEL="stable" - NETDATA_INSTALLER_OPTIONS="$NETDATA_INSTALLER_OPTIONS --stable-channel" - ;; - "--allow-duplicate-install") NETDATA_ALLOW_DUPLICATE_INSTALL=1 ;; - "--reinstall") NETDATA_REINSTALL=1 ;; - "--claim-token") - NETDATA_CLAIM_TOKEN="${2}" - shift 1 - ;; - "--claim-rooms") - NETDATA_CLAIM_ROOMS="${2}" - shift 1 +# Check for an already installed package with a given name. +pkg_installed() { + case "${DISTRO_COMPAT_NAME}" in + debian|ubuntu) + dpkg -l "${1}" > /dev/null 2>&1 + return $? ;; - "--claim-url") - NETDATA_CLAIM_URL="${2}" - shift 1 + centos|fedora|opensuse) + rpm -q "${1}" > /dev/null 2>&1 + return $? ;; - "--claim-proxy") - NETDATA_CLAIM_EXTRA="${NETDATA_CLAIM_EXTRA} -proxy ${2}" - shift 1 + *) + return 1 ;; - "--dont-start-it") - NETDATA_CLAIM_EXTRA="${NETDATA_CLAIM_EXTRA} -daemon-not-running" - NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --dont-start-it" + esac +} + +# Check for the existence of a usable netdata package in the repo. +netdata_avail_check() { + case "${DISTRO_COMPAT_NAME}" in + debian|ubuntu) + env DEBIAN_FRONTEND=noninteractive apt-cache policy netdata | grep -q packagecloud.io/netdata/netdata; + return $? ;; - "--install") - NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --install ${2}" - NETDATA_PREFIX="${2}" - shift 1 + centos|fedora) + # shellcheck disable=SC2086 + ${pm_cmd} search -v netdata | grep -qE 'Repo *: netdata(-edge)?$' + return $? ;; - "--disable-cloud") - NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --disable-cloud" - NETDATA_DISABLE_CLOUD=1 + opensuse) + zypper packages -r "$(zypper repos | grep -E 'netdata |netdata-edge ' | cut -f 1 -d '|' | tr -d ' ')" | grep -E 'netdata ' + return $? ;; - "--disable-telemetry") - NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --disable-telemetry" - NETDATA_DISABLE_TELEMETRY=1 + *) + return 1 ;; - "--local-files") - if [ -z "${2}" ]; then - fatal "Missing netdata: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" F1002 - fi + esac +} - export NETDATA_LOCAL_TARBALL_OVERRIDE="${2}" +# Check for any distro-specific dependencies we know we need. +check_special_native_deps() { + if [ "${DISTRO_COMPAT_NAME}" = "centos" ] && [ "${SYSVERSION}" = "7" ]; then + progress "Checking for libuv availability." + # shellcheck disable=SC2086 + if ${pm_cmd} search ${interactive_opts} -v libuv | grep -q "No matches found"; then + progress "libv not found, checking for EPEL availability." + # shellcheck disable=SC2086 + if ${pm_cmd} search ${interactive_opts} -v epel-release | grep -q "No matches found"; then + warning "Unable to find a suitable source for libuv, cannot install on this system." + return 1 + else + progress "EPEL is available, attempting to install so that required dependencies are available." - if [ -z "${3}" ]; then - fatal "Missing checksum file: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" F1003 + # shellcheck disable=SC2086 + if ! run ${ROOTCMD} env ${env} ${pm_cmd} install ${pkg_install_opts} epel-release; then + warning "Failed to install EPEL." + return 1 + fi fi + else + return 0 + fi + fi +} - export NETDATA_LOCAL_TARBALL_OVERRIDE_CHECKSUM="${3}" - - if [ -z "${4}" ]; then - fatal "Missing go.d tarball: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" F1004 - fi +try_package_install() { + if [ -z "${DISTRO}" ]; then + warning "Unable to determine Linux distribution for native packages." + return 1 + fi - export NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN="${4}" + progress "Attempting to install using native packages..." - if [ -z "${5}" ]; then - fatal "Missing go.d config tarball: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" F1005 - fi + if [ "${RELEASE_CHANNEL}" = "nightly" ]; then + release="-edge" + else + release="" + fi - export NETDATA_LOCAL_TARBALL_OVERRIDE_GO_PLUGIN_CONFIG="${5}" + if [ "${INTERACTIVE}" = "0" ]; then + interactive_opts="-y" + env="DEBIAN_FRONTEND=noninteractive" + else + interactive_opts="" + env="" + fi - if [ -z "${6}" ]; then - fatal "Missing dependencies management scriptlet: Option --local-files requires extra information. The desired tarball for netdata, the checksum, the go.d plugin tarball , the go.d plugin config tarball and the dependency management script, in this particular order" F1006 + case "${DISTRO_COMPAT_NAME}" in + debian) + needs_early_refresh=1 + pm_cmd="apt-get" + repo_subcmd="update" + repo_prefix="debian/${SYSCODENAME}" + pkg_type="deb" + pkg_suffix="_all" + pkg_vsep="_" + pkg_install_opts="${interactive_opts}" + repo_update_opts="${interactive_opts}" + uninstall_subcmd="purge" + INSTALL_TYPE="binpkg-deb" + ;; + ubuntu) + needs_early_refresh=1 + pm_cmd="apt-get" + repo_subcmd="update" + repo_prefix="ubuntu/${SYSCODENAME}" + pkg_type="deb" + pkg_suffix="_all" + pkg_vsep="_" + pkg_install_opts="${interactive_opts}" + repo_update_opts="${interactive_opts}" + uninstall_subcmd="purge" + INSTALL_TYPE="binpkg-deb" + ;; + centos) + if command -v dnf > /dev/null; then + pm_cmd="dnf" + repo_subcmd="makecache" + else + pm_cmd="yum" fi - - export NETDATA_LOCAL_TARBALL_OVERRIDE_DEPS_SCRIPT="${6}" - shift 5 + repo_prefix="el/${SYSVERSION}" + pkg_type="rpm" + pkg_suffix=".noarch" + pkg_vsep="-" + pkg_install_opts="${interactive_opts}" + repo_update_opts="${interactive_opts}" + uninstall_subcmd="remove" + INSTALL_TYPE="binpkg-rpm" + ;; + fedora) + if command -v dnf > /dev/null; then + pm_cmd="dnf" + repo_subcmd="makecache" + else + pm_cmd="yum" + fi + repo_prefix="fedora/${SYSVERSION}" + pkg_type="rpm" + pkg_suffix=".noarch" + pkg_vsep="-" + pkg_install_opts="${interactive_opts}" + repo_update_opts="${interactive_opts}" + uninstall_subcmd="remove" + INSTALL_TYPE="binpkg-rpm" + ;; + opensuse) + pm_cmd="zypper" + repo_subcmd="--gpg-auto-import-keys refresh" + repo_prefix="opensuse/${SYSVERSION}" + pkg_type="rpm" + pkg_suffix=".noarch" + pkg_vsep="-" + pkg_install_opts="${interactive_opts} --allow-unsigned-rpm" + repo_update_opts="" + uninstall_subcmd="remove" + INSTALL_TYPE="binpkg-rpm" ;; *) - NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} ${1}" + warning "We do not provide native packages for ${DISTRO}." + return 2 ;; esac - shift 1 -done -if [ "${INTERACTIVE}" = "0" ]; then - PACKAGES_INSTALLER_OPTIONS="--dont-wait --non-interactive ${PACKAGES_INSTALLER_OPTIONS}" - NETDATA_INSTALLER_OPTIONS="$NETDATA_INSTALLER_OPTIONS --dont-wait" -fi + repoconfig_name="netdata-repo${release}" + repoconfig_file="${repoconfig_name}${pkg_vsep}${REPOCONFIG_VERSION}${pkg_suffix}.${pkg_type}" + repoconfig_url="${REPOCONFIG_URL_PREFIX}/${repo_prefix}/${repoconfig_file}/download.${pkg_type}" + + if ! pkg_installed "${repoconfig_name}"; then + progress "Downloading repository configuration package." + if ! download "${repoconfig_url}" "${tmpdir}/${repoconfig_file}"; then + warning "Failed to download repository configuration package." + return 2 + fi + + if [ -n "${needs_early_refresh}" ]; then + progress "Updating repository metadata." + # shellcheck disable=SC2086 + if ! run ${ROOTCMD} env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts}; then + warning "Failed to refresh repository metadata." + return 2 + fi + fi -if [ -n "${NETDATA_DISABLE_CLOUD}" ]; then - if [ -n "${NETDATA_CLAIM_TOKEN}" ] || [ -n "${NETDATA_CLAIM_ROOMS}" ] || [ -n "${NETDATA_CLAIM_URL}" ]; then - run_failed "Cloud explicitly disabled but automatic claiming requested." - run_failed "Either enable Netdata Cloud, or remove the --claim-* options." - exit 1 + progress "Installing repository configuration package." + # shellcheck disable=SC2086 + if ! run ${ROOTCMD} env ${env} ${pm_cmd} install ${pkg_install_opts} "${tmpdir}/${repoconfig_file}"; then + warning "Failed to install repository configuration package." + return 2 + fi + + if [ -n "${repo_subcmd}" ]; then + progress "Updating repository metadata." + # shellcheck disable=SC2086 + if ! run ${ROOTCMD} env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts}; then + fatal "Failed to update repository metadata." F0205 + fi + fi + else + progress "Repository configuration is already present, attempting to install netdata." fi -fi -# shellcheck disable=SC2235,SC2030,SC2031 -if ( [ -z "${NETDATA_CLAIM_TOKEN}" ] && [ -n "${NETDATA_CLAIM_URL}" ] ) || ( [ -n "${NETDATA_CLAIM_TOKEN}" ] && [ -z "${NETDATA_CLAIM_URL}" ] ); then - run_failed "Invalid claiming options, both a claiming token and URL must be specified." - exit 1 -elif [ -z "${NETDATA_CLAIM_TOKEN}" ] && [ -n "${NETDATA_CLAIM_ROOMS}" ]; then - run_failed "Invalid claiming options, claim rooms may only be specified when a token and URL are specified." - exit 1 -fi + if ! check_special_native_deps; then + warning "Could not find secondary dependencies ${DISTRO} on ${SYSARCH}." + if [ -z "${NO_CLEANUP}" ]; then + progress "Attempting to uninstall repository configuration package." + # shellcheck disable=SC2086 + run ${ROOTCMD} env ${env} ${pm_cmd} ${uninstall_subcmd} ${pkg_install_opts} "${repoconfig_name}" + fi + return 2 + fi -# --------------------------------------------------------------------------------------------------------------------- -# look for an existing install and try to update that instead if it exists + progress "Checking for usable Netdata package." + if ! netdata_avail_check "${DISTRO_COMPAT_NAME}"; then + warning "Could not find a usable native package for ${DISTRO} on ${SYSARCH}." + if [ -z "${NO_CLEANUP}" ]; then + progress "Attempting to uninstall repository configuration package." + # shellcheck disable=SC2086 + run ${ROOTCMD} env ${env} ${pm_cmd} ${uninstall_subcmd} ${pkg_install_opts} "${repoconfig_name}" + fi + return 2 + fi -ndpath="$(command -v netdata 2>/dev/null)" -if [ -z "$ndpath" ] && [ -x /opt/netdata/bin/netdata ] ; then - ndpath="/opt/netdata/bin/netdata" -fi + if [ "${NETDATA_DISABLE_TELEMETRY}" -eq 1 ]; then + run ${ROOTCMD} mkdir -p "/etc/netdata" + run ${ROOTCMD} touch "/etc/netdata/.opt-out-from-anonymous-statistics" + fi -if [ -n "$ndpath" ] ; then - ndprefix="$(dirname "$(dirname "${ndpath}")")" + progress "Installing Netdata package." + # shellcheck disable=SC2086 + if ! run ${ROOTCMD} env ${env} ${pm_cmd} install ${pkg_install_opts} netdata; then + warning "Failed to install Netdata package." + if [ -z "${NO_CLEANUP}" ]; then + progress "Attempting to uninstall repository configuration package." + # shellcheck disable=SC2086 + run ${ROOTCMD} env ${env} ${pm_cmd} ${uninstall_subcmd} ${pkg_install_opts} "${repoconfig_name}" + fi + return 2 + fi +} - if [ "${ndprefix}" = /usr ] ; then - ndprefix="/" +# ====================================================================== +# Static build install code + +set_static_archive_urls() { + if [ "${RELEASE_CHANNEL}" = "stable" ]; then + latest="$(get_redirect "https://github.com/netdata/netdata/releases/latest")" + export NETDATA_STATIC_ARCHIVE_URL="https://github.com/netdata/netdata/releases/download/${latest}/netdata-${SYSARCH}-latest.gz.run" + export NETDATA_STATIC_ARCHIVE_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/${latest}/sha256sums.txt" + else + export NETDATA_STATIC_ARCHIVE_URL="${NETDATA_TARBALL_BASEURL}/netdata-${SYSARCH}-latest.gz.run" + export NETDATA_STATIC_ARCHIVE_CHECKSUM_URL="${NETDATA_TARBALL_BASEURL}/sha256sums.txt" fi +} - progress "Found existing install of Netdata under: ${ndprefix}" +try_static_install() { + set_static_archive_urls "${RELEASE_CHANNEL}" + progress "Downloading static netdata binary: ${NETDATA_STATIC_ARCHIVE_URL}" - if [ -r "${ndprefix}/etc/netdata/.environment" ] ; then - ndstatic="$(grep IS_NETDATA_STATIC_BINARY "${ndprefix}/etc/netdata/.environment" | cut -d "=" -f 2 | tr -d \")" - if [ -z "${NETDATA_REINSTALL}" ] && [ -z "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ] ; then - if [ -n "${NETDATA_CLAIM_TOKEN}" ] ; then - if [ "${ndprefix}" != '/' ] ; then - NETDATA_PREFIX="${ndprefix}" - fi + if ! download "${NETDATA_STATIC_ARCHIVE_URL}" "${tmpdir}/netdata-${SYSARCH}-latest.gz.run"; then + warning "Unable to download static build archive for ${SYSARCH}." + return 2 + fi - claim - exit $? - elif [ -x "${ndprefix}/usr/libexec/netdata/netdata-updater.sh" ] ; then - progress "Attempting to update existing install instead of creating a new one" - if run ${sudo} "${ndprefix}/usr/libexec/netdata/netdata-updater.sh" --not-running-from-cron ; then - progress "Updated existing install at ${ndpath}" - exit 0 - else - fatal "Failed to update existing Netdata install" F0100 - fi - else - if [ -z "${NETDATA_ALLOW_DUPLICATE_INSTALL}" ] || [ "${ndstatic}" = "yes" ] ; then - fatal "Existing installation detected which cannot be safely updated by this script. Refusing to continue." F0101 - else - progress "User explicitly requested duplicate install, proceeding." - fi - fi - else - if [ "${ndstatic}" = "no" ] ; then - progress "User requested reinstall instead of update, proceeding." - else - fatal "Existing install is a static install. Please use kickstart-static64.sh instead." F0102 - fi - fi + if ! download "${NETDATA_STATIC_ARCHIVE_CHECKSUM_URL}" "${tmpdir}/sha256sum.txt"; then + fatal "Unable to fetch checksums to verify static build archive." F0206 + fi + + if ! grep "netdata-${SYSARCH}-latest.gz.run" "${tmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then + fatal "Static binary checksum validation failed. Usually this is a result of an older copy of the file being cached somewhere upstream and can be resolved by retrying in an hour." F0207 + fi + + if [ "${INTERACTIVE}" -eq 0 ]; then + opts="${opts} --accept" + fi + + progress "Installing netdata" + # shellcheck disable=SC2086 + if ! run ${ROOTCMD} sh "${tmpdir}/netdata-${SYSARCH}-latest.gz.run" ${opts} -- ${NETDATA_AUTO_UPDATES:+--auto-update} ${NETDATA_INSTALLER_OPTIONS}; then + warning "Failed to install static build of Netdata on ${SYSARCH}." + run rm -rf /opt/netdata + return 2 + fi + + install_type_file="/opt/netdata/etc/netdata/.install-type" + if [ -f "${install_type_file}" ]; then + ${ROOTCMD} sh -c "cat \"${install_type_file}\" > \"${tmpdir}/install-type\"" + ${ROOTCMD} chown "$(id -u)":"$(id -g)" "${tmpdir}/install-type" + # shellcheck disable=SC1091 + . "${tmpdir}/install-type" + cat > "${tmpdir}/install-type" <<- EOF + INSTALL_TYPE='kickstart-static' + PREBUILT_ARCH='${PREBUILT_ARCH}' + EOF + ${ROOTCMD} chown netdata:netdata "${tmpdir}/install-type" + ${ROOTCMD} cp "${tmpdir}/install-type" "${install_type_file}" + fi +} + +# ====================================================================== +# Local build install code + +set_source_archive_urls() { + if [ "$1" = "stable" ]; then + latest="$(get_redirect "https://github.com/netdata/netdata/releases/latest")" + export NETDATA_SOURCE_ARCHIVE_URL="https://github.com/netdata/netdata/releases/download/${latest}/netdata-${latest}.tar.gz" + export NETDATA_SOURCE_ARCHIVE_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/${latest}/sha256sums.txt" else - progress "Existing install appears to be handled manually or through the system package manager." - if [ -n "${NETDATA_CLAIM_TOKEN}" ] ; then - if [ "${ndprefix}" != '/' ] ; then - NETDATA_PREFIX="${ndprefix}" - fi + export NETDATA_SOURCE_ARCHIVE_URL="${NETDATA_TARBALL_BASEURL}/netdata-latest.tar.gz" + export NETDATA_SOURCE_ARCHIVE_CHECKSUM_URL="${NETDATA_TARBALL_BASEURL}/sha256sums.txt" + fi +} + +install_local_build_dependencies() { + bash="$(command -v bash 2> /dev/null)" + + if [ -z "${bash}" ] || [ ! -x "${bash}" ]; then + warning "Unable to find a usable version of \`bash\` (required for local build)." + return 1 + fi + + progress "Fetching script to detect required packages..." + download "${PACKAGES_SCRIPT}" "${tmpdir}/install-required-packages.sh" + + if [ ! -s "${tmpdir}/install-required-packages.sh" ]; then + warning "Downloaded dependency installation script is empty." + else + progress "Running downloaded script to detect required packages..." - claim - exit $? - elif [ -z "${NETDATA_ALLOW_DUPLICATE_INSTALL}" ] ; then - fatal "Existing installation detected which cannot be safely updated by this script. Refusing to continue." F0103 + if [ "${INTERACTIVE}" -eq 0 ]; then + opts="--dont-wait --non-interactive" + fi + + if [ "${SYSTYPE}" = "Darwin" ]; then + sudo="" else - progress "User explicitly requested duplicate install, proceeding." + sudo="${ROOTCMD}" + fi + + # shellcheck disable=SC2086 + if ! run ${sudo} "${bash}" "${tmpdir}/install-required-packages.sh" ${opts} netdata; then + warning "It failed to install all the required packages, but installation might still be possible." fi fi -fi +} -# --------------------------------------------------------------------------------------------------------------------- -# install required system packages +build_and_install() { + progress "Building netdata" -ndtmpdir=$(create_tmp_directory) -cd "${ndtmpdir}" || exit 1 + echo "INSTALL_TYPE='kickstart-build'" > system/.install-type -dependencies + opts="${NETDATA_INSTALLER_OPTIONS}" -# --------------------------------------------------------------------------------------------------------------------- -# download netdata package + if [ "${INTERACTIVE}" -eq 0 ]; then + opts="${opts} --dont-wait" + fi -if [ -z "${NETDATA_LOCAL_TARBALL_OVERRIDE}" ]; then - set_tarball_urls "${RELEASE_CHANNEL}" + if [ "${NETDATA_AUTO_UPDATES}" -eq 1 ]; then + opts="${opts} --auto-update" + fi - download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" - download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz" -else - progress "Installation sources were given as input, running installation using \"${NETDATA_LOCAL_TARBALL_OVERRIDE}\"" - run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE_CHECKSUM}" "${ndtmpdir}/sha256sum.txt" - run cp "${NETDATA_LOCAL_TARBALL_OVERRIDE}" "${ndtmpdir}/netdata-latest.tar.gz" -fi + if [ "${RELEASE_CHANNEL}" = "stable" ]; then + opts="${opts} --stable-channel" + fi -if ! grep netdata-latest.tar.gz "${ndtmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then - fatal "Tarball checksum validation failed. Stopping Netdata Agent installation and leaving tarball in ${ndtmpdir}.\nUsually this is a result of an older copy of the file being cached somewhere upstream and can be resolved by retrying in an hour." F0005 -fi -run tar -xf netdata-latest.tar.gz -rm -rf netdata-latest.tar.gz > /dev/null 2>&1 -cd netdata-* || fatal "Cannot cd to netdata source tree" F0006 + if [ "${NETDATA_REQUIRE_CLOUD}" -eq 1 ]; then + opts="${opts} --require-cloud" + elif [ "${NETDATA_DISABLE_CLOUD}" -eq 1 ]; then + opts="${opts} --disable-cloud" + fi -# --------------------------------------------------------------------------------------------------------------------- -# install netdata from source + # shellcheck disable=SC2086 + run ${ROOTCMD} ./netdata-installer.sh ${opts} -install() { - progress "Installing netdata..." - run ${sudo} ./netdata-installer.sh ${NETDATA_UPDATES} ${NETDATA_INSTALLER_OPTIONS} case $? in 1) fatal "netdata-installer.sh exited with error" F0007 @@ -633,25 +1129,262 @@ install() { fatal "Insufficient RAM to install netdata" F0008 ;; esac - if [ -d "${ndtmpdir}" ] && [ ! "${ndtmpdir}" = "/" ]; then - run ${sudo} rm -rf "${ndtmpdir}" > /dev/null 2>&1 +} + +try_build_install() { + if ! install_local_build_dependencies; then + return 1 + fi + + set_source_archive_urls "${RELEASE_CHANNEL}" + + download "${NETDATA_SOURCE_ARCHIVE_CHECKSUM_URL}" "${tmpdir}/sha256sum.txt" + download "${NETDATA_SOURCE_ARCHIVE_URL}" "${tmpdir}/netdata-latest.tar.gz" + + if ! grep netdata-latest.tar.gz "${tmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then + fatal "Tarball checksum validation failed. Usually this is a result of an older copy of the file being cached somewhere upstream and can be resolved by retrying in an hour." F0005 + fi + + run tar -xf "${tmpdir}/netdata-latest.tar.gz" -C "${tmpdir}" + rm -rf "${tmpdir}/netdata-latest.tar.gz" > /dev/null 2>&1 + cd "$(find "${tmpdir}" -mindepth 1 -maxdepth 1 -type d -name netdata-)" || fatal "Cannot cd to netdata source tree" F0006 + + if [ -x netdata-installer.sh ]; then + build_and_install || return 1 + else + # This case is needed because some platforms produce an extra directory on the source tarball extraction. + 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)" && build_and_install || return 1 + else + fatal "Cannot install netdata from source (the source directory does not include netdata-installer.sh). Leaving all files in ${tmpdir}" F0009 + fi fi } -if [ -x netdata-installer.sh ]; then - echo "INSTALL_TYPE='kickstart-build'" > system/.install-type - install "$@" -else - 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)" && install "$@" +# ====================================================================== +# Per system-type install logic + +install_on_linux() { + if [ "${NETDATA_ONLY_STATIC}" -ne 1 ] && [ "${NETDATA_ONLY_BUILD}" -ne 1 ]; then + SELECTED_INSTALL_METHOD="native" + try_package_install + + case "$?" in + 0) + NETDATA_INSTALL_SUCCESSFUL=1 + ;; + 1) + fatal "Unable to install on this system." F0300 + ;; + 2) + if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then + fatal "Could not install native binary packages." F0301 + else + warning "Could not install native binary packages, falling back to alternative installation method." + fi + ;; + esac + fi + + if [ "${NETDATA_ONLY_NATIVE}" -ne 1 ] && [ "${NETDATA_ONLY_BUILD}" -ne 1 ] && [ -z "${NETDATA_INSTALL_SUCCESSFUL}" ]; then + SELECTED_INSTALL_METHOD="static" + INSTALL_TYPE="kickstart-static" + try_static_install + + case "$?" in + 0) + NETDATA_INSTALL_SUCCESSFUL=1 + INSTALL_PREFIX="/opt/netdata" + ;; + 1) + fatal "Unable to install on this system." F0302 + ;; + 2) + if [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then + fatal "Could not install static build." F0303 + else + warning "Could not install static build, falling back to alternative installation method." + fi + ;; + esac + fi + + if [ "${NETDATA_ONLY_NATIVE}" -ne 1 ] && [ "${NETDATA_ONLY_STATIC}" -ne 1 ] && [ -z "${NETDATA_INSTALL_SUCCESSFUL}" ]; then + SELECTED_INSTALL_METHOD="build" + INSTALL_TYPE="kickstart-build" + try_build_install + + case "$?" in + 0) + NETDATA_INSTALL_SUCCESSFUL=1 + ;; + *) + fatal "Unable to install on this system." F0304 + ;; + esac + fi +} + +install_on_macos() { + if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then + fatal "User requested native package, but native packages are not available for macOS. Try installing without \`--only-native\` option." F0305 + elif [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then + fatal "User requested static build, but static builds are not available for macOS. Try installing without \`--only-static\` option." F0306 else - fatal "Cannot install netdata from source (the source directory does not include netdata-installer.sh). Leaving all files in ${ndtmpdir}" F0009 - exit 1 + SELECTED_INSTALL_METHOD="build" + INSTALL_TYPE="kickstart-build" + try_build_install + + case "$?" in + 0) + NETDATA_INSTALL_SUCCESSFUL=1 + ;; + *) + fatal "Unable to install on this system." F0307 + ;; + esac fi -fi +} + +install_on_freebsd() { + if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then + fatal "User requested native package, but native packages are not available for FreeBSD. Try installing without \`--only-native\` option." F0308 + elif [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then + fatal "User requested static build, but static builds are not available for FreeBSD. Try installing without \`--only-static\` option." F0309 + else + SELECTED_INSTALL_METHOD="build" + INSTALL_TYPE="kickstart-build" + try_build_install + + case "$?" in + 0) + NETDATA_INSTALL_SUCCESSFUL=1 + ;; + *) + fatal "Unable to install on this system." F030A + ;; + esac + fi +} + +# ====================================================================== +# Main program -# -------------------------------------------------------------------------------------------------------------------- +setup_terminal || echo > /dev/null + +while [ -n "${1}" ]; do + case "${1}" in + "--help") + usage + cleanup + trap - EXIT + exit 0 + ;; + "--no-cleanup") NO_CLEANUP=1 ;; + "--dont-wait"|"--non-interactive") INTERACTIVE=0 ;; + "--interactive") INTERACTIVE=1 ;; + "--stable-channel") RELEASE_CHANNEL="stable" ;; + "--no-updates") NETDATA_AUTO_UPDATES=0 ;; + "--auto-update") NETDATA_AUTO_UPDATES="1" ;; + "--reinstall") NETDATA_REINSTALL=1 ;; + "--reinstall-even-if-unsafe") NETDATA_UNSAFE_REINSTALL=1 ;; + "--claim-only") NETDATA_CLAIM_ONLY=1 ;; + "--disable-cloud") + NETDATA_DISABLE_CLOUD=1 + NETDATA_REQUIRE_CLOUD=0 + ;; + "--require-cloud") + NETDATA_DISABLE_CLOUD=0 + NETDATA_REQUIRE_CLOUD=1 + ;; + "--dont-start-it") + NETDATA_NO_START=1 + NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --dont-start-it" + ;; + "--disable-telemetry") + NETDATA_DISABLE_TELEMETRY="1" + NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --disable-telemetry" + ;; + "--install") + INSTALL_PREFIX="${2}" + shift 1 + ;; + "--native-only") + NETDATA_ONLY_NATIVE=1 + NETDATA_ONLY_STATIC=0 + NETDATA_ONLY_BUILD=0 + SELECTED_INSTALL_METHOD="native" + ;; + "--static-only") + NETDATA_ONLY_STATIC=1 + NETDATA_ONLY_NATIVE=0 + NETDATA_ONLY_BUILD=0 + SELECTED_INSTALL_METHOD="static" + ;; + "--build-only") + NETDATA_ONLY_BUILD=1 + NETDATA_ONLY_NATIVE=0 + NETDATA_ONLY_STATIC=0 + SELECTED_INSTALL_METHOD="build" + ;; + "--claim-token") + NETDATA_CLAIM_TOKEN="${2}" + shift 1 + ;; + "--claim-rooms") + NETDATA_CLAIM_ROOMS="${2}" + shift 1 + ;; + "--claim-url") + NETDATA_CLAIM_URL="${2}" + shift 1 + ;; + "--claim-*") + optname="$(echo "${1}" | cut -d '-' -f 4-)" + case "${optname}" in + id|proxy|user|hostname) + NETDATA_CLAIM_EXTRA="${NETDATA_CLAIM_EXTRA} -${optname} ${2}" + shift 1 + ;; + verbose|insecure|noproxy|noreload|daemon-not-running) + NETDATA_CLAIM_EXTRA="${NETDATA_CLAIM_EXTRA} -${optname}" + ;; + *) + warning "Ignoring unrecognized claiming option ${optname}" + ;; + esac + ;; + *) + warning "Passing unrecognized option '${1}' to installer script. If this is intended, please add it to \$NETDATA_INSTALLER_OPTIONS instead." + NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} ${1}" + ;; + esac + shift 1 +done + +check_claim_opts +confirm_root_support +get_system_info +confirm_install_prefix + +tmpdir="$(create_tmp_directory)" +progress "Using ${tmpdir} as a temporary directory." +cd "${tmpdir}" || exit 1 + +handle_existing_install + +case "${SYSTYPE}" in + Linux) install_on_linux ;; + Darwin) install_on_macos ;; + FreeBSD) install_on_freebsd ;; +esac if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then claim +elif [ "${NETDATA_DISABLE_CLOUD}" -eq 1 ]; then + soft_disable_cloud fi + +telemetry_event INSTALL_SUCCESS "" "" +cleanup +trap - EXIT -- cgit v1.2.3