| 1 | #!/bin/sh |
| 2 | # SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | # |
| 4 | # Netdata updater utility |
| 5 | # |
| 6 | # Variables needed by script: |
| 7 | # - PATH |
| 8 | # - CFLAGS |
| 9 | # - LDFLAGS |
| 10 | # - MAKEOPTS |
| 11 | # - IS_NETDATA_STATIC_BINARY |
| 12 | # - NETDATA_CONFIGURE_OPTIONS |
| 13 | # - REINSTALL_OPTIONS |
| 14 | # - NETDATA_TARBALL_URL |
| 15 | # - NETDATA_TARBALL_CHECKSUM_URL |
| 16 | # - NETDATA_TARBALL_CHECKSUM |
| 17 | # - NETDATA_PREFIX |
| 18 | # - NETDATA_LIB_DIR |
| 19 | # |
| 20 | # Optional environment options: |
| 21 | # |
| 22 | # - TMPDIR (set to a usable temporary directory) |
| 23 | # - NETDATA_NIGHTLIES_BASEURL (set the base url for downloading the dist tarball) |
| 24 | |
| 25 | # Next unused error code: U0029 |
| 26 | |
| 27 | set -e |
| 28 | |
| 29 | PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/install-required-packages.sh" |
| 30 | |
| 31 | NETDATA_STABLE_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata/releases}" |
| 32 | NETDATA_NIGHTLY_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata-nightlies/releases}" |
| 33 | NETDATA_STABLE_REPO_URL="${NETDATA_BASE_URL:-https://repository.netdata.cloud/repos/stable}" |
| 34 | NETDATA_NIGHTLY_REPO_URL="${NETDATA_BASE_URL:-https://repository.netdata.cloud/repos/edge}" |
| 35 | NETDATA_DEFAULT_ACCEPT_MAJOR_VERSIONS="1 2" |
| 36 | |
| 37 | # Following variables are intended to be overridden by the updater config file. |
| 38 | NETDATA_UPDATER_JITTER=3600 |
| 39 | NETDATA_NO_SYSTEMD_JOURNAL=0 |
| 40 | NETDATA_ACCEPT_MAJOR_VERSIONS='' |
| 41 | |
| 42 | script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)" |
| 43 | |
| 44 | if [ -x "${script_dir}/netdata-updater" ]; then |
| 45 | script_source="${script_dir}/netdata-updater" |
| 46 | else |
| 47 | script_source="${script_dir}/netdata-updater.sh" |
| 48 | fi |
| 49 | |
| 50 | PATH="${PATH}:/usr/local/bin:/usr/local/sbin" |
| 51 | |
| 52 | if [ ! -t 1 ]; then |
| 53 | INTERACTIVE=0 |
| 54 | else |
| 55 | INTERACTIVE=1 |
| 56 | fi |
| 57 | |
| 58 | if [ -n "${script_source}" ]; then |
| 59 | script_name="$(basename "${script_source}")" |
| 60 | else |
| 61 | script_name="netdata-updater.sh" |
| 62 | fi |
| 63 | |
| 64 | info() { |
| 65 | echo >&3 "$(date) : INFO: ${script_name}: " "${1}" |
| 66 | } |
| 67 | |
| 68 | warning() { |
| 69 | echo >&3 "$(date) : WARNING: ${script_name}: " "${@}" |
| 70 | } |
| 71 | |
| 72 | error() { |
| 73 | echo >&3 "$(date) : ERROR: ${script_name}: " "${1}" |
| 74 | if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then |
| 75 | NETDATA_WARNINGS="${NETDATA_WARNINGS}\n - ${1}" |
| 76 | fi |
| 77 | } |
| 78 | |
| 79 | fatal() { |
| 80 | echo >&3 "$(date) : FATAL: ${script_name}: FAILED TO UPDATE NETDATA: " "${1}" |
| 81 | if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then |
| 82 | NETDATA_WARNINGS="${NETDATA_WARNINGS}\n - ${1}" |
| 83 | fi |
| 84 | exit_reason "${1}" "${2}" |
| 85 | exit 1 |
| 86 | } |
| 87 | |
| 88 | exit_reason() { |
| 89 | if [ -n "${NETDATA_SAVE_WARNINGS}" ]; then |
| 90 | EXIT_REASON="${1}" |
| 91 | EXIT_CODE="${2}" |
| 92 | if [ -n "${NETDATA_PROPAGATE_WARNINGS}" ]; then |
| 93 | if [ -n "${NETDATA_SCRIPT_STATUS_PATH}" ]; then |
| 94 | { |
| 95 | echo "EXIT_REASON=\"${EXIT_REASON}\"" |
| 96 | echo "EXIT_CODE=\"${EXIT_CODE}\"" |
| 97 | echo "NETDATA_WARNINGS=\"${NETDATA_WARNINGS}\"" |
| 98 | } >> "${NETDATA_SCRIPT_STATUS_PATH}" |
| 99 | else |
| 100 | export EXIT_REASON |
| 101 | export EXIT_CODE |
| 102 | export NETDATA_WARNINGS |
| 103 | fi |
| 104 | fi |
| 105 | fi |
| 106 | } |
| 107 | |
| 108 | is_integer () { |
| 109 | case "${1#[+-]}" in |
| 110 | *[!0123456789]*) return 1 ;; |
| 111 | '') return 1 ;; |
| 112 | *) return 0 ;; |
| 113 | esac |
| 114 | } |
| 115 | |
| 116 | safe_pidof() { |
| 117 | pidof_cmd="$(command -v pidof 2> /dev/null)" |
| 118 | if [ -n "${pidof_cmd}" ]; then |
| 119 | ${pidof_cmd} "${@}" |
| 120 | return $? |
| 121 | else |
| 122 | ps -acxo pid,comm | |
| 123 | sed "s/^ *//g" | |
| 124 | grep netdata | |
| 125 | cut -d ' ' -f 1 |
| 126 | return $? |
| 127 | fi |
| 128 | } |
| 129 | |
| 130 | issystemd() { |
| 131 | # if there is no systemctl command, it is not systemd |
| 132 | systemctl=$(command -v systemctl 2> /dev/null) |
| 133 | if [ -z "${systemctl}" ] || [ ! -x "${systemctl}" ]; then |
| 134 | return 1 |
| 135 | fi |
| 136 | |
| 137 | # Check the output of systemctl is-system-running. |
| 138 | # If this reports 'offline', it’s not systemd. If it reports 'unknown' |
| 139 | # or nothing at all (which indicates the command is not supported), it |
| 140 | # may or may not be systemd, so continue to other checks. If it reports |
| 141 | # anything else, it is systemd. |
| 142 | # |
| 143 | # This may return a non-zero exit status in cases when it actually |
| 144 | # succeeded for our purposes (notably, if the state is `degraded`), |
| 145 | # so we need to toggle set -e off here. |
| 146 | set +e |
| 147 | systemd_state="$(systemctl is-system-running)" |
| 148 | set -e |
| 149 | |
| 150 | case "${systemd_state}" in |
| 151 | offline) return 1 ;; |
| 152 | unknown) : ;; |
| 153 | "") : ;; |
| 154 | *) return 0 ;; |
| 155 | esac |
| 156 | |
| 157 | # if pid 1 is systemd, it is systemd |
| 158 | [ "$(basename "$(readlink /proc/1/exe)" 2> /dev/null)" = "systemd" ] && return 0 |
| 159 | |
| 160 | # if systemd is not running, it is not systemd |
| 161 | pids=$(safe_pidof systemd 2> /dev/null) |
| 162 | [ -z "${pids}" ] && return 1 |
| 163 | |
| 164 | # check if the running systemd processes are not in our namespace |
| 165 | myns="$(readlink /proc/self/ns/pid 2> /dev/null)" |
| 166 | for p in ${pids}; do |
| 167 | ns="$(readlink "/proc/${p}/ns/pid" 2> /dev/null)" |
| 168 | |
| 169 | # if pid of systemd is in our namespace, it is systemd |
| 170 | [ -n "${myns}" ] && [ "${myns}" = "${ns}" ] && return 0 |
| 171 | done |
| 172 | |
| 173 | # else, it is not systemd |
| 174 | return 1 |
| 175 | } |
| 176 | |
| 177 | systemd_unit_exists() { |
| 178 | if systemctl list-unit-files "${1}" 2>&1 | tail -n 1 | grep -qv '^0 '; then |
| 179 | return 0 |
| 180 | else |
| 181 | return 1 |
| 182 | fi |
| 183 | } |
| 184 | |
| 185 | # shellcheck disable=SC2009 |
| 186 | running_under_anacron() { |
| 187 | pid="${1:-$$}" |
| 188 | iter="${2:-0}" |
| 189 | |
| 190 | [ "${iter}" -gt 50 ] && return 1 |
| 191 | |
| 192 | if [ "$(uname -s)" = "Linux" ] && [ -r "/proc/${pid}/stat" ]; then |
| 193 | ppid="$(cut -f 4 -d ' ' "/proc/${pid}/stat")" |
| 194 | if [ -n "${ppid}" ]; then |
| 195 | # The below case accounts for the hidepid mount option for procfs, as well as setups with LSM |
| 196 | [ ! -r "/proc/${ppid}/comm" ] && return 1 |
| 197 | |
| 198 | [ "${ppid}" -eq "${pid}" ] && return 1 |
| 199 | |
| 200 | grep -q anacron "/proc/${ppid}/comm" && return 0 |
| 201 | |
| 202 | running_under_anacron "${ppid}" "$((iter + 1))" |
| 203 | |
| 204 | return "$?" |
| 205 | fi |
| 206 | else |
| 207 | ppid="$(ps -o pid= -o ppid= 2>/dev/null | grep -e "^ *${pid}" | xargs | cut -f 2 -d ' ')" |
| 208 | if [ -n "${ppid}" ]; then |
| 209 | [ "${ppid}" -eq "${pid}" ] && return 1 |
| 210 | |
| 211 | ps -o pid= -o command= 2>/dev/null | grep -e "^ *${ppid}" | grep -q anacron && return 0 |
| 212 | |
| 213 | running_under_anacron "${ppid}" "$((iter + 1))" |
| 214 | |
| 215 | return "$?" |
| 216 | fi |
| 217 | fi |
| 218 | |
| 219 | return 1 |
| 220 | } |
| 221 | |
| 222 | _get_intervaldir() { |
| 223 | if [ -d /etc/cron.daily ]; then |
| 224 | echo /etc/cron.daily |
| 225 | elif [ -d /etc/periodic/daily ]; then |
| 226 | echo /etc/periodic/daily |
| 227 | else |
| 228 | return 1 |
| 229 | fi |
| 230 | |
| 231 | return 0 |
| 232 | } |
| 233 | |
| 234 | _get_scheduler_type() { |
| 235 | if _get_intervaldir > /dev/null ; then |
| 236 | echo 'interval' |
| 237 | elif issystemd ; then |
| 238 | echo 'systemd' |
| 239 | elif [ -d /etc/cron.d ] ; then |
| 240 | echo 'crontab' |
| 241 | else |
| 242 | echo 'none' |
| 243 | fi |
| 244 | } |
| 245 | |
| 246 | confirm() { |
| 247 | prompt="${1} [y/n]" |
| 248 | |
| 249 | while true; do |
| 250 | echo "${prompt}" |
| 251 | read -r yn |
| 252 | |
| 253 | case "$yn" in |
| 254 | [Yy]*) return 0;; |
| 255 | [Nn]*) return 1;; |
| 256 | *) echo "Please answer yes or no.";; |
| 257 | esac |
| 258 | done |
| 259 | } |
| 260 | |
| 261 | warn_major_update() { |
| 262 | nmv_suffix="New major versions generally involve breaking changes, and may not work in the same way as older versions." |
| 263 | |
| 264 | if [ "${INTERACTIVE}" -eq 0 ]; then |
| 265 | warning "Would update to a new major version of Netdata. ${nmv_suffix}" |
| 266 | 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}." |
| 267 | fatal "Aborting update to new major version to avoid breaking things." U001B |
| 268 | else |
| 269 | warning "This update will install a new major version of Netdata. ${nmv_suffix}" |
| 270 | if confirm "Are you sure you want to update to a new major version of Netdata?"; then |
| 271 | notice "User accepted update to new major version of Netdata." |
| 272 | else |
| 273 | fatal "Aborting update to new major version at user request." U001C |
| 274 | fi |
| 275 | fi |
| 276 | } |
| 277 | |
| 278 | install_build_dependencies() { |
| 279 | bash="$(command -v bash 2> /dev/null)" |
| 280 | |
| 281 | if [ -z "${bash}" ] || [ ! -x "${bash}" ]; then |
| 282 | error "Unable to find a usable version of \`bash\` (required for local build)." |
| 283 | return 1 |
| 284 | fi |
| 285 | |
| 286 | info "Fetching dependency handling script..." |
| 287 | download "${PACKAGES_SCRIPT}" "./install-required-packages.sh" || true |
| 288 | |
| 289 | if [ ! -s "./install-required-packages.sh" ]; then |
| 290 | error "Downloaded dependency installation script is empty." |
| 291 | else |
| 292 | info "Running dependency handling script..." |
| 293 | |
| 294 | opts="--dont-wait --non-interactive" |
| 295 | |
| 296 | # shellcheck disable=SC2086 |
| 297 | if ! "${bash}" "./install-required-packages.sh" ${opts} netdata >&3 2>&3; then |
| 298 | error "Installing build dependencies failed. The update should still work, but you might be missing some features." |
| 299 | fi |
| 300 | fi |
| 301 | } |
| 302 | |
| 303 | # Certain versions of this script had a bug that could cause /dev/null |
| 304 | # to be removed mistakenly under some circumstances. |
| 305 | # |
| 306 | # This function attempts to detect and fix the resulting situation. |
| 307 | # |
| 308 | # Fix limited to Linux for the moment because apparently trying to |
| 309 | # proactively fix systems that we aren’t certain have been affected is |
| 310 | # too invasive of a change for some people... |
| 311 | dev_null_fix() { |
| 312 | if [ -f /dev/null ] || [ ! -e /dev/null ]; then |
| 313 | case "$(uname -s)" in |
| 314 | Linux) |
| 315 | rm -f /dev/.null |
| 316 | mknod -m 666 /dev/.null c 1 3 |
| 317 | # Some distros use ownership other than root:root for /dev/null, |
| 318 | # but it almost always matches the ownership of /dev/full, |
| 319 | # so if possible copy the onwership from there. |
| 320 | if [ -c /dev/full ]; then |
| 321 | chown --reference=/dev/full /dev/.null |
| 322 | fi |
| 323 | mv -f /dev/.null /dev/null |
| 324 | # If the system seems to be using SELinux, apply the correct |
| 325 | # security context to the new /dev/null. |
| 326 | # |
| 327 | # This check doesn’t use /dev/null as trying to access it |
| 328 | # without the right security context being set may fail. |
| 329 | dummy_null="$(mktemp)" |
| 330 | if command -v restorecon >"${dummy_null}" 2>&1; then |
| 331 | restorecon /dev/null |
| 332 | fi |
| 333 | rm -f "${dummy_null}" || true # Cleanup from the above check |
| 334 | ;; |
| 335 | *) ;; |
| 336 | esac |
| 337 | fi |
| 338 | } |
| 339 | |
| 340 | enable_netdata_updater() { |
| 341 | updater_type="$(echo "${1}" | tr '[:upper:]' '[:lower:]')" |
| 342 | case "${updater_type}" in |
| 343 | systemd|interval|crontab) |
| 344 | updater_type="${1}" |
| 345 | ;; |
| 346 | "") |
| 347 | updater_type="$(_get_scheduler_type)" |
| 348 | ;; |
| 349 | *) |
| 350 | fatal "Unrecognized updater type ${updater_type} requested. Supported types are 'systemd', 'interval', and 'crontab'." U0001 |
| 351 | ;; |
| 352 | esac |
| 353 | |
| 354 | case "${updater_type}" in |
| 355 | "systemd") |
| 356 | if issystemd; then |
| 357 | if systemd_unit_exists netdata-updater.timer; then |
| 358 | systemctl enable netdata-updater.timer |
| 359 | systemctl start netdata-updater.timer |
| 360 | |
| 361 | info "Auto-updating has been ENABLED using a systemd timer unit.\n" |
| 362 | info "If the update process fails, the failure will be logged to the systemd journal just like a regular service failure." |
| 363 | info "Successful updates should produce empty logs." |
| 364 | else |
| 365 | error "Systemd-based auto-update scheduling requested, but the required timer unit does not exist. Auto-updates have NOT been enabled." |
| 366 | return 1 |
| 367 | fi |
| 368 | else |
| 369 | error "Systemd-based auto-update scheduling requested, but this does not appear to be a systemd system. Auto-updates have NOT been enabled." |
| 370 | return 1 |
| 371 | fi |
| 372 | ;; |
| 373 | "interval") |
| 374 | if _get_intervaldir > /dev/null; then |
| 375 | ln -sf "${NETDATA_PREFIX}/usr/libexec/netdata/netdata-updater.sh" "$(_get_intervaldir)/netdata-updater" |
| 376 | |
| 377 | info "Auto-updating has been ENABLED through cron, updater script linked to $(_get_intervaldir)/netdata-updater\n" |
| 378 | 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." |
| 379 | info "Successful updates will not send an email." |
| 380 | else |
| 381 | error "Interval-based auto-update scheduling requested, but I could not find an interval scheduling directory. Auto-updates have NOT been enabled." |
| 382 | return 1 |
| 383 | fi |
| 384 | ;; |
| 385 | "crontab") |
| 386 | if [ -d "/etc/cron.d" ]; then |
| 387 | [ -f "/etc/cron.d/netdata-updater" ] && rm -f "/etc/cron.d/netdata-updater" |
| 388 | install -p -m 0644 -o 0 -g 0 "${NETDATA_PREFIX}/usr/lib/netdata/system/cron/netdata-updater-daily" "/etc/cron.d/netdata-updater-daily" |
| 389 | |
| 390 | info "Auto-updating has been ENABLED through cron, using a crontab at /etc/cron.d/netdata-updater\n" |
| 391 | 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." |
| 392 | info "Successful updates will not send an email." |
| 393 | else |
| 394 | error "Crontab-based auto-update scheduling requested, but there is no '/etc/cron.d'. Auto-updates have NOT been enabled." |
| 395 | return 1 |
| 396 | fi |
| 397 | ;; |
| 398 | *) |
| 399 | error "Unable to determine what type of auto-update scheduling to use. Auto-updates have NOT been enabled." |
| 400 | return 1 |
| 401 | esac |
| 402 | |
| 403 | return 0 |
| 404 | } |
| 405 | |
| 406 | disable_netdata_updater() { |
| 407 | if issystemd && systemd_unit_exists "netdata-updater.timer" ; then |
| 408 | systemctl disable netdata-updater.timer |
| 409 | systemctl stop netdata-updater.timer |
| 410 | fi |
| 411 | |
| 412 | if [ -d /etc/cron.daily ]; then |
| 413 | rm -f /etc/cron.daily/netdata-updater.sh |
| 414 | rm -f /etc/cron.daily/netdata-updater |
| 415 | fi |
| 416 | |
| 417 | if [ -d /etc/periodic/daily ]; then |
| 418 | rm -f /etc/periodic/daily/netdata-updater.sh |
| 419 | rm -f /etc/periodic/daily/netdata-updater |
| 420 | fi |
| 421 | |
| 422 | if [ -d /etc/cron.d ]; then |
| 423 | rm -f /etc/cron.d/netdata-updater |
| 424 | rm -f /etc/cron.d/netdata-updater-daily |
| 425 | fi |
| 426 | |
| 427 | info "Auto-updates have been DISABLED." |
| 428 | |
| 429 | return 0 |
| 430 | } |
| 431 | |
| 432 | auto_update_status() { |
| 433 | case "$(_get_scheduler_type)" in |
| 434 | systemd) info "The default auto-update scheduling method for this system is: systemd timer units" ;; |
| 435 | crontab) info "The default auto-update scheduling method for this system is: drop-in crontab" ;; |
| 436 | interval) info "The default auto-update scheduling method for this system is: drop-in periodic script" ;; |
| 437 | *) info "No recognized auto-update scheduling method found" ; return ;; |
| 438 | esac |
| 439 | |
| 440 | duplicate="" |
| 441 | enabled="" |
| 442 | |
| 443 | if issystemd; then |
| 444 | if systemd_unit_exists "netdata-updater.timer"; then |
| 445 | if systemctl is-enabled netdata-updater.timer; then |
| 446 | info "Auto-updates using a systemd timer unit are ENABLED" |
| 447 | enabled="systemd" |
| 448 | else |
| 449 | info "Auto-updates using a systemd timer unit are DISABLED" |
| 450 | fi |
| 451 | else |
| 452 | info "Auto-updates using a systemd timer unit are NOT SUPPORTED due to: Required unit files not installed" |
| 453 | fi |
| 454 | else |
| 455 | info "Auto-updates using a systemd timer unit are NOT SUPPORTED due to: Systemd not present" |
| 456 | fi |
| 457 | |
| 458 | interval_found="" |
| 459 | |
| 460 | if [ -d /etc/cron.daily ]; then |
| 461 | interval_found="1" |
| 462 | |
| 463 | if [ -x /etc/cron.daily/netdata-updater.sh ] || [ -x /etc/cron.daily/netdata-updater ]; then |
| 464 | info "Auto-updates using a drop-in periodic script in /etc/cron.daily are ENABLED" |
| 465 | |
| 466 | if [ -n "${enabled}" ]; then |
| 467 | duplicate="1" |
| 468 | else |
| 469 | enabled="cron.daily" |
| 470 | fi |
| 471 | else |
| 472 | info "Auto-updates using a drop-in periodic script in /etc/cron.daily are DISABLED" |
| 473 | fi |
| 474 | else |
| 475 | info "Auto-updates using a drop-in periodic script in /etc/cron.daily are NOT SUPPORTED: due to: Directory does not exist" |
| 476 | fi |
| 477 | |
| 478 | if [ -d /etc/periodic/daily ]; then |
| 479 | if [ -x /etc/periodic/daily/netdata-updater.sh ] || [ -x /etc/periodic/daily/netdata-updater ]; then |
| 480 | info "Auto-updates using a drop-in periodic script in /etc/periodic/daily are ENABLED" |
| 481 | |
| 482 | if [ -n "${enabled}" ]; then |
| 483 | duplicate="1" |
| 484 | else |
| 485 | enabled="periodic/daily" |
| 486 | fi |
| 487 | else |
| 488 | if [ -z "${interval_found}" ]; then |
| 489 | info "Auto-updates using a drop-in periodic script in /etc/periodic/daily are DISABLED" |
| 490 | fi |
| 491 | fi |
| 492 | elif [ -z "${interval_found}" ]; then |
| 493 | info "Auto-updates using a drop-in periodic script in /etc/periodic/daily are NOT SUPPORTED due to: Directory does not exist" |
| 494 | fi |
| 495 | |
| 496 | if [ -d /etc/cron.d ]; then |
| 497 | if [ -f /etc/cron.d/netdata-updater ] || [ -f /etc/cron.d/netdata-updater-daily ]; then |
| 498 | info "Auto-updates using a drop-in crontab are ENABLED" |
| 499 | |
| 500 | if [ -n "${enabled}" ]; then |
| 501 | duplicate="1" |
| 502 | else |
| 503 | enabled="cron.d" |
| 504 | fi |
| 505 | else |
| 506 | info "Auto-updates using a drop-in crontab are DISABLED" |
| 507 | fi |
| 508 | else |
| 509 | info "Auto-updates using a drop-in crontab are NOT SUPPORTED due to: Directory does not exist" |
| 510 | fi |
| 511 | |
| 512 | if [ -n "${duplicate}" ]; then |
| 513 | warning "More than one method of auto-updates is enabled! Please disable and re-enable auto-updates to correct this." |
| 514 | fi |
| 515 | } |
| 516 | |
| 517 | str_in_list() { |
| 518 | printf "%s\n" "${2}" | tr ' ' "\n" | grep -qE "^${1}\$" |
| 519 | return $? |
| 520 | } |
| 521 | |
| 522 | safe_sha256sum() { |
| 523 | # Within the context of the installer, we only use -c option that is common between the two commands |
| 524 | # We will have to reconsider if we start non-common options |
| 525 | if command -v shasum > /dev/null 2>&1; then |
| 526 | shasum -a 256 "$@" |
| 527 | elif command -v sha256sum > /dev/null 2>&1; then |
| 528 | sha256sum "$@" |
| 529 | else |
| 530 | fatal "I could not find a suitable checksum binary to use" U0002 |
| 531 | fi |
| 532 | } |
| 533 | |
| 534 | cleanup() { |
| 535 | if [ -n "${logfile}" ]; then |
| 536 | cat >&2 "${logfile}" |
| 537 | rm "${logfile}" |
| 538 | fi |
| 539 | |
| 540 | if [ -n "$ndtmpdir" ] && [ -d "$ndtmpdir" ]; then |
| 541 | rm -rf "$ndtmpdir" |
| 542 | fi |
| 543 | } |
| 544 | |
| 545 | _cannot_use_tmpdir() { |
| 546 | testfile="$(TMPDIR="${1}" mktemp -q -t netdata-test.XXXXXXXXXX)" |
| 547 | ret=0 |
| 548 | |
| 549 | if [ -z "${testfile}" ] ; then |
| 550 | return "${ret}" |
| 551 | fi |
| 552 | |
| 553 | if printf '#!/bin/sh\necho SUCCESS\n' > "${testfile}" ; then |
| 554 | if chmod +x "${testfile}" ; then |
| 555 | if [ "$("${testfile}" 2>/dev/null)" = "SUCCESS" ] ; then |
| 556 | ret=1 |
| 557 | fi |
| 558 | fi |
| 559 | fi |
| 560 | |
| 561 | rm -f "${testfile}" |
| 562 | return "${ret}" |
| 563 | } |
| 564 | |
| 565 | create_exec_tmp_directory() { |
| 566 | if [ -z "${ndtmpdir}" ]; then |
| 567 | if [ -n "${NETDATA_TMPDIR_PATH}" ]; then |
| 568 | ndtmpdir="${NETDATA_TMPDIR_PATH}" |
| 569 | else |
| 570 | root_dir="" |
| 571 | |
| 572 | if [ -n "${NETDATA_TMPDIR}" ] && ! _cannot_use_tmpdir "${NETDATA_TMPDIR}"; then |
| 573 | root_dir="${NETDATA_TMPDIR}" |
| 574 | elif [ -n "${TMPDIR}" ] && ! _cannot_use_tmpdir "${TMPDIR}"; then |
| 575 | root_dir="${TMPDIR}" |
| 576 | elif ! _cannot_use_tmpdir /tmp; then |
| 577 | root_dir="/tmp" |
| 578 | elif ! _cannot_use_tmpdir "${PWD}"; then |
| 579 | root_dir="${PWD}" |
| 580 | else |
| 581 | 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 |
| 582 | fi |
| 583 | |
| 584 | TMPDIR="${root_dir}" |
| 585 | |
| 586 | ndtmpdir="$(mktemp -d -p "${root_dir}" -t netdata-updater-XXXXXXXXXX)" |
| 587 | fi |
| 588 | fi |
| 589 | |
| 590 | info "Putting temporary files in ${ndtmpdir}" |
| 591 | } |
| 592 | |
| 593 | check_for_curl() { |
| 594 | if [ -z "${curl}" ]; then |
| 595 | curl="$(PATH="${PATH}:/opt/netdata/bin" command -v curl 2>/dev/null || true)" |
| 596 | fi |
| 597 | } |
| 598 | |
| 599 | check_for_wget() { |
| 600 | if [ -z "${wget}" ]; then |
| 601 | wget="$(command -v wget 2>/dev/null || true)" |
| 602 | fi |
| 603 | |
| 604 | if [ -z "${wget}" ]; then |
| 605 | wget="$(command -v wget2 2>/dev/null || true)" |
| 606 | fi |
| 607 | } |
| 608 | |
| 609 | _safe_download() { |
| 610 | url="${1}" |
| 611 | dest="${2}" |
| 612 | |
| 613 | if echo "${url}" | grep -Eq "^file:///"; then |
| 614 | cp "${url#file://}" "${dest}" || return 1 |
| 615 | return 0 |
| 616 | fi |
| 617 | |
| 618 | check_for_curl |
| 619 | check_for_wget |
| 620 | create_exec_tmp_directory |
| 621 | dl_log="${ndtmpdir}/download.log" |
| 622 | rm -f "${dl_log}" |
| 623 | |
| 624 | if [ -n "${curl}" ]; then |
| 625 | set +e |
| 626 | "${curl}" --silent --fail --location --write-out "%{http_code}" --connect-timeout 10 --retry 3 "${url}" --output "${dest}" > "${dl_log}" |
| 627 | result="$?" |
| 628 | set -e |
| 629 | |
| 630 | case "${result}" in |
| 631 | 0) return 0 ;; |
| 632 | 22|78) |
| 633 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 634 | case "$(tail -n 1 "${dl_log}")" in |
| 635 | 404) return 1 ;; |
| 636 | 4*) return 5 ;; |
| 637 | 5*) return 6 ;; |
| 638 | *) return 4 ;; |
| 639 | esac |
| 640 | ;; |
| 641 | 5|6|7) |
| 642 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 643 | return 2 |
| 644 | ;; |
| 645 | 35|60|83) |
| 646 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 647 | return 3 |
| 648 | ;; |
| 649 | *) |
| 650 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 651 | return 4 |
| 652 | ;; |
| 653 | esac |
| 654 | elif [ -n "${wget}" ]; then |
| 655 | set +e |
| 656 | "${wget}" -T 15 -S -o "${dl_log}" -O "${dest}" "${url}" |
| 657 | result="$?" |
| 658 | set -e |
| 659 | |
| 660 | case "${result}" in |
| 661 | 0) return 0 ;; |
| 662 | 8) |
| 663 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 664 | |
| 665 | case "$(grep "HTTP/" "${dl_log}" | tail -n 1 | awk '{ print $2 }')" in |
| 666 | 404) return 1 ;; |
| 667 | 4*) return 5 ;; |
| 668 | 5*) return 6 ;; |
| 669 | *) return 4 ;; |
| 670 | esac |
| 671 | ;; |
| 672 | 4) |
| 673 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 674 | return 2 |
| 675 | ;; |
| 676 | 5) |
| 677 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 678 | return 3 |
| 679 | ;; |
| 680 | *) |
| 681 | [ "${dest}" != "/dev/null" ] && rm -f "${dest}" |
| 682 | return 4 |
| 683 | ;; |
| 684 | esac |
| 685 | fi |
| 686 | |
| 687 | return 255 |
| 688 | } |
| 689 | |
| 690 | download() { |
| 691 | url="${1}" |
| 692 | dest="${2}" |
| 693 | |
| 694 | set +e |
| 695 | _safe_download "${url}" "${dest}" |
| 696 | ret=$? |
| 697 | set -e |
| 698 | |
| 699 | case "${ret}" in |
| 700 | 0) return 0 ;; |
| 701 | 1) fatal "File ${url} not found on remote server" U0022 ;; |
| 702 | 2) fatal "Unable to connect to remote host to download ${url}" U0023 ;; |
| 703 | 3) fatal "TLS error connecting to remote host to download ${url}" U0024 ;; |
| 704 | 5) fatal "Client error when trying to download ${url}" U0027 ;; |
| 705 | 6) fatal "Internal server error when trying to download ${url}" U0028 ;; |
| 706 | 255) fatal "I need curl or wget to proceed, but neither is available on this system." U0004 ;; |
| 707 | *) fatal "Cannot download ${url}" U0005 ;; |
| 708 | esac |
| 709 | } |
| 710 | |
| 711 | get_netdata_latest_tag() { |
| 712 | url="${1}/latest" |
| 713 | |
| 714 | check_for_curl |
| 715 | check_for_wget |
| 716 | |
| 717 | if [ -z "${curl}" ] && [ -z "${wget}" ]; then |
| 718 | fatal "I need curl or wget to proceed, but neither of them are available on this system." U0006 |
| 719 | fi |
| 720 | |
| 721 | if [ -n "${curl}" ]; then |
| 722 | tag=$("${curl}" "${url}" -s -L -I -o /dev/null -w '%{url_effective}' || true) |
| 723 | fi |
| 724 | |
| 725 | if [ -z "${tag}" ]; then |
| 726 | if [ -n "${wget}" ]; then |
| 727 | tag=$("${wget}" -S -O /dev/null "${url}" 2>&1 | grep Location || true) |
| 728 | fi |
| 729 | fi |
| 730 | |
| 731 | if [ -z "${tag}" ]; then |
| 732 | tag='latest' |
| 733 | fi |
| 734 | |
| 735 | tag="$(echo "${tag}" | grep -Eom 1 '[^/]*/?$')" |
| 736 | |
| 737 | # Fallback case for simpler local testing. |
| 738 | if echo "${tag}" | grep -Eq 'latest/?$'; then |
| 739 | set +e |
| 740 | _safe_download "${url}/latest-version.txt" ./ndupdate-version.txt |
| 741 | result="$?" |
| 742 | set -e |
| 743 | |
| 744 | case "${result}" in |
| 745 | 0) tag="$(cat ./ndupdate-version.txt)" ;; |
| 746 | *) tag='latest' ;; |
| 747 | esac |
| 748 | |
| 749 | rm -f ./ndupdate-version.txt |
| 750 | fi |
| 751 | |
| 752 | echo "${tag}" |
| 753 | } |
| 754 | |
| 755 | newer_commit_date() { |
| 756 | info "Checking if a newer version of the updater script is available." |
| 757 | |
| 758 | create_exec_tmp_directory |
| 759 | commit_check_file="${ndtmpdir}/latest-commit.json" |
| 760 | commit_check_url="https://api.github.com/repos/netdata/netdata/commits?path=packaging%2Finstaller%2Fnetdata-updater.sh&page=1&per_page=1" |
| 761 | python_version_check=" |
| 762 | from __future__ import print_function |
| 763 | import sys, json |
| 764 | |
| 765 | try: |
| 766 | data = json.load(sys.stdin) |
| 767 | except: |
| 768 | print('') |
| 769 | else: |
| 770 | print(data[0]['commit']['committer']['date'] if isinstance(data, list) and data else '') |
| 771 | " |
| 772 | |
| 773 | if ! _safe_download "${commit_check_url}" "${commit_check_file}"; then |
| 774 | warning "Failed to check for an updated updater script, skipping self-update check." |
| 775 | rm -f "${commit_check_file}" 2>/dev/null || true |
| 776 | return 1 |
| 777 | fi |
| 778 | |
| 779 | if command -v jq > /dev/null 2>&1; then |
| 780 | commit_date="$(jq '.[0].commit.committer.date' 2>/dev/null < "${commit_check_file}" | tr -d '"')" |
| 781 | elif command -v python > /dev/null 2>&1;then |
| 782 | commit_date="$(python -c "${python_version_check}" < "${commit_check_file}")" |
| 783 | elif command -v python3 > /dev/null 2>&1;then |
| 784 | commit_date="$(python3 -c "${python_version_check}" < "${commit_check_file}")" |
| 785 | fi |
| 786 | |
| 787 | if [ -z "${NETDATA_TMPDIR_PATH}" ]; then |
| 788 | rm -f "${commit_check_file}" 2>/dev/null || true |
| 789 | fi |
| 790 | |
| 791 | if [ -z "${commit_date}" ] ; then |
| 792 | return 0 |
| 793 | elif [ "$(uname)" = "Linux" ]; then |
| 794 | commit_date="$(date -d "${commit_date}" +%s)" |
| 795 | else # assume BSD-style `date` if we are not on Linux |
| 796 | commit_date="$(/bin/date -j -f "%Y-%m-%dT%H:%M:%SZ" "${commit_date}" +%s 2>/dev/null)" |
| 797 | |
| 798 | if [ -z "${commit_date}" ]; then |
| 799 | return 0 |
| 800 | fi |
| 801 | fi |
| 802 | |
| 803 | if [ -e "${script_source}" ]; then |
| 804 | script_date="$(date -r "${script_source}" +%s)" |
| 805 | else |
| 806 | script_date="$(date +%s)" |
| 807 | fi |
| 808 | |
| 809 | [ "${commit_date}" -ge "${script_date}" ] |
| 810 | } |
| 811 | |
| 812 | self_update() { |
| 813 | if [ -z "${NETDATA_NO_UPDATER_SELF_UPDATE}" ] && newer_commit_date; then |
| 814 | info "Downloading newest version of updater script." |
| 815 | |
| 816 | create_exec_tmp_directory |
| 817 | cd "${ndtmpdir}" || exit 1 |
| 818 | |
| 819 | if _safe_download "https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/netdata-updater.sh" ./netdata-updater.sh; then |
| 820 | chmod +x ./netdata-updater.sh || exit 1 |
| 821 | export ENVIRONMENT_FILE="${ENVIRONMENT_FILE}" |
| 822 | |
| 823 | cmd="./netdata-updater.sh --not-running-from-cron --no-updater-self-update" |
| 824 | [ "$NETDATA_FORCE_UPDATE" = "1" ] && cmd="$cmd --force-update" |
| 825 | [ "$INTERACTIVE" = "0" ] && cmd="$cmd --non-interactive" |
| 826 | cmd="$cmd --tmpdir-path $(pwd)" |
| 827 | |
| 828 | exec $cmd |
| 829 | else |
| 830 | error "Failed to download newest version of updater script, continuing with current version." |
| 831 | fi |
| 832 | fi |
| 833 | } |
| 834 | |
| 835 | parse_version() { |
| 836 | r="${1}" |
| 837 | if [ "${r}" = "latest" ]; then |
| 838 | # If we get ‘latest’ as a version, return the largest possible |
| 839 | # version value. |
| 840 | printf "999999999999999" |
| 841 | return 0 |
| 842 | elif echo "${r}" | grep -q '^v.*'; then |
| 843 | # shellcheck disable=SC2001 |
| 844 | # XXX: Need a regex group substitution here. |
| 845 | r="$(echo "${r}" | sed -e 's/^v\(.*\)/\1/')" |
| 846 | fi |
| 847 | |
| 848 | tmpfile="$(mktemp)" |
| 849 | echo "${r}" | tr '-' ' ' > "${tmpfile}" |
| 850 | read -r v b _ < "${tmpfile}" |
| 851 | |
| 852 | if echo "${b}" | grep -vEq "^[0-9]+$"; then |
| 853 | b="0" |
| 854 | fi |
| 855 | |
| 856 | echo "${v}" | tr '.' ' ' > "${tmpfile}" |
| 857 | read -r maj min patch _ < "${tmpfile}" |
| 858 | |
| 859 | rm -f "${tmpfile}" |
| 860 | |
| 861 | printf "%04d%03d%03d%05d" "${maj}" "${min}" "${patch}" "${b}" |
| 862 | } |
| 863 | |
| 864 | get_latest_tag() { |
| 865 | if [ -z "${_latest_tag}" ]; then |
| 866 | if [ "${RELEASE_CHANNEL}" = "stable" ]; then |
| 867 | _latest_tag="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}")" |
| 868 | else |
| 869 | _latest_tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}")" |
| 870 | fi |
| 871 | fi |
| 872 | |
| 873 | echo "${_latest_tag}" |
| 874 | } |
| 875 | |
| 876 | validate_environment_file() { |
| 877 | if [ -n "${NETDATA_PREFIX+SET_BUT_NULL}" ] && [ -n "${REINSTALL_OPTIONS+SET_BUT_NULL}" ]; then |
| 878 | return 0 |
| 879 | else |
| 880 | fatal "Environment file located at ${ENVIRONMENT_FILE} is not valid, unable to update." U0007 |
| 881 | fi |
| 882 | } |
| 883 | |
| 884 | get_current_version() { |
| 885 | basepath="$(dirname "$(dirname "$(dirname "${NETDATA_LIB_DIR}")")")" |
| 886 | searchpath="${basepath}/bin:${basepath}/sbin:${basepath}/usr/bin:${basepath}/usr/sbin:${PATH}" |
| 887 | searchpath="${basepath}/netdata/bin:${basepath}/netdata/sbin:${basepath}/netdata/usr/bin:${basepath}/netdata/usr/sbin:${searchpath}" |
| 888 | ndbinary="$(PATH="${searchpath}" command -v netdata 2>/dev/null)" |
| 889 | |
| 890 | if [ -z "${ndbinary}" ]; then |
| 891 | _current_version=0 |
| 892 | else |
| 893 | _current_version="$(parse_version "$(${ndbinary} -V | cut -f 2 -d ' ')")" |
| 894 | fi |
| 895 | |
| 896 | echo "${_current_version:-0}" |
| 897 | } |
| 898 | |
| 899 | get_latest_version() { |
| 900 | parse_version "$(get_latest_tag)" |
| 901 | } |
| 902 | |
| 903 | update_available() { |
| 904 | if [ "$NETDATA_FORCE_UPDATE" = "1" ]; then |
| 905 | info "Force update requested" |
| 906 | return 0 |
| 907 | fi |
| 908 | |
| 909 | current_version="$(get_current_version)" |
| 910 | latest_version="$(get_latest_version)" |
| 911 | |
| 912 | info "Current Version: ${current_version}" |
| 913 | info "Latest Version: ${latest_version}" |
| 914 | |
| 915 | if [ -z "${latest_version}" ] || [ -z "${current_version}" ] ; then |
| 916 | info "Unable to compare versions for update check, assuming an update is required." |
| 917 | return 0 |
| 918 | elif [ "${latest_version}" -gt 0 ] && [ "${current_version}" -gt 0 ] && [ "${current_version}" -ge "${latest_version}" ]; then |
| 919 | info "Newest version (current=${current_version} >= latest=${latest_version}) is already installed" |
| 920 | return 1 |
| 921 | else |
| 922 | info "Update available" |
| 923 | |
| 924 | if [ "${current_version}" -ne 0 ] && [ "${latest_version}" -ne 0 ]; then |
| 925 | current_major="$(echo "${current_version}" | head -c 4)" |
| 926 | latest_major="$(echo "${latest_version}" | head -c 4)" |
| 927 | |
| 928 | if [ "${current_major}" -ne "${latest_major}" ]; then |
| 929 | update_safe=0 |
| 930 | |
| 931 | for v in ${NETDATA_ACCEPT_MAJOR_VERSIONS}; do |
| 932 | if [ "${latest_major}" -eq "${v}" ]; then |
| 933 | update_safe=1 |
| 934 | break |
| 935 | fi |
| 936 | done |
| 937 | |
| 938 | if [ "${update_safe}" -eq 0 ]; then |
| 939 | warn_major_update |
| 940 | fi |
| 941 | fi |
| 942 | fi |
| 943 | |
| 944 | return 0 |
| 945 | fi |
| 946 | } |
| 947 | |
| 948 | set_tarball_urls() { |
| 949 | filename="netdata-latest.tar.gz" |
| 950 | |
| 951 | if [ "$2" = "yes" ]; then |
| 952 | if [ -e /opt/netdata/etc/netdata/.install-type ]; then |
| 953 | # shellcheck disable=SC1091 |
| 954 | . /opt/netdata/etc/netdata/.install-type |
| 955 | [ -z "${PREBUILT_ARCH:-}" ] && PREBUILT_ARCH="$(uname -m)" |
| 956 | filename="netdata-${PREBUILT_ARCH}-latest.gz.run" |
| 957 | else |
| 958 | filename="netdata-x86_64-latest.gz.run" |
| 959 | fi |
| 960 | fi |
| 961 | |
| 962 | if [ -n "${NETDATA_OFFLINE_INSTALL_SOURCE}" ]; then |
| 963 | path="$(cd "${NETDATA_OFFLINE_INSTALL_SOURCE}" || exit 1; pwd)" |
| 964 | export NETDATA_TARBALL_URL="file://${path}/${filename}" |
| 965 | export NETDATA_TARBALL_CHECKSUM_URL="file://${path}/sha256sums.txt" |
| 966 | elif [ "$1" = "stable" ]; then |
| 967 | latest="$(get_latest_tag)" |
| 968 | export NETDATA_TARBALL_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/${filename}" |
| 969 | export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/sha256sums.txt" |
| 970 | else |
| 971 | tag="$(get_latest_tag)" |
| 972 | export NETDATA_TARBALL_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/${filename}" |
| 973 | export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/sha256sums.txt" |
| 974 | fi |
| 975 | } |
| 976 | |
| 977 | update_build() { |
| 978 | [ -z "${logfile}" ] && info "Running on a terminal - (this script also supports running headless from crontab)" |
| 979 | |
| 980 | RUN_INSTALLER=0 |
| 981 | create_exec_tmp_directory |
| 982 | cd "$ndtmpdir" || fatal "Failed to change current working directory to ${ndtmpdir}" U0016 |
| 983 | |
| 984 | install_build_dependencies |
| 985 | |
| 986 | if update_available; then |
| 987 | download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" >&3 2>&3 |
| 988 | download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-latest.tar.gz" |
| 989 | if [ -n "${NETDATA_TARBALL_CHECKSUM}" ] && |
| 990 | grep "${NETDATA_TARBALL_CHECKSUM}" sha256sum.txt >&3 2>&3 && |
| 991 | [ "$NETDATA_FORCE_UPDATE" != "1" ]; then |
| 992 | info "Newest version is already installed" |
| 993 | else |
| 994 | if ! grep netdata-latest.tar.gz sha256sum.txt | safe_sha256sum -c - >&3 2>&3; then |
| 995 | 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 |
| 996 | fi |
| 997 | NEW_CHECKSUM="$(safe_sha256sum netdata-latest.tar.gz 2> /dev/null | cut -d' ' -f1)" |
| 998 | tar -xf netdata-latest.tar.gz >&3 2>&3 |
| 999 | rm netdata-latest.tar.gz >&3 2>&3 |
| 1000 | if [ -z "$path_version" ]; then |
| 1001 | latest_tag="$(get_latest_tag)" |
| 1002 | path_version="$(echo "${latest_tag}" | cut -f 1 -d "-")" |
| 1003 | fi |
| 1004 | cd "$(find . -maxdepth 1 -type d -name "netdata-${path_version}*" | head -n 1)" || fatal "Failed to switch to build directory" U0017 |
| 1005 | RUN_INSTALLER=1 |
| 1006 | fi |
| 1007 | fi |
| 1008 | |
| 1009 | # We got the sources, run the update now |
| 1010 | if [ ${RUN_INSTALLER} -eq 1 ]; then |
| 1011 | # signal netdata to start saving its database |
| 1012 | # this is handy if your database is big |
| 1013 | possible_pids=$(pidof netdata) |
| 1014 | do_not_start= |
| 1015 | if [ -n "${possible_pids}" ]; then |
| 1016 | # shellcheck disable=SC2086 |
| 1017 | kill -USR1 ${possible_pids} |
| 1018 | else |
| 1019 | # netdata is currently not running, so do not start it after updating |
| 1020 | do_not_start="--dont-start-it" |
| 1021 | fi |
| 1022 | |
| 1023 | env="env TMPDIR=${TMPDIR}" |
| 1024 | |
| 1025 | if [ -n "${NETDATA_SELECTED_DASHBOARD}" ]; then |
| 1026 | env="${env} NETDATA_SELECTED_DASHBOARD=${NETDATA_SELECTED_DASHBOARD}" |
| 1027 | fi |
| 1028 | |
| 1029 | if [ ! -x ./netdata-installer.sh ]; then |
| 1030 | if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -x "$(find . -mindepth 1 -maxdepth 1 -type d)/netdata-installer.sh" ]; then |
| 1031 | cd "$(find . -mindepth 1 -maxdepth 1 -type d)" || fatal "Failed to switch to build directory" U0018 |
| 1032 | fi |
| 1033 | fi |
| 1034 | |
| 1035 | if [ -e "${NETDATA_PREFIX}/etc/netdata/.install-type" ] ; then |
| 1036 | install_type="$(cat "${NETDATA_PREFIX}"/etc/netdata/.install-type)" |
| 1037 | else |
| 1038 | install_type="INSTALL_TYPE='legacy-build'" |
| 1039 | fi |
| 1040 | |
| 1041 | if [ "${INSTALL_TYPE}" = "custom" ] && [ -f "${NETDATA_PREFIX}" ]; then |
| 1042 | install_type="INSTALL_TYPE='legacy-build'" |
| 1043 | fi |
| 1044 | |
| 1045 | info "Re-installing netdata..." |
| 1046 | export NETDATA_SAVE_WARNINGS=1 |
| 1047 | export NETDATA_PROPAGATE_WARNINGS=1 |
| 1048 | export NETDATA_WARNINGS="${NETDATA_WARNINGS}" |
| 1049 | export NETDATA_SCRIPT_STATUS_PATH="${NETDATA_SCRIPT_STATUS_PATH}" |
| 1050 | # shellcheck disable=SC2086 |
| 1051 | if ! ${env} ./netdata-installer.sh ${REINSTALL_OPTIONS} --dont-wait ${do_not_start} >&3 2>&3; then |
| 1052 | if [ -r "${NETDATA_SCRIPT_STATUS_PATH}" ]; then |
| 1053 | # shellcheck disable=SC1090 |
| 1054 | . "${NETDATA_SCRIPT_STATUS_PATH}" |
| 1055 | rm -f "${NETDATA_SCRIPT_STATUS_PATH}" |
| 1056 | fi |
| 1057 | if [ -n "${EXIT_REASON}" ]; then |
| 1058 | fatal "Failed to rebuild existing netdata install: ${EXIT_REASON}" "U${EXIT_CODE}" |
| 1059 | else |
| 1060 | fatal "Failed to rebuild existing netdata reinstall." UI0000 |
| 1061 | fi |
| 1062 | fi |
| 1063 | |
| 1064 | # We no longer store checksum info here. but leave this so that we clean up all environment files upon next update. |
| 1065 | sed -i '/NETDATA_TARBALL/d' "${ENVIRONMENT_FILE}" |
| 1066 | |
| 1067 | info "Updating tarball checksum info" |
| 1068 | echo "${NEW_CHECKSUM}" > "${NETDATA_LIB_DIR}/netdata.tarball.checksum" |
| 1069 | |
| 1070 | echo "${install_type}" > "${NETDATA_PREFIX}/etc/netdata/.install-type" |
| 1071 | fi |
| 1072 | |
| 1073 | rm -rf "${ndtmpdir}" >&3 2>&3 |
| 1074 | [ -n "${logfile}" ] && rm "${logfile}" && logfile= |
| 1075 | |
| 1076 | return 0 |
| 1077 | } |
| 1078 | |
| 1079 | update_static() { |
| 1080 | create_exec_tmp_directory |
| 1081 | PREVDIR="$(pwd)" |
| 1082 | |
| 1083 | info "Entering ${ndtmpdir}" |
| 1084 | cd "${ndtmpdir}" || fatal "Failed to change current working directory to ${ndtmpdir}" U0019 |
| 1085 | |
| 1086 | if update_available; then |
| 1087 | sysarch="${PREBUILT_ARCH}" |
| 1088 | [ -z "$sysarch" ] && sysarch="$(uname -m)" |
| 1089 | download "${NETDATA_TARBALL_CHECKSUM_URL}" "${ndtmpdir}/sha256sum.txt" |
| 1090 | download "${NETDATA_TARBALL_URL}" "${ndtmpdir}/netdata-${sysarch}-latest.gz.run" |
| 1091 | if ! grep "netdata-${sysarch}-latest.gz.run" "${ndtmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then |
| 1092 | 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 |
| 1093 | fi |
| 1094 | |
| 1095 | if [ -e /opt/netdata/etc/netdata/.install-type ] ; then |
| 1096 | install_type="$(cat /opt/netdata/etc/netdata/.install-type)" |
| 1097 | else |
| 1098 | install_type="INSTALL_TYPE='legacy-static'" |
| 1099 | fi |
| 1100 | |
| 1101 | # Do not pass any options other than the accept, for now |
| 1102 | # shellcheck disable=SC2086 |
| 1103 | if sh "${ndtmpdir}/netdata-${sysarch}-latest.gz.run" --accept -- ${REINSTALL_OPTIONS} >&3 2>&3; then |
| 1104 | rm -r "${ndtmpdir}" |
| 1105 | else |
| 1106 | info "NOTE: did not remove: ${ndtmpdir}" |
| 1107 | fi |
| 1108 | |
| 1109 | echo "${install_type}" > /opt/netdata/etc/netdata/.install-type |
| 1110 | fi |
| 1111 | |
| 1112 | if [ -e "${PREVDIR}" ]; then |
| 1113 | info "Switching back to ${PREVDIR}" |
| 1114 | cd "${PREVDIR}" |
| 1115 | fi |
| 1116 | [ -n "${logfile}" ] && rm "${logfile}" && logfile= |
| 1117 | |
| 1118 | return 0 |
| 1119 | } |
| 1120 | |
| 1121 | get_new_binpkg_major() { |
| 1122 | case "${pm_cmd}" in |
| 1123 | apt-get) apt-get --just-print upgrade 2>&1 | grep Inst | grep ' netdata ' | cut -f 3 -d ' ' | tr -d '[]' | cut -f 1 -d '.' ;; |
| 1124 | yum) yum check-update netdata | grep -E '^netdata ' | awk '{print $2}' | cut -f 1 -d '.' ;; |
| 1125 | dnf) dnf check-update netdata | grep -E '^netdata ' | awk '{print $2}' | cut -f 1 -d '.' ;; |
| 1126 | zypper) zypper list-updates | grep '| netdata |' | cut -f 5 -d '|' | tr -d ' ' | cut -f 1 -d '.' ;; |
| 1127 | esac |
| 1128 | } |
| 1129 | |
| 1130 | update_binpkg() { |
| 1131 | os_release_file= |
| 1132 | if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then |
| 1133 | os_release_file="/etc/os-release" |
| 1134 | elif [ -s "/usr/lib/os-release" ] && [ -r "/usr/lib/os-release" ]; then |
| 1135 | os_release_file="/usr/lib/os-release" |
| 1136 | else |
| 1137 | fatal "Cannot find an os-release file ..." U000B |
| 1138 | fi |
| 1139 | |
| 1140 | # shellcheck disable=SC1090 |
| 1141 | . "${os_release_file}" |
| 1142 | |
| 1143 | DISTRO="${ID}" |
| 1144 | SYSVERSION="${VERSION_ID}" |
| 1145 | |
| 1146 | supported_compat_names="debian ubuntu centos centos-stream fedora opensuse ol amzn" |
| 1147 | |
| 1148 | if str_in_list "${DISTRO}" "${supported_compat_names}"; then |
| 1149 | DISTRO_COMPAT_NAME="${DISTRO}" |
| 1150 | else |
| 1151 | case "${DISTRO}" in |
| 1152 | opensuse-leap|opensuse-tumbleweed) |
| 1153 | DISTRO_COMPAT_NAME="opensuse" |
| 1154 | ;; |
| 1155 | cloudlinux|almalinux|rocky|rhel) |
| 1156 | DISTRO_COMPAT_NAME="centos" |
| 1157 | ;; |
| 1158 | raspbian) |
| 1159 | SYSARCH="$(uname -m)" |
| 1160 | if [ "$SYSARCH" = "armv7l" ] || [ "$SYSARCH" = "aarch64" ]; then |
| 1161 | DISTRO_COMPAT_NAME="debian" |
| 1162 | fi |
| 1163 | ;; |
| 1164 | *) |
| 1165 | DISTRO_COMPAT_NAME="unknown" |
| 1166 | ;; |
| 1167 | esac |
| 1168 | fi |
| 1169 | |
| 1170 | interactive_opts="" |
| 1171 | env="" |
| 1172 | |
| 1173 | case "${DISTRO_COMPAT_NAME}" in |
| 1174 | debian|ubuntu) |
| 1175 | if [ "${INTERACTIVE}" = "0" ]; then |
| 1176 | upgrade_subcmd="-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold --only-upgrade install" |
| 1177 | interactive_opts="-y" |
| 1178 | env="DEBIAN_FRONTEND=noninteractive" |
| 1179 | else |
| 1180 | upgrade_subcmd="--only-upgrade install" |
| 1181 | fi |
| 1182 | pm_cmd="apt-get" |
| 1183 | repo_subcmd="update" |
| 1184 | install_subcmd="install" |
| 1185 | mark_auto_cmd="apt-mark auto" |
| 1186 | pkg_install_opts="${interactive_opts}" |
| 1187 | repo_update_opts="${interactive_opts}" |
| 1188 | pkg_installed_check="dpkg-query -s" |
| 1189 | INSTALL_TYPE="binpkg-deb" |
| 1190 | if [ -n "${VERSION_CODENAME}" ]; then |
| 1191 | repo_path="${DISTRO_COMPAT_NAME}/${VERSION_CODENAME}" |
| 1192 | fi |
| 1193 | ;; |
| 1194 | centos|centos-stream|fedora|ol|amzn) |
| 1195 | if [ "${INTERACTIVE}" = "0" ]; then |
| 1196 | interactive_opts="-y" |
| 1197 | fi |
| 1198 | if command -v dnf > /dev/null; then |
| 1199 | pm_cmd="dnf" |
| 1200 | repo_subcmd="makecache" |
| 1201 | mark_auto_cmd="dnf mark remove" |
| 1202 | else |
| 1203 | pm_cmd="yum" |
| 1204 | mark_auto_cmd="yumdb set reason dep" |
| 1205 | fi |
| 1206 | upgrade_subcmd="upgrade" |
| 1207 | install_subcmd="install" |
| 1208 | pkg_install_opts="${interactive_opts}" |
| 1209 | repo_update_opts="${interactive_opts}" |
| 1210 | pkg_installed_check="rpm -q" |
| 1211 | INSTALL_TYPE="binpkg-rpm" |
| 1212 | case "${DISTRO_COMPAT_NAME}" in |
| 1213 | amzn) repo_path="amazonlinux/${SYSVERSION}/$(uname -m)" ;; |
| 1214 | centos-stream) repo_path="el/c${SYSVERSION}s/$(uname -m)" ;; |
| 1215 | fedora) repo_path="fedora/${SYSVERSION}/$(uname -m)" ;; |
| 1216 | ol) repo_path="ol/${SYSVERSION}/$(uname -m)" ;; |
| 1217 | *) repo_path="el/$(echo "${SYSVERSION}" | cut -f 1 -d '.')/$(uname -m)" ;; |
| 1218 | esac |
| 1219 | ;; |
| 1220 | opensuse) |
| 1221 | if [ "${INTERACTIVE}" = "0" ]; then |
| 1222 | upgrade_subcmd="--non-interactive update" |
| 1223 | else |
| 1224 | upgrade_subcmd="update" |
| 1225 | fi |
| 1226 | pm_cmd="zypper" |
| 1227 | repo_subcmd="--gpg-auto-import-keys refresh" |
| 1228 | install_subcmd="install" |
| 1229 | mark_auto_cmd="" |
| 1230 | pkg_install_opts="" |
| 1231 | repo_update_opts="" |
| 1232 | pkg_installed_check="rpm -q" |
| 1233 | INSTALL_TYPE="binpkg-rpm" |
| 1234 | repo_path="${DISTRO_COMPAT_NAME}/${SYSVERSION}/$(uname -m)" |
| 1235 | ;; |
| 1236 | *) |
| 1237 | warning "We do not provide native packages for ${DISTRO}." |
| 1238 | return 2 |
| 1239 | ;; |
| 1240 | esac |
| 1241 | |
| 1242 | initial_version="$(get_current_version)" |
| 1243 | |
| 1244 | if [ -n "${repo_subcmd}" ]; then |
| 1245 | # shellcheck disable=SC2086 |
| 1246 | env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000C |
| 1247 | fi |
| 1248 | |
| 1249 | if ${pkg_installed_check} netdata-repo > /dev/null 2>&1; then |
| 1250 | RELEASE_CHANNEL="stable" |
| 1251 | repopkg="netdata-repo" |
| 1252 | elif ${pkg_installed_check} netdata-repo-edge > /dev/null 2>&1; then |
| 1253 | RELEASE_CHANNEL="nightly" |
| 1254 | repopkg="netdata-repo-edge" |
| 1255 | elif echo "${initial_version}" | grep -Eq -- '^[0-9]*[1-9][0-9]*0{5}$'; then # All five final digits are zero and at least one preceeding digit is non-zero. |
| 1256 | RELEASE_CHANNEL="stable" |
| 1257 | elif echo "${initial_version}" | grep -Eq -- '^[0-9]*[1-9][0-9]{0,4}$'; then # At least one of the final five digits is non-zero. |
| 1258 | RELEASE_CHANNEL="nightly" |
| 1259 | else |
| 1260 | RELEASE_CHANNEL="none" |
| 1261 | warning "Unable to determine which release channel is being used on this system, cannot check if packages are still being published." |
| 1262 | fi |
| 1263 | |
| 1264 | if [ -n "${repo_path}" ]; then |
| 1265 | case "${RELEASE_CHANNEL}" in |
| 1266 | stable) check_url="${NETDATA_STABLE_REPO_URL}/${repo_path}/.currently.published" ;; |
| 1267 | nightly) check_url="${NETDATA_NIGHTLY_REPO_URL}/${repo_path}/.currently.published" ;; |
| 1268 | esac |
| 1269 | fi |
| 1270 | |
| 1271 | if [ -n "${check_url}" ]; then |
| 1272 | info "Checking if native packages are still being published for this platform." |
| 1273 | |
| 1274 | set +e |
| 1275 | _safe_download "${check_url}" /dev/null |
| 1276 | ret=$? |
| 1277 | set -e |
| 1278 | |
| 1279 | case "${ret}" in |
| 1280 | 0) info "Native packages are still being published for this platform." ;; |
| 1281 | 1) |
| 1282 | error "" |
| 1283 | error "NETDATA CANNOT BE UPDATED ON THIS SYSTEM!" |
| 1284 | error "" |
| 1285 | error "Native packages are no longer being published for this platform." |
| 1286 | error "" |
| 1287 | error "To update to the latest version of Netdata, you will need to switch to a different install type." |
| 1288 | error "For details on how to do so, see https://learn.netdata.cloud/docs/netdata-agent/installation/linux/switch-install-types-and-release-channels" |
| 1289 | error "" |
| 1290 | fatal "Unable to update due to native packages no longer being published for this platform" U001E |
| 1291 | ;; |
| 1292 | 2) fatal "Failed to connect to Netdata package repositories. This is most likely a result of networking problems with this system." U001F ;; |
| 1293 | 3) fatal "TLS error when trying to connect to Netdata package repositories." U0020 ;; |
| 1294 | 4) fatal "Unknown error when trying to connect to Netdata package repositories." U0021 ;; |
| 1295 | 5) fatal "Client error when trying to connect to Netdata package repositories." U0025 ;; |
| 1296 | 6) fatal "Internal server error when trying to connect to Netdata package repositories." U0026 ;; |
| 1297 | 255) warning "Unable to check whether native packages are being published, wget or curl is required." ;; |
| 1298 | esac |
| 1299 | fi |
| 1300 | |
| 1301 | if [ -n "${repopkg}" ]; then |
| 1302 | # shellcheck disable=SC2086 |
| 1303 | env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} ${repopkg} >&3 2>&3 || fatal "Failed to update Netdata repository config." U000D |
| 1304 | # shellcheck disable=SC2086 |
| 1305 | if [ -n "${repo_subcmd}" ]; then |
| 1306 | env ${env} ${pm_cmd} ${repo_subcmd} ${repo_update_opts} >&3 2>&3 || fatal "Failed to update repository metadata." U000E |
| 1307 | fi |
| 1308 | fi |
| 1309 | |
| 1310 | current_major="$(get_current_version | head -c 4 | awk '{ print $1 + 0 }')" |
| 1311 | latest_major="$(get_new_binpkg_major)" |
| 1312 | |
| 1313 | # current_major == 0 means we could not determine the installed version |
| 1314 | if [ -n "${latest_major}" ] && [ "${current_major}" -ne 0 ] && [ "${latest_major}" -ne "${current_major}" ]; then |
| 1315 | update_safe=0 |
| 1316 | |
| 1317 | for v in ${NETDATA_ACCEPT_MAJOR_VERSIONS}; do |
| 1318 | if [ "${latest_major}" -eq "${v}" ]; then |
| 1319 | update_safe=1 |
| 1320 | break |
| 1321 | fi |
| 1322 | done |
| 1323 | |
| 1324 | if [ "${update_safe}" -eq 0 ]; then |
| 1325 | warn_major_update |
| 1326 | fi |
| 1327 | fi |
| 1328 | |
| 1329 | # shellcheck disable=SC2086 |
| 1330 | env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F |
| 1331 | |
| 1332 | if ${pkg_installed_check} systemd > /dev/null 2>&1; then |
| 1333 | if [ "${NETDATA_NO_SYSTEMD_JOURNAL}" -eq 0 ]; then |
| 1334 | if ! ${pkg_installed_check} netdata-plugin-systemd-journal > /dev/null 2>&1; then |
| 1335 | env ${env} ${pm_cmd} ${install_subcmd} ${pkg_install_opts} netdata-plugin-systemd-journal >&3 2>&3 |
| 1336 | |
| 1337 | if [ -n "${mark_auto_cmd}" ]; then |
| 1338 | # shellcheck disable=SC2086 |
| 1339 | env ${env} ${mark_auto_cmd} netdata-plugin-systemd-journal >&3 2>&3 |
| 1340 | fi |
| 1341 | fi |
| 1342 | fi |
| 1343 | fi |
| 1344 | |
| 1345 | current_version="$(get_current_version)" |
| 1346 | latest_version="$(get_latest_version)" |
| 1347 | |
| 1348 | if [ "${RELEASE_CHANNEL}" != "none" ] && [ "${current_version}" -ne 0 ] && [ "${latest_version}" -ne 0 ]; then |
| 1349 | if [ "${current_version}" -lt "${latest_version}" ] && [ "${initial_version}" -eq "${current_version}" ]; then |
| 1350 | error "" |
| 1351 | error "NETDATA WAS NOT UPDATED!" |
| 1352 | error "" |
| 1353 | error "A newer version of Netdata is available, but the system package manager does not appear to have updated to that version." |
| 1354 | error "" |
| 1355 | error "Most likely, your system is not up to date, and you have it configured in a way that prevents updating one or more of Netdata's dependencies." |
| 1356 | error "Please try updating your system manually and then re-running the Netdata updater before reporting an issue with the update process." |
| 1357 | error "" |
| 1358 | fatal "Package manager did not fully update Netdata despite not reporting a failure." U001D |
| 1359 | fi |
| 1360 | fi |
| 1361 | |
| 1362 | [ -n "${logfile}" ] && rm "${logfile}" && logfile= |
| 1363 | return 0 |
| 1364 | } |
| 1365 | |
| 1366 | # Simple function to encapsulate original updater behavior. |
| 1367 | update_legacy() { |
| 1368 | set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}" |
| 1369 | case "${IS_NETDATA_STATIC_BINARY}" in |
| 1370 | yes) update_static && exit 0 ;; |
| 1371 | *) update_build && exit 0 ;; |
| 1372 | esac |
| 1373 | } |
| 1374 | |
| 1375 | logfile= |
| 1376 | ndtmpdir= |
| 1377 | |
| 1378 | trap cleanup EXIT |
| 1379 | |
| 1380 | if [ -t 2 ] || [ "${GITHUB_ACTIONS}" ]; then |
| 1381 | # we are running on a terminal or under CI |
| 1382 | # open fd 3 and send it to stderr |
| 1383 | exec 3>&2 |
| 1384 | else |
| 1385 | # we are headless |
| 1386 | # create a temporary file for the log |
| 1387 | logfile="$(mktemp -t netdata-updater.log.XXXXXX)" |
| 1388 | # open fd 3 and send it to logfile |
| 1389 | exec 3> "${logfile}" |
| 1390 | fi |
| 1391 | |
| 1392 | : "${ENVIRONMENT_FILE:=THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT}" |
| 1393 | |
| 1394 | if [ "${ENVIRONMENT_FILE}" = "THIS_SHOULD_BE_REPLACED_BY_INSTALLER_SCRIPT" ]; then |
| 1395 | if [ -r "${script_dir}/../../../etc/netdata/.environment" ] || [ -r "${script_dir}/../../../etc/netdata/.install-type" ]; then |
| 1396 | ENVIRONMENT_FILE="${script_dir}/../../../etc/netdata/.environment" |
| 1397 | elif [ -r "/etc/netdata/.environment" ] || [ -r "/etc/netdata/.install-type" ]; then |
| 1398 | ENVIRONMENT_FILE="/etc/netdata/.environment" |
| 1399 | elif [ -r "/opt/netdata/etc/netdata/.environment" ] || [ -r "/opt/netdata/etc/netdata/.install-type" ]; then |
| 1400 | ENVIRONMENT_FILE="/opt/netdata/etc/netdata/.environment" |
| 1401 | else |
| 1402 | 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)" |
| 1403 | 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)" |
| 1404 | if [ -r "${envpath}" ]; then |
| 1405 | ENVIRONMENT_FILE="${envpath}" |
| 1406 | elif [ -r "${itpath}" ]; then |
| 1407 | ENVIRONMENT_FILE="$(dirname "${itpath}")/.environment" |
| 1408 | else |
| 1409 | fatal "Cannot find environment file or install type file, unable to update." U0010 |
| 1410 | fi |
| 1411 | fi |
| 1412 | fi |
| 1413 | |
| 1414 | if [ -r "${ENVIRONMENT_FILE}" ] ; then |
| 1415 | # shellcheck source=/dev/null |
| 1416 | . "${ENVIRONMENT_FILE}" || fatal "Failed to source ${ENVIRONMENT_FILE}" U0014 |
| 1417 | fi |
| 1418 | |
| 1419 | if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then |
| 1420 | # shellcheck source=/dev/null |
| 1421 | . "$(dirname "${ENVIRONMENT_FILE}")/.install-type" || fatal "Failed to source $(dirname "${ENVIRONMENT_FILE}")/.install-type" U0015 |
| 1422 | fi |
| 1423 | |
| 1424 | UPDATER_CONFIG_PATH="$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf" |
| 1425 | if [ -r "${UPDATER_CONFIG_PATH}" ]; then |
| 1426 | # shellcheck source=/dev/null |
| 1427 | . "${UPDATER_CONFIG_PATH}" |
| 1428 | fi |
| 1429 | |
| 1430 | [ -z "${NETDATA_ACCEPT_MAJOR_VERSIONS}" ] && NETDATA_ACCEPT_MAJOR_VERSIONS="${NETDATA_DEFAULT_ACCEPT_MAJOR_VERSIONS}" |
| 1431 | |
| 1432 | while [ -n "${1}" ]; do |
| 1433 | case "${1}" in |
| 1434 | --not-running-from-cron) NETDATA_NOT_RUNNING_FROM_CRON=1 ;; |
| 1435 | --no-updater-self-update) NETDATA_NO_UPDATER_SELF_UPDATE=1 ;; |
| 1436 | --force-update) NETDATA_FORCE_UPDATE=1 ;; |
| 1437 | --non-interactive) INTERACTIVE=0 ;; |
| 1438 | --interactive) INTERACTIVE=1 ;; |
| 1439 | --offline-install-source) |
| 1440 | NETDATA_OFFLINE_INSTALL_SOURCE="${2}" |
| 1441 | shift 1 |
| 1442 | ;; |
| 1443 | --tmpdir-path) |
| 1444 | NETDATA_TMPDIR_PATH="${2}" |
| 1445 | shift 1 |
| 1446 | ;; |
| 1447 | --enable-auto-updates) |
| 1448 | enable_netdata_updater "${2}" |
| 1449 | exit $? |
| 1450 | ;; |
| 1451 | --disable-auto-updates) |
| 1452 | disable_netdata_updater |
| 1453 | exit $? |
| 1454 | ;; |
| 1455 | --auto-update-status) |
| 1456 | auto_update_status |
| 1457 | exit 0 |
| 1458 | ;; |
| 1459 | *) fatal "Unrecognized option ${1}" U001A ;; |
| 1460 | esac |
| 1461 | |
| 1462 | shift 1 |
| 1463 | done |
| 1464 | |
| 1465 | if [ -n "${NETDATA_OFFLINE_INSTALL_SOURCE}" ]; then |
| 1466 | NETDATA_NO_UPDATER_SELF_UPDATE=1 |
| 1467 | NETDATA_UPDATER_JITTER=0 |
| 1468 | NETDATA_FORCE_UPDATE=1 |
| 1469 | fi |
| 1470 | |
| 1471 | # If we seem to be running under anacron, act as if we’re not running from cron. |
| 1472 | # This is mostly to disable jitter, which should not be needed when run from anacron. |
| 1473 | if running_under_anacron; then |
| 1474 | NETDATA_NOT_RUNNING_FROM_CRON="${NETDATA_NOT_RUNNING_FROM_CRON:-1}" |
| 1475 | fi |
| 1476 | |
| 1477 | # Random sleep to alleviate stampede effect of Agents upgrading |
| 1478 | # and disconnecting/reconnecting at the same time (or near to). |
| 1479 | # But only we're not a controlling terminal (tty) |
| 1480 | # Randomly sleep between 1s and 60m |
| 1481 | if [ ! -t 1 ] && \ |
| 1482 | [ -z "${GITHUB_ACTIONS}" ] && \ |
| 1483 | [ -z "${NETDATA_NOT_RUNNING_FROM_CRON}" ] && \ |
| 1484 | is_integer "${NETDATA_UPDATER_JITTER}" && \ |
| 1485 | [ "${NETDATA_UPDATER_JITTER}" -gt 1 ]; then |
| 1486 | rnd="$(awk " |
| 1487 | BEGIN { srand() |
| 1488 | printf(\"%d\\n\", ${NETDATA_UPDATER_JITTER} * rand()) |
| 1489 | }")" |
| 1490 | sleep $(((rnd % NETDATA_UPDATER_JITTER) + 1)) |
| 1491 | fi |
| 1492 | |
| 1493 | # We dont expect to find lib dir variable on older installations, so load this path if none found |
| 1494 | export NETDATA_LIB_DIR="${NETDATA_LIB_DIR:-${NETDATA_PREFIX}/var/lib/netdata}" |
| 1495 | |
| 1496 | # Source the tarball checksum, if not already available from environment (for existing installations with the old logic) |
| 1497 | [ -z "${NETDATA_TARBALL_CHECKSUM}" ] && [ -f "${NETDATA_LIB_DIR}/netdata.tarball.checksum" ] && NETDATA_TARBALL_CHECKSUM="$(cat "${NETDATA_LIB_DIR}/netdata.tarball.checksum")" |
| 1498 | |
| 1499 | if echo "$INSTALL_TYPE" | grep -qv ^binpkg && [ "${INSTALL_UID}" != "$(id -u)" ]; then |
| 1500 | 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 |
| 1501 | fi |
| 1502 | |
| 1503 | self_update |
| 1504 | |
| 1505 | dev_null_fix |
| 1506 | |
| 1507 | # shellcheck disable=SC2153 |
| 1508 | case "${INSTALL_TYPE}" in |
| 1509 | *-build) |
| 1510 | validate_environment_file |
| 1511 | set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}" |
| 1512 | update_build && exit 0 |
| 1513 | ;; |
| 1514 | *-static*) |
| 1515 | validate_environment_file |
| 1516 | set_tarball_urls "${RELEASE_CHANNEL}" "${IS_NETDATA_STATIC_BINARY}" |
| 1517 | update_static && exit 0 |
| 1518 | ;; |
| 1519 | *binpkg*) update_binpkg && exit 0 ;; |
| 1520 | "") # Fallback case for no `.install-type` file. This just works like the old install type detection. |
| 1521 | validate_environment_file |
| 1522 | update_legacy |
| 1523 | ;; |
| 1524 | custom) |
| 1525 | # At this point, we _should_ have a valid `.environment` file, but it's best to just check. |
| 1526 | # If we do, then behave like the legacy updater. |
| 1527 | if validate_environment_file && [ -n "${IS_NETDATA_STATIC_BINARY}" ]; then |
| 1528 | update_legacy |
| 1529 | else |
| 1530 | fatal "This script does not support updating custom installations without valid environment files." U0012 |
| 1531 | fi |
| 1532 | ;; |
| 1533 | oci) fatal "This script does not support updating Netdata inside our official Docker containers, please instead update the container itself." U0013 ;; |
| 1534 | *) fatal "Unrecognized installation type (${INSTALL_TYPE}), unable to update." U0014 ;; |
| 1535 | esac |