#!/usr/bin/env bash # install_tiny_agent.sh — Install Prometheus exporters (node_exporter / process-exporter) # Debian/Ubuntu. Run as root. set -euo pipefail # ========= Defaults (env overridable) ========= NODE_EXP_VER="${NODE_EXP_VER:-1.8.2}" PROC_EXP_VER="${PROC_EXP_VER:-0.7.10}" INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" VERIFY="${VERIFY:-1}" # 1=verify sha256 for node_exporter CURL_INSECURE="${CURL_INSECURE:-0}" # 1=allow curl -k BIND_ADDR="${BIND_ADDR:-0.0.0.0}" # listen address for both exporters NODE_PORT="${NODE_PORT:-9100}" PROC_PORT="${PROC_PORT:-9256}" # ========= Arg parsing ========= MODE="both" # node/process/both usage() { cat <&2; exit 1 ;; esac } curl_get() { local u="$1" o="$2"; local extra=() [[ "$CURL_INSECURE" = "1" ]] && extra+=(-k) curl -fL --retry 6 --retry-all-errors --connect-timeout 20 --max-time 600 \ --speed-time 30 --speed-limit 10240 -o "$o" "${extra[@]}" "$u" } cleanup_bad() { [[ -f "$1" ]] && rm -f "$1"; } install_binary() { install -m 0755 "$1" "$2"; } ensure_user() { id -u "$1" >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin "$1"; } download_with_fallback() { # $1: array var name of URLs; $2: out path local -n arr="$1"; local out="$2"; local ok=0 for u in "${arr[@]}"; do echo "→ Download: $u" if curl_get "$u" "$out"; then ok=1; break; else echo "WARN: fail $u"; fi done [[ $ok -eq 1 ]] || { echo "ERROR: all mirrors failed for $out"; exit 2; } } verify_sha256() { # $1=tar.gz; $2=sum_url; $3=filename local f="$1" url="$2" fname="$3" sums sums="$(mktemp)"; trap 'rm -f "$sums"' RETURN echo "→ Fetch checksum list"; if ! curl_get "$url" "$sums"; then echo "WARN: cannot fetch checksums; skip verification"; return 0; fi local expect; expect="$(grep -E " ${fname}$" "$sums" | awk '{print $1}')" [[ -z "${expect:-}" ]] && { echo "WARN: checksum entry not found; skip"; return 0; } local got; got="$(sha256sum "$f" | awk '{print $1}')" if [[ "$got" != "$expect" ]]; then echo "ERROR: sha256 mismatch"; return 1; fi } # ========= Installers ========= install_node_exporter() { local ARCH TAR NAME TARPATH SUMURL TMP ARCH="$(arch_norm)" NAME="node_exporter-${NODE_EXP_VER}.linux-${ARCH}" TAR="${NAME}.tar.gz" SUMURL="https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXP_VER}/sha256sums.txt" TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' RETURN echo "[*] Installing node_exporter v${NODE_EXP_VER} (${ARCH})" local URLS=( "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXP_VER}/${TAR}" ) TARPATH="${TMP}/${TAR}" download_with_fallback URLS "$TARPATH" if [[ "$VERIFY" = "1" ]]; then if ! verify_sha256 "$TARPATH" "$SUMURL" "$TAR"; then cleanup_bad "$TARPATH"; echo "Retry downloading due to checksum mismatch..." download_with_fallback URLS "$TARPATH" verify_sha256 "$TARPATH" "$SUMURL" "$TAR" || { echo "FATAL: checksum still bad"; exit 3; } fi fi echo "→ Extract & install" tar xzf "$TARPATH" -C "$TMP" || { cleanup_bad "$TARPATH"; echo "FATAL: tar failed"; exit 4; } install_binary "$TMP/$NAME/node_exporter" "$INSTALL_DIR/node_exporter" ensure_user node_exporter cat >/etc/systemd/system/node_exporter.service </dev/null 2>&1 || \ echo "NOTE: can't fetch metrics (ok if bound to 127.0.0.1 and you run remotely)." } install_process_exporter() { local ARCH TAR NAME TMP ARCH="$(arch_norm)" NAME="process-exporter-${PROC_EXP_VER}.linux-${ARCH}" TAR="${NAME}.tar.gz" TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' RETURN echo "[*] Installing process-exporter v${PROC_EXP_VER} (${ARCH})" local URLS=( "https://github.com/ncabatoff/process-exporter/releases/download/v${PROC_EXP_VER}/${TAR}" ) local TARPATH="${TMP}/${TAR}" download_with_fallback URLS "$TARPATH" echo "→ Extract & install" tar xzf "$TARPATH" -C "$TMP" || { cleanup_bad "$TARPATH"; echo "FATAL: tar failed"; exit 5; } install_binary "$TMP/$NAME/process-exporter" "$INSTALL_DIR/process-exporter" ensure_user process_exporter # Minimal config: group by executable name; you can refine later cat >/etc/process-exporter.yml <<'YML' process_names: - name: "{{.Comm}}" cmdline: [".+"] YML chown process_exporter:process_exporter /etc/process-exporter.yml chmod 0644 /etc/process-exporter.yml cat >/etc/systemd/system/process-exporter.service </dev/null 2>&1 || \ echo "NOTE: can't fetch metrics (ok if bound to 127.0.0.1 and you run remotely)." } # ========= Execute ========= case "$MODE" in node) install_node_exporter ;; process) install_process_exporter ;; both) install_node_exporter; install_process_exporter ;; *) echo "Invalid MODE: $MODE"; exit 1 ;; esac echo "Done."