Files
zabbix-agent/install-zabbix-agent2-ubuntu.sh
T

149 lines
6.7 KiB
Bash
Executable File

#!/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