#!/usr/bin/env bash # ------------------------------------------------------------------ # WeComCenter / ROMAN 定制中心 — one-step installer # # Usage: # ./install.sh # auto-detect the running zabbix web container # ./install.sh /path/to/modules # copy into a plain (non-docker) modules dir # # It will: # 1) copy the WecomCenter module next to the Zabbix frontend, # 2) fix permissions (module readable, assets/l2topology writable for the config mirror), # 3) create the two L2 tables if a MySQL container is reachable (idempotent), # 4) install the L2 collector into /opt/zabbix/l2collector and (optionally) crontab. # # Env knobs: # MYSQL_CONTAINER (default: auto / zabbix-mysql) # MYSQL_ROOT_PASSWORD (default: CobcoIT132) # MYSQL_DATABASE (default: zabbix) # COLLECTOR_DIR (default: /opt/zabbix/l2collector) # INSTALL_CRON=0 to skip installing crontab entries. # ------------------------------------------------------------------ set -euo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" SRC="$HERE/WecomCenter" MYSQL_CONTAINER="${MYSQL_CONTAINER:-}" MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-CobcoIT132}" MYSQL_DATABASE="${MYSQL_DATABASE:-zabbix}" COLLECTOR_DIR="${COLLECTOR_DIR:-/opt/zabbix/l2collector}" INSTALL_CRON="${INSTALL_CRON:-1}" if [ ! -d "$SRC" ]; then echo "ERROR: WecomCenter folder not found next to install.sh" >&2 exit 1 fi DEST="" CONTAINER="" if [ $# -ge 1 ]; then DEST="$1" mkdir -p "$DEST" rm -rf "$DEST/WecomCenter" cp -r "$SRC" "$DEST/WecomCenter" echo "OK: copied to $DEST/WecomCenter" else CONTAINER="$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE 'zabbix.*(web|nginx|apache|frontend)' | head -n1 || true)" if [ -z "$CONTAINER" ]; then echo "ERROR: no running Zabbix frontend container detected." >&2 echo " Pass the modules directory explicitly, e.g.: ./install.sh /opt/zabbix/zabbix-server/web-modules" >&2 exit 1 fi docker cp "$SRC" "$CONTAINER:/usr/share/zabbix/modules/" echo "OK: copied into container '$CONTAINER' -> /usr/share/zabbix/modules/WecomCenter" fi # ---- permissions: module readable everywhere, config dir writable by php ---- if [ -n "$DEST" ]; then chmod -R a+rX "$DEST/WecomCenter" 2>/dev/null || true chmod -R 777 "$DEST/WecomCenter/assets/l2topology" 2>/dev/null || true else docker exec "$CONTAINER" sh -c 'M=/usr/share/zabbix/modules/WecomCenter; chmod -R a+rX "$M"; chmod -R 777 "$M/assets/l2topology"' 2>/dev/null || true fi # ---- create L2 tables (idempotent) ---- if [ -z "$MYSQL_CONTAINER" ]; then MYSQL_CONTAINER="$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE 'zabbix.*(mysql|db|mariadb)' | head -n1 || true)" fi if [ -n "$MYSQL_CONTAINER" ]; then echo "Ensuring L2 tables in container '$MYSQL_CONTAINER' ..." docker exec -i "$MYSQL_CONTAINER" mysql -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" <<'SQL' || echo "WARN: could not create tables automatically (page will retry on first load)." CREATE TABLE IF NOT EXISTS l2_topology_history ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, ts BIGINT UNSIGNED NOT NULL, captured_at DATETIME NOT NULL, stats TEXT NOT NULL, snapshot MEDIUMBLOB NOT NULL, PRIMARY KEY (id), KEY idx_l2_ts (ts) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE IF NOT EXISTS l2_topology_config ( id TINYINT UNSIGNED NOT NULL, config LONGTEXT NOT NULL, updated DATETIME NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; SQL else echo "WARN: no MySQL container detected; skip table creation (page auto-creates on load)." fi # ---- install collector on the host (needs SNMP access to switches) ---- COLLECTOR_SRC="$HERE/../collector" if [ -d "$COLLECTOR_SRC" ] && [ -d /opt/zabbix ]; then echo "Installing L2 collector to $COLLECTOR_DIR ..." mkdir -p "$COLLECTOR_DIR" cp -f "$COLLECTOR_SRC"/*.py "$COLLECTOR_DIR"/ 2>/dev/null || true cp -f "$COLLECTOR_SRC"/*.sh "$COLLECTOR_DIR"/ 2>/dev/null || true chmod +x "$COLLECTOR_DIR"/*.sh 2>/dev/null || true # mirror config next to the module so collectors can read it CFG="$(dirname "$SRC")/WecomCenter/assets/l2topology/config.json" if [ -f "$CFG" ]; then cp -f "$CFG" "$COLLECTOR_DIR/config.json"; fi if [ "$INSTALL_CRON" = "1" ] && command -v crontab >/dev/null 2>&1; then { crontab -l 2>/dev/null | grep -v l2collector || true echo "*/5 * * * * /bin/bash $COLLECTOR_DIR/run_full.sh >/dev/null 2>&1" echo "* * * * * /bin/bash $COLLECTOR_DIR/refresh_alarms.sh >/dev/null 2>&1" } | crontab - || echo "WARN: crontab install failed" echo "OK: crontab entries installed (full every 5 min, alarm refresh every 1 min)." fi else echo "INFO: collector/ not found next to install.sh or /opt/zabbix missing; skip collector install." fi echo echo "Done. Next steps:" echo " 1) Zabbix -> Administration -> ROMAN 定制中心 (module should already be enabled by compose)" echo " If not listed: Administration -> Modules -> 'Scan directory' -> Enable 'WecomCenter'" echo " 2) Administration -> ROMAN 定制中心 -> 'L2 拓扑' tab: choose templates / colours / intervals -> Save" echo " 3) Monitoring -> L2 Topology (or: /zabbix.php?action=l2.topology.view)" echo " 4) Run once: sudo bash $COLLECTOR_DIR/run_full.sh (log: /var/log/l2collector.log)"