One-shot Ubuntu agent2 installer (active checks)
This commit is contained in:
Executable
+148
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env bash
|
||||
# install-zabbix-agent2-ubuntu.sh — one-shot Zabbix agent2 (ACTIVE checks)
|
||||
# installer for Ubuntu. Public-safe: nothing about any specific environment
|
||||
# is baked in; the server address comes from the required --server flag.
|
||||
#
|
||||
# Idempotent — safe to re-run. What it does:
|
||||
# 1. Installs Zabbix agent2 from the official Zabbix apt repo
|
||||
# 2. Writes an ACTIVE-check config (agent connects OUT to the server;
|
||||
# no inbound ports, no firewall changes needed — works behind NAT):
|
||||
# ServerActive=<server from --server>
|
||||
# Server=127.0.0.1,<server host>
|
||||
# Hostname=<--hostname, else the short system hostname>
|
||||
# 3. Enables + restarts the service and sanity-checks the connection.
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./install-zabbix-agent2-ubuntu.sh --server 203.0.113.10
|
||||
# sudo ./install-zabbix-agent2-ubuntu.sh --server 203.0.113.10:10051 --hostname web01
|
||||
# sudo ./install-zabbix-agent2-ubuntu.sh web01 --server 203.0.113.10 # positional hostname
|
||||
#
|
||||
# One-liner (no local copy needed):
|
||||
# curl -fsSL <repo-url>/install-zabbix-agent2-ubuntu.sh | sudo bash -s -- --server 203.0.113.10
|
||||
#
|
||||
# After it succeeds, the host must exist on the Zabbix server with the EXACT
|
||||
# same technical name (an active-agent template, e.g. "Linux by Zabbix agent
|
||||
# active"). The script warns if the agent cannot fetch its config yet — that
|
||||
# warning clears by itself within ~a minute of the host being created.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ZABBIX_MAJOR="7.4"
|
||||
CONF="/etc/zabbix/zabbix_agent2.conf"
|
||||
LOG="/var/log/zabbix/zabbix_agent2.log"
|
||||
|
||||
say() { echo "[zabbix-agent2] $*"; }
|
||||
die() { echo "[zabbix-agent2] ERROR: $*" >&2; exit 1; }
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: sudo $0 --server HOST[:PORT] [--hostname NAME] [--major X.Y]
|
||||
|
||||
--server HOST[:PORT] required — Zabbix server/proxy for active checks
|
||||
(IP or DNS name; port defaults to 10051)
|
||||
--hostname NAME Zabbix host name (default: short system hostname;
|
||||
MUST equal the technical host name on the server)
|
||||
--major X.Y Zabbix major version from the official repo
|
||||
(default: ${ZABBIX_MAJOR}; use your server's version)
|
||||
NAME (positional) shorthand for --hostname NAME
|
||||
EOF
|
||||
}
|
||||
|
||||
# ---- args --------------------------------------------------------------------
|
||||
SERVER_RAW=""
|
||||
HOSTNAME_ARG=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--server) SERVER_RAW="${2:?}"; shift 2 ;;
|
||||
-n|--hostname) HOSTNAME_ARG="${2:?}"; shift 2 ;;
|
||||
--major) ZABBIX_MAJOR="${2:?}"; shift 2 ;;
|
||||
-h|--help) tail -n +2 "$0" | grep '^#' | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
*) HOSTNAME_ARG="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$SERVER_RAW" ] || { usage; die "--server is required"; }
|
||||
[[ "$ZABBIX_MAJOR" =~ ^[0-9]+\.[0-9]+$ ]] || die "--major must look like 7.4, not '${ZABBIX_MAJOR}'"
|
||||
|
||||
# server HOST[:PORT] -> SA_HOST / SA_PORT (plain IPv4 or DNS name)
|
||||
case "$SERVER_RAW" in
|
||||
*:*) SA_HOST="${SERVER_RAW%%:*}"; SA_PORT="${SERVER_RAW##*:}" ;;
|
||||
*) SA_HOST="$SERVER_RAW"; SA_PORT="10051" ;;
|
||||
esac
|
||||
[[ "$SA_PORT" =~ ^[0-9]+$ ]] || die "bad port in --server '${SERVER_RAW}' (IPv6 literals: give a DNS name instead)"
|
||||
[ -n "$SA_HOST" ] && [ "$SA_HOST" != "$SA_PORT" ] || die "bad --server '${SERVER_RAW}'"
|
||||
SA_ADDR="$SA_HOST"; [ "$SA_PORT" = "10051" ] || SA_ADDR="${SA_HOST}:${SA_PORT}"
|
||||
|
||||
ZBX_HOSTNAME="${HOSTNAME_ARG:-$(hostname -s)}"
|
||||
case "$ZBX_HOSTNAME" in
|
||||
*[!A-Za-z0-9._-]*) die "hostname '${ZBX_HOSTNAME}' has odd chars — pass --hostname <exact Zabbix technical name>" ;;
|
||||
esac
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "run as root (sudo)"
|
||||
|
||||
# ---- platform ----------------------------------------------------------------
|
||||
. /etc/os-release
|
||||
[ "${ID:-}" = "ubuntu" ] || die "Ubuntu only (found '${ID:-unknown}'); for Debian, swap 'ubuntu' for 'debian' in the repo URL below"
|
||||
say "Ubuntu ${VERSION_ID} (${PRETTY_NAME:-ubuntu}) → server ${SA_ADDR}, hostname '${ZBX_HOSTNAME}'"
|
||||
|
||||
# ---- 1. repo + package ---------------------------------------------------------
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
APT_OPTS="-y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold"
|
||||
|
||||
apt-get update -qq
|
||||
apt-get install -qq $APT_OPTS ca-certificates curl >/dev/null
|
||||
|
||||
DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_MAJOR}/release/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_${ZABBIX_MAJOR}+ubuntu${VERSION_ID}_all.deb"
|
||||
curl -fsSI -o /dev/null "$DEB_URL" || die "no zabbix-release for Ubuntu ${VERSION_ID} (check --major); looked at ${DEB_URL}"
|
||||
curl -fsS -o /tmp/zabbix-release.deb "$DEB_URL"
|
||||
dpkg -i /tmp/zabbix-release.deb || apt-get -f install -qq $APT_OPTS
|
||||
rm -f /tmp/zabbix-release.deb
|
||||
apt-get update -qq
|
||||
apt-get install -qq $APT_OPTS zabbix-agent2
|
||||
say "installed: $(zabbix_agent2 -V | head -1)"
|
||||
|
||||
# ---- 2. config (replace-or-append: one authoritative line per key) -------------
|
||||
if [ -f "$CONF" ] && [ ! -f "${CONF}.pre-install.bak" ]; then
|
||||
cp -a "$CONF" "${CONF}.pre-install.bak"
|
||||
say "backed up stock config to ${CONF}.pre-install.bak"
|
||||
fi
|
||||
|
||||
set_conf() { # file key value — drop every existing (commented) line, append ours
|
||||
sed -i -E "/^[[:space:]]*#?[[:space:]]*${2}=/d" "$1"
|
||||
echo "${2}=${3}" >> "$1"
|
||||
}
|
||||
[ -f "$CONF" ] || die "expected ${CONF} to exist after install"
|
||||
|
||||
set_conf "$CONF" ServerActive "$SA_ADDR"
|
||||
set_conf "$CONF" Server "127.0.0.1,${SA_HOST}"
|
||||
set_conf "$CONF" Hostname "$ZBX_HOSTNAME"
|
||||
|
||||
# ---- 3. service + sanity -------------------------------------------------------
|
||||
systemctl enable zabbix-agent2 >/dev/null
|
||||
systemctl restart zabbix-agent2
|
||||
sleep 3
|
||||
systemctl is-active --quiet zabbix-agent2 || { journalctl -u zabbix-agent2 -n 20 --no-pager; die "service not active"; }
|
||||
zabbix_agent2 -t agent.version >/dev/null 2>&1 || die "agent fails to parse config / answer local test"
|
||||
|
||||
# Active-check reachability: give the agent ~20s to fetch its first config.
|
||||
loggrep() { # pattern — agent log file, else the journal
|
||||
if [ -r "$LOG" ]; then grep -Eqi "$1" "$LOG"; else journalctl -u zabbix-agent2 --since '-2 min' | grep -Eqi "$1"; fi
|
||||
}
|
||||
WARN=""
|
||||
for _ in $(seq 1 10); do
|
||||
if loggrep 'started to fail|cannot obtain|no active checks|host not found'; then WARN=1; break; fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo
|
||||
say "done. config:"
|
||||
grep -E '^(Server|ServerActive|Hostname)=' "$CONF" | sed 's/^/ /'
|
||||
if [ -n "$WARN" ]; then
|
||||
say "WARNING: agent cannot fetch its config yet:"
|
||||
if [ -r "$LOG" ]; then tail -n 4 "$LOG" | sed 's/^/ /'
|
||||
else journalctl -u zabbix-agent2 -n 4 --no-pager | sed 's/^/ /'; fi
|
||||
say "expected if the host doesn't exist on the Zabbix server yet — create it"
|
||||
say "with the EXACT technical name '${ZBX_HOSTNAME}' and an active-agent"
|
||||
say "template; the warning clears by itself within a minute."
|
||||
else
|
||||
say "active checks OK (no connection errors in the agent log)."
|
||||
fi
|
||||
Reference in New Issue
Block a user