Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| temp [2026/02/27 21:06] – jdlewis | temp [2026/03/09 18:51] (current) – jdlewis | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | < | + | . |
| - | # | + | |
| - | set -euo pipefail | + | |
| - | + | ||
| - | # ─── Config ─────────────────────────────────────────────────────────────────── | + | |
| - | SCRIPT_DIR=" | + | |
| - | HOSTS_FILE=" | + | |
| - | SITES_FILE=" | + | |
| - | OUTPUT_FILE="/ | + | |
| - | + | ||
| - | # ─── Trim leading/ | + | |
| - | trim() { sed ' | + | |
| - | + | ||
| - | # ─── Colour palette (cycles if more sites than colours) ─────────────────────── | + | |
| - | palette=("# | + | |
| - | + | ||
| - | # ─── Load sites.csv ─────────────────────────────────────────────────────────── | + | |
| - | declare -A site_map | + | |
| - | declare -A site_color_map | + | |
| - | declare -a site_order=() | + | |
| - | color_idx=0 | + | |
| - | header=true | + | |
| - | + | ||
| - | while IFS=, read -r prefix site; do | + | |
| - | $header && { header=false; | + | |
| - | prefix=" | + | |
| - | site=" | + | |
| - | site_map[" | + | |
| - | if [[ -z " | + | |
| - | site_color_map[" | + | |
| - | site_order+=(" | + | |
| - | (( color_idx++ )) || true | + | |
| - | fi | + | |
| - | done < " | + | |
| - | + | ||
| - | # ─── DNS lookup ─────────────────────────────────────────────────────────────── | + | |
| - | resolve() { | + | |
| - | # getent uses the system resolver (same as applications) | + | |
| - | getent hosts " | + | |
| - | } | + | |
| - | + | ||
| - | get_site() { | + | |
| - | local ip=" | + | |
| - | local oct3 oct2 oct1 | + | |
| - | oct3=" | + | |
| - | oct2=" | + | |
| - | oct1=" | + | |
| - | # Match longest prefix first (most specific wins) | + | |
| - | if [[ -n " | + | |
| - | elif [[ -n " | + | |
| - | elif [[ -n " | + | |
| - | else echo " | + | |
| - | fi | + | |
| - | } | + | |
| - | + | ||
| - | # ─── Ping test (1 packet, 2s timeout) ──────────────────────────────────────── | + | |
| - | ping_host() { | + | |
| - | local result time | + | |
| - | result=$(ping -c 1 -w 2 " | + | |
| - | time=$(echo " | + | |
| - | if [[ -n " | + | |
| - | printf " | + | |
| - | else | + | |
| - | echo " | + | |
| - | fi | + | |
| - | } | + | |
| - | + | ||
| - | # ─── Process hosts.csv ──────────────────────────────────────────────────────── | + | |
| - | declare -a rows=() | + | |
| - | declare -A site_counts | + | |
| - | total=0 | + | |
| - | error_count=0 | + | |
| - | header=true | + | |
| - | + | ||
| - | while IFS=, read -r hostname name; do | + | |
| - | $header && { header=false; | + | |
| - | hostname=" | + | |
| - | name=" | + | |
| - | + | ||
| - | ip=" | + | |
| - | + | ||
| - | if [[ -z " | + | |
| - | site=" | + | |
| - | color="# | + | |
| - | ip_display=" | + | |
| - | ping_status=" | + | |
| - | ping_avg="" | + | |
| - | (( error_count++ )) || true | + | |
| - | else | + | |
| - | site=" | + | |
| - | color=" | + | |
| - | ip_display=" | + | |
| - | site_counts[" | + | |
| - | ping_result=" | + | |
| - | ping_status=" | + | |
| - | ping_avg=" | + | |
| - | fi | + | |
| - | + | ||
| - | rows+=(" | + | |
| - | (( total++ )) || true | + | |
| - | done < " | + | |
| - | + | ||
| - | last_updated=" | + | |
| - | + | ||
| - | # ─── Build summary cards ────────────────────────────────────────────────────── | + | |
| - | site_cards="" | + | |
| - | for site in " | + | |
| - | count=" | + | |
| - | [[ " | + | |
| - | col=" | + | |
| - | site_cards+=" | + | |
| - | <div class=\" | + | |
| - | <div class=\" | + | |
| - | <div class=\" | + | |
| - | <div class=\" | + | |
| - | </ | + | |
| - | done | + | |
| - | + | ||
| - | if [[ " | + | |
| - | site_cards+=" | + | |
| - | <div class=\" | + | |
| - | <div class=\" | + | |
| - | <div class=\" | + | |
| - | <div class=\" | + | |
| - | </ | + | |
| - | fi | + | |
| - | + | ||
| - | # ─── Build table rows ───────────────────────────────────────────────────────── | + | |
| - | table_rows="" | + | |
| - | for row in " | + | |
| - | IFS=' | + | |
| - | if [[ " | + | |
| - | ip_html="< | + | |
| - | else | + | |
| - | ip_html="< | + | |
| - | fi | + | |
| - | if [[ " | + | |
| - | ping_html="< | + | |
| - | else | + | |
| - | ping_html="< | + | |
| - | fi | + | |
| - | table_rows+=" | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | done | + | |
| - | + | ||
| - | # ─── Write HTML ─────────────────────────────────────────────────────────────── | + | |
| - | mkdir -p " | + | |
| - | + | ||
| - | cat > " | + | |
| - | < | + | |
| - | <html lang=" | + | |
| - | < | + | |
| - | <meta charset=" | + | |
| - | <meta name=" | + | |
| - | < | + | |
| - | < | + | |
| - | *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | + | |
| - | body { | + | |
| - | font-family: | + | |
| - | background: #0f172a; color: #e2e8f0; | + | |
| - | min-height: 100vh; padding: 2rem 1rem; | + | |
| - | } | + | |
| - | .container { max-width: 960px; margin: 0 auto; } | + | |
| - | header { | + | |
| - | display: flex; align-items: | + | |
| - | flex-wrap: wrap; gap: 1rem; margin-bottom: | + | |
| - | } | + | |
| - | .header-left h1 { font-size: 1.6rem; font-weight: | + | |
| - | .header-left p { font-size: 0.8rem; color: #64748b; margin-top: 0.2rem; } | + | |
| - | .summary { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: | + | |
| - | .card { | + | |
| - | background: #1e293b; border: 1px solid #334155; | + | |
| - | border-radius: | + | |
| - | } | + | |
| - | .card-label { font-size: 0.7rem; text-transform: | + | |
| - | .card-value { font-size: 1.8rem; font-weight: | + | |
| - | .card-sub | + | |
| - | .table-wrap { background: #1e293b; border: 1px solid #334155; border-radius: | + | |
| - | table { width: 100%; border-collapse: | + | |
| - | thead { background: #0f172a; } | + | |
| - | th { | + | |
| - | text-align: left; padding: 0.75rem 1rem; font-size: 0.7rem; | + | |
| - | text-transform: | + | |
| - | } | + | |
| - | td { padding: 0.85rem 1rem; border-top: 1px solid #1e293b; font-size: 0.9rem; vertical-align: | + | |
| - | tr: | + | |
| - | tr:hover td { background: #1d2d45; } | + | |
| - | .hostname { font-weight: | + | |
| - | .friendly { color: #94a3b8; } | + | |
| - | .ip { font-family: | + | |
| - | .ip.failed { color: #f87171; font-style: italic; } | + | |
| - | .badge { display: inline-block; | + | |
| - | .ping-ok | + | |
| - | .ping-fail { background:# | + | |
| - | .hint { | + | |
| - | margin-top: 1.5rem; background: #1e293b; border: 1px solid #334155; | + | |
| - | border-radius: | + | |
| - | color: #64748b; display: flex; gap: 2rem; flex-wrap: wrap; | + | |
| - | } | + | |
| - | .hint strong { color: #94a3b8; display: block; margin-bottom: | + | |
| - | .hint code { | + | |
| - | background: #0f172a; border: 1px solid #334155; | + | |
| - | padding: 0.1rem 0.4rem; border-radius: | + | |
| - | } | + | |
| - | @media (max-width: 600px) { th: | + | |
| - | </ | + | |
| - | </ | + | |
| - | < | + | |
| - | <div class=" | + | |
| - | < | + | |
| - | <div class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </ | + | |
| - | <div class=" | + | |
| - | <div class=" | + | |
| - | <div class=" | + | |
| - | <div class=" | + | |
| - | <div class=" | + | |
| - | </ | + | |
| - | ${site_cards} | + | |
| - | </ | + | |
| - | <div class=" | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </ | + | |
| - | < | + | |
| - | ${table_rows} | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | <div class=" | + | |
| - | < | + | |
| - | < | + | |
| - | Edit < | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | |
| - | Edit < | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | |
| - | Page regenerated by cron — last run shown above | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | </ | + | |
| - | HTML | + | |
| - | + | ||
| - | echo " | + | |
| - | </ | + | |