Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
Executable
+522
@@ -0,0 +1,522 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Script Name: network-info-exporter.sh
|
||||
# Description: Prometheus exporter for Linux network metrics
|
||||
#
|
||||
# Collects interface statistics, connection states, routing info, firewall
|
||||
# rules, DNS configuration, protocol statistics, and latency measurements.
|
||||
#
|
||||
# Author: Phil Connor
|
||||
# Contact: contact@mylinux.work
|
||||
# Website: https://mylinux.work
|
||||
# License: MIT
|
||||
# Version: 3.0
|
||||
#
|
||||
# Usage:
|
||||
# # Output to stdout
|
||||
# ./network-info-exporter.sh
|
||||
#
|
||||
# # Textfile collector mode (atomic write)
|
||||
# ./network-info-exporter.sh --textfile
|
||||
#
|
||||
# # Custom output file
|
||||
# ./network-info-exporter.sh -o /path/to/metrics.prom
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# ============================================================================
|
||||
# CONFIGURATION VARIABLES
|
||||
# ============================================================================
|
||||
|
||||
TEXTFILE_DIR="/var/lib/node_exporter"
|
||||
OUTPUT_FILE=""
|
||||
HOSTNAME=$(hostname)
|
||||
|
||||
PING_TARGETS="${PING_TARGETS:-8.8.8.8 1.1.1.1 google.com}"
|
||||
PING_COUNT="${PING_COUNT:-5}"
|
||||
PING_TIMEOUT="${PING_TIMEOUT:-2}"
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Export Linux network metrics as Prometheus metrics.
|
||||
|
||||
MODES:
|
||||
--textfile Write to node_exporter textfile collector
|
||||
(writes to $TEXTFILE_DIR/network_info.prom)
|
||||
|
||||
OPTIONS:
|
||||
-o, --output Output file path (for custom locations)
|
||||
-h, --help Show this help message
|
||||
|
||||
EXAMPLES:
|
||||
$0 # Output to stdout
|
||||
$0 --textfile # Write to textfile collector
|
||||
$0 -o /tmp/network.prom # Write to custom file
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help) show_usage ;;
|
||||
--textfile) OUTPUT_FILE="$TEXTFILE_DIR/network_info.prom"; shift ;;
|
||||
-o|--output) OUTPUT_FILE="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# METRIC GENERATION
|
||||
# ============================================================================
|
||||
|
||||
generate_metrics() {
|
||||
local START_TIME
|
||||
START_TIME=$(date +%s.%N)
|
||||
|
||||
# --- System info ---
|
||||
echo "# HELP network_exporter_info Exporter and system information"
|
||||
echo "# TYPE network_exporter_info gauge"
|
||||
local kernel arch os_name os_version
|
||||
kernel=$(uname -r)
|
||||
arch=$(uname -m)
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
. /etc/os-release
|
||||
os_name="${NAME:-unknown}"
|
||||
os_version="${VERSION_ID:-unknown}"
|
||||
else
|
||||
os_name="unknown"
|
||||
os_version="unknown"
|
||||
fi
|
||||
echo "network_exporter_info{hostname=\"${HOSTNAME}\",kernel=\"${kernel}\",arch=\"${arch}\",os=\"${os_name}\",version=\"${os_version}\"} 1"
|
||||
echo ""
|
||||
|
||||
# --- Interface counters from /proc/net/dev ---
|
||||
if [[ -r /proc/net/dev ]]; then
|
||||
awk '
|
||||
NR > 2 {
|
||||
sub(/:/, " ")
|
||||
iface = $1
|
||||
if (iface == "lo") next
|
||||
devices[count++] = iface
|
||||
rx_bytes[iface] = $2; rx_packets[iface] = $3
|
||||
rx_errors[iface] = $4; rx_dropped[iface] = $5
|
||||
tx_bytes[iface] = $10; tx_packets[iface] = $11
|
||||
tx_errors[iface] = $12; tx_dropped[iface] = $13
|
||||
}
|
||||
END {
|
||||
metrics["receive_bytes"] = "Total bytes received"; t["receive_bytes"] = "counter"
|
||||
metrics["receive_packets"] = "Total packets received"; t["receive_packets"] = "counter"
|
||||
metrics["receive_errors"] = "Total receive errors"; t["receive_errors"] = "counter"
|
||||
metrics["receive_dropped"] = "Total receive drops"; t["receive_dropped"] = "counter"
|
||||
metrics["transmit_bytes"] = "Total bytes transmitted"; t["transmit_bytes"] = "counter"
|
||||
metrics["transmit_packets"] = "Total packets transmitted"; t["transmit_packets"] = "counter"
|
||||
metrics["transmit_errors"] = "Total transmit errors"; t["transmit_errors"] = "counter"
|
||||
metrics["transmit_dropped"] = "Total transmit drops"; t["transmit_dropped"] = "counter"
|
||||
|
||||
order[0]="receive_bytes"; order[1]="receive_packets"
|
||||
order[2]="receive_errors"; order[3]="receive_dropped"
|
||||
order[4]="transmit_bytes"; order[5]="transmit_packets"
|
||||
order[6]="transmit_errors"; order[7]="transmit_dropped"
|
||||
|
||||
for (m = 0; m < 8; m++) {
|
||||
key = order[m]
|
||||
name = "network_" key "_total"
|
||||
printf "# HELP %s %s\n", name, metrics[key]
|
||||
printf "# TYPE %s %s\n", name, t[key]
|
||||
for (i = 0; i < count; i++) {
|
||||
d = devices[i]
|
||||
if (key == "receive_bytes") v = rx_bytes[d]
|
||||
else if (key == "receive_packets") v = rx_packets[d]
|
||||
else if (key == "receive_errors") v = rx_errors[d]
|
||||
else if (key == "receive_dropped") v = rx_dropped[d]
|
||||
else if (key == "transmit_bytes") v = tx_bytes[d]
|
||||
else if (key == "transmit_packets") v = tx_packets[d]
|
||||
else if (key == "transmit_errors") v = tx_errors[d]
|
||||
else if (key == "transmit_dropped") v = tx_dropped[d]
|
||||
printf "%s{device=\"%s\",hostname=\"%s\"} %s\n", name, d, ENVIRON["HOSTNAME"], v
|
||||
}
|
||||
print ""
|
||||
}
|
||||
}
|
||||
' /proc/net/dev
|
||||
fi
|
||||
|
||||
# --- Interface status, MTU, queue length, speed ---
|
||||
echo "# HELP network_interface_up Interface operational status (1=up, 0=down)"
|
||||
echo "# TYPE network_interface_up gauge"
|
||||
echo "# HELP network_interface_mtu Interface MTU size"
|
||||
echo "# TYPE network_interface_mtu gauge"
|
||||
echo "# HELP network_interface_tx_queue_length Interface transmit queue length"
|
||||
echo "# TYPE network_interface_tx_queue_length gauge"
|
||||
echo "# HELP network_interface_speed_mbps Interface link speed in Mbps"
|
||||
echo "# TYPE network_interface_speed_mbps gauge"
|
||||
|
||||
for iface_path in /sys/class/net/*; do
|
||||
iface=$(basename "$iface_path")
|
||||
[[ "$iface" == "lo" ]] && continue
|
||||
|
||||
# status
|
||||
local operstate
|
||||
operstate=$(cat "$iface_path/operstate" 2>/dev/null) || operstate="unknown"
|
||||
if [[ "$operstate" == "up" ]]; then
|
||||
echo "network_interface_up{device=\"${iface}\",hostname=\"${HOSTNAME}\"} 1"
|
||||
else
|
||||
echo "network_interface_up{device=\"${iface}\",hostname=\"${HOSTNAME}\"} 0"
|
||||
fi
|
||||
|
||||
# mtu
|
||||
local mtu
|
||||
mtu=$(cat "$iface_path/mtu" 2>/dev/null) || mtu=0
|
||||
echo "network_interface_mtu{device=\"${iface}\",hostname=\"${HOSTNAME}\"} ${mtu}"
|
||||
|
||||
# tx queue length
|
||||
local qlen
|
||||
qlen=$(cat "$iface_path/tx_queue_len" 2>/dev/null) || qlen=0
|
||||
echo "network_interface_tx_queue_length{device=\"${iface}\",hostname=\"${HOSTNAME}\"} ${qlen}"
|
||||
|
||||
# speed (only for physical interfaces with valid speed)
|
||||
if [[ -r "$iface_path/speed" ]]; then
|
||||
local speed
|
||||
speed=$(cat "$iface_path/speed" 2>/dev/null) || speed=-1
|
||||
if [[ "$speed" =~ ^[0-9]+$ ]] && [[ "$speed" -gt 0 ]]; then
|
||||
echo "network_interface_speed_mbps{device=\"${iface}\",hostname=\"${HOSTNAME}\"} ${speed}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
# --- Routing ---
|
||||
echo "# HELP network_routes_total Route count by protocol"
|
||||
echo "# TYPE network_routes_total gauge"
|
||||
if command -v ip &>/dev/null; then
|
||||
local ipv4_routes ipv6_routes default_routes
|
||||
ipv4_routes=$(ip route show 2>/dev/null | wc -l)
|
||||
ipv6_routes=$(ip -6 route show 2>/dev/null | wc -l)
|
||||
default_routes=$(ip route show default 2>/dev/null | wc -l)
|
||||
echo "network_routes_total{family=\"ipv4\",hostname=\"${HOSTNAME}\"} ${ipv4_routes}"
|
||||
echo "network_routes_total{family=\"ipv6\",hostname=\"${HOSTNAME}\"} ${ipv6_routes}"
|
||||
echo "network_routes_total{type=\"default\",hostname=\"${HOSTNAME}\"} ${default_routes}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- DNS nameservers ---
|
||||
echo "# HELP network_dns_nameservers_configured Number of configured DNS nameservers"
|
||||
echo "# TYPE network_dns_nameservers_configured gauge"
|
||||
local ns_count=0
|
||||
if [[ -r /etc/resolv.conf ]]; then
|
||||
ns_count=$(grep -c "^nameserver" /etc/resolv.conf 2>/dev/null) || ns_count=0
|
||||
fi
|
||||
echo "network_dns_nameservers_configured{hostname=\"${HOSTNAME}\"} ${ns_count}"
|
||||
echo ""
|
||||
|
||||
# --- Firewall rules ---
|
||||
echo "# HELP network_firewall_rules_total Firewall rule count"
|
||||
echo "# TYPE network_firewall_rules_total gauge"
|
||||
local ipt_rules=0 ip6t_rules=0
|
||||
if command -v iptables &>/dev/null; then
|
||||
ipt_rules=$(iptables -S 2>/dev/null | grep -c '^-A' 2>/dev/null) || ipt_rules=0
|
||||
fi
|
||||
if command -v ip6tables &>/dev/null; then
|
||||
ip6t_rules=$(ip6tables -S 2>/dev/null | grep -c '^-A' 2>/dev/null) || ip6t_rules=0
|
||||
fi
|
||||
echo "network_firewall_rules_total{family=\"ipv4\",hostname=\"${HOSTNAME}\"} ${ipt_rules}"
|
||||
echo "network_firewall_rules_total{family=\"ipv6\",hostname=\"${HOSTNAME}\"} ${ip6t_rules}"
|
||||
echo ""
|
||||
|
||||
# --- Network service status ---
|
||||
if command -v systemctl &>/dev/null; then
|
||||
echo "# HELP network_service_active Network service status (1=active, 0=inactive)"
|
||||
echo "# TYPE network_service_active gauge"
|
||||
for svc in NetworkManager networking systemd-networkd dhcpcd wpa_supplicant; do
|
||||
local status=0
|
||||
systemctl is-active "$svc" &>/dev/null && status=1
|
||||
echo "network_service_active{service=\"${svc}\",hostname=\"${HOSTNAME}\"} ${status}"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- Socket stats from /proc/net/sockstat ---
|
||||
if [[ -r /proc/net/sockstat ]]; then
|
||||
echo "# HELP network_sockets_inuse Sockets currently in use by protocol"
|
||||
echo "# TYPE network_sockets_inuse gauge"
|
||||
local tcp_inuse udp_inuse raw_inuse
|
||||
tcp_inuse=$(awk '/^TCP:/ {print $3}' /proc/net/sockstat 2>/dev/null) || tcp_inuse=0
|
||||
udp_inuse=$(awk '/^UDP:/ {print $3}' /proc/net/sockstat 2>/dev/null) || udp_inuse=0
|
||||
raw_inuse=$(awk '/^RAW:/ {print $3}' /proc/net/sockstat 2>/dev/null) || raw_inuse=0
|
||||
echo "network_sockets_inuse{protocol=\"tcp\",hostname=\"${HOSTNAME}\"} ${tcp_inuse:-0}"
|
||||
echo "network_sockets_inuse{protocol=\"udp\",hostname=\"${HOSTNAME}\"} ${udp_inuse:-0}"
|
||||
echo "network_sockets_inuse{protocol=\"raw\",hostname=\"${HOSTNAME}\"} ${raw_inuse:-0}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- TCP retransmissions and listen overflows from /proc/net/netstat ---
|
||||
if [[ -r /proc/net/netstat ]]; then
|
||||
local tcp_retrans=0 listen_overflows=0 listen_drops=0
|
||||
# Parse TcpExt header+values pair
|
||||
local headers values
|
||||
headers=$(grep "^TcpExt:" /proc/net/netstat | head -1)
|
||||
values=$(grep "^TcpExt:" /proc/net/netstat | tail -1)
|
||||
if [[ -n "$headers" && -n "$values" ]]; then
|
||||
tcp_retrans=$(paste <(echo "$headers" | tr ' ' '\n') <(echo "$values" | tr ' ' '\n') | awk -F'\t' '$1=="TCPRetransSegs" {print $2}')
|
||||
listen_overflows=$(paste <(echo "$headers" | tr ' ' '\n') <(echo "$values" | tr ' ' '\n') | awk -F'\t' '$1=="ListenOverflows" {print $2}')
|
||||
listen_drops=$(paste <(echo "$headers" | tr ' ' '\n') <(echo "$values" | tr ' ' '\n') | awk -F'\t' '$1=="ListenDrops" {print $2}')
|
||||
fi
|
||||
|
||||
echo "# HELP network_tcp_retransmit_segments_total TCP segments retransmitted"
|
||||
echo "# TYPE network_tcp_retransmit_segments_total counter"
|
||||
echo "network_tcp_retransmit_segments_total{hostname=\"${HOSTNAME}\"} ${tcp_retrans:-0}"
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_tcp_listen_overflows_total TCP listen queue overflows"
|
||||
echo "# TYPE network_tcp_listen_overflows_total counter"
|
||||
echo "network_tcp_listen_overflows_total{hostname=\"${HOSTNAME}\"} ${listen_overflows:-0}"
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_tcp_listen_drops_total TCP listen queue drops"
|
||||
echo "# TYPE network_tcp_listen_drops_total counter"
|
||||
echo "network_tcp_listen_drops_total{hostname=\"${HOSTNAME}\"} ${listen_drops:-0}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- ARP table ---
|
||||
if [[ -r /proc/net/arp ]]; then
|
||||
echo "# HELP network_arp_entries_total ARP table entries"
|
||||
echo "# TYPE network_arp_entries_total gauge"
|
||||
local arp_count
|
||||
arp_count=$(($(wc -l < /proc/net/arp) - 1))
|
||||
[[ $arp_count -lt 0 ]] && arp_count=0
|
||||
echo "network_arp_entries_total{hostname=\"${HOSTNAME}\"} ${arp_count}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- UDP sockets ---
|
||||
if [[ -r /proc/net/udp ]]; then
|
||||
echo "# HELP network_udp_sockets_total UDP sockets"
|
||||
echo "# TYPE network_udp_sockets_total gauge"
|
||||
local udp_sockets
|
||||
udp_sockets=$(($(wc -l < /proc/net/udp) - 1))
|
||||
[[ $udp_sockets -lt 0 ]] && udp_sockets=0
|
||||
echo "network_udp_sockets_total{hostname=\"${HOSTNAME}\"} ${udp_sockets}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- ICMP stats from /proc/net/snmp ---
|
||||
if [[ -r /proc/net/snmp ]]; then
|
||||
local icmp_header icmp_values
|
||||
icmp_header=$(grep "^Icmp:" /proc/net/snmp | head -1)
|
||||
icmp_values=$(grep "^Icmp:" /proc/net/snmp | tail -1)
|
||||
if [[ -n "$icmp_header" && -n "$icmp_values" ]]; then
|
||||
local icmp_in icmp_out icmp_err_in icmp_err_out
|
||||
icmp_in=$(paste <(echo "$icmp_header" | tr ' ' '\n') <(echo "$icmp_values" | tr ' ' '\n') | awk -F'\t' '$1=="InMsgs" {print $2}')
|
||||
icmp_out=$(paste <(echo "$icmp_header" | tr ' ' '\n') <(echo "$icmp_values" | tr ' ' '\n') | awk -F'\t' '$1=="OutMsgs" {print $2}')
|
||||
icmp_err_in=$(paste <(echo "$icmp_header" | tr ' ' '\n') <(echo "$icmp_values" | tr ' ' '\n') | awk -F'\t' '$1=="InErrors" {print $2}')
|
||||
icmp_err_out=$(paste <(echo "$icmp_header" | tr ' ' '\n') <(echo "$icmp_values" | tr ' ' '\n') | awk -F'\t' '$1=="OutErrors" {print $2}')
|
||||
|
||||
echo "# HELP network_icmp_messages_total ICMP messages by direction"
|
||||
echo "# TYPE network_icmp_messages_total counter"
|
||||
echo "network_icmp_messages_total{direction=\"in\",hostname=\"${HOSTNAME}\"} ${icmp_in:-0}"
|
||||
echo "network_icmp_messages_total{direction=\"out\",hostname=\"${HOSTNAME}\"} ${icmp_out:-0}"
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_icmp_errors_total ICMP errors by direction"
|
||||
echo "# TYPE network_icmp_errors_total counter"
|
||||
echo "network_icmp_errors_total{direction=\"in\",hostname=\"${HOSTNAME}\"} ${icmp_err_in:-0}"
|
||||
echo "network_icmp_errors_total{direction=\"out\",hostname=\"${HOSTNAME}\"} ${icmp_err_out:-0}"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- TCP connections by state ---
|
||||
if [[ -r /proc/net/tcp ]]; then
|
||||
echo "# HELP network_tcp_connections TCP connections by state"
|
||||
echo "# TYPE network_tcp_connections gauge"
|
||||
# hex state codes: 01=ESTABLISHED, 06=TIME_WAIT, 0A=LISTEN
|
||||
local tcp_estab tcp_listen tcp_tw tcp_close_wait tcp_syn_recv
|
||||
tcp_estab=$(awk '$4=="01" {c++} END {print c+0}' /proc/net/tcp 2>/dev/null)
|
||||
tcp_listen=$(awk '$4=="0A" {c++} END {print c+0}' /proc/net/tcp 2>/dev/null)
|
||||
tcp_tw=$(awk '$4=="06" {c++} END {print c+0}' /proc/net/tcp 2>/dev/null)
|
||||
tcp_close_wait=$(awk '$4=="08" {c++} END {print c+0}' /proc/net/tcp 2>/dev/null)
|
||||
tcp_syn_recv=$(awk '$4=="03" {c++} END {print c+0}' /proc/net/tcp 2>/dev/null)
|
||||
echo "network_tcp_connections{state=\"established\",hostname=\"${HOSTNAME}\"} ${tcp_estab}"
|
||||
echo "network_tcp_connections{state=\"listen\",hostname=\"${HOSTNAME}\"} ${tcp_listen}"
|
||||
echo "network_tcp_connections{state=\"time_wait\",hostname=\"${HOSTNAME}\"} ${tcp_tw}"
|
||||
echo "network_tcp_connections{state=\"close_wait\",hostname=\"${HOSTNAME}\"} ${tcp_close_wait}"
|
||||
echo "network_tcp_connections{state=\"syn_recv\",hostname=\"${HOSTNAME}\"} ${tcp_syn_recv}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- Conntrack ---
|
||||
if [[ -r /proc/sys/net/netfilter/nf_conntrack_count ]]; then
|
||||
echo "# HELP network_nf_conntrack_entries Conntrack table entries"
|
||||
echo "# TYPE network_nf_conntrack_entries gauge"
|
||||
echo "network_nf_conntrack_entries{hostname=\"${HOSTNAME}\"} $(cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null || echo 0)"
|
||||
fi
|
||||
if [[ -r /proc/sys/net/netfilter/nf_conntrack_max ]]; then
|
||||
echo "# HELP network_nf_conntrack_entries_limit Conntrack table maximum"
|
||||
echo "# TYPE network_nf_conntrack_entries_limit gauge"
|
||||
echo "network_nf_conntrack_entries_limit{hostname=\"${HOSTNAME}\"} $(cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null || echo 0)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- Latency (parallel ping) ---
|
||||
if command -v ping &>/dev/null; then
|
||||
read -ra targets <<< "$PING_TARGETS"
|
||||
local tmp_files=() pids=() labels=()
|
||||
|
||||
for target in "${targets[@]}"; do
|
||||
[[ -z "$target" ]] && continue
|
||||
local label
|
||||
label=$(echo "$target" | tr -c 'a-zA-Z0-9._-' '_' | sed 's/_*$//')
|
||||
labels+=("$label")
|
||||
|
||||
local tmp
|
||||
tmp=$(mktemp)
|
||||
tmp_files+=("$tmp")
|
||||
|
||||
(
|
||||
set +e
|
||||
timeout $((PING_COUNT * PING_TIMEOUT + 5)) ping -c "$PING_COUNT" -W "$PING_TIMEOUT" "$target" > "$tmp" 2>&1
|
||||
echo "EXIT=$?" >> "$tmp"
|
||||
) &
|
||||
pids+=($!)
|
||||
done
|
||||
|
||||
[[ ${#pids[@]} -gt 0 ]] && wait "${pids[@]}"
|
||||
|
||||
# Collect parsed results
|
||||
local all_min=() all_avg=() all_max=() all_stddev=() all_loss=()
|
||||
|
||||
for i in "${!tmp_files[@]}"; do
|
||||
local tmp="${tmp_files[$i]}"
|
||||
local exit_code min_v=0 avg_v=0 max_v=0 stddev_v=0 loss_v=100
|
||||
|
||||
if [[ -f "$tmp" ]]; then
|
||||
exit_code=$(grep "^EXIT=" "$tmp" | tail -1 | cut -d= -f2)
|
||||
if [[ "${exit_code:-1}" -eq 0 ]]; then
|
||||
local stats
|
||||
stats=$(grep -E 'rtt min/avg/max/(mdev|stddev)' "$tmp" | head -1)
|
||||
if [[ -n "$stats" ]]; then
|
||||
local vals
|
||||
vals=$(echo "$stats" | cut -d= -f2 | awk '{print $1}')
|
||||
min_v=$(echo "$vals" | cut -d/ -f1)
|
||||
avg_v=$(echo "$vals" | cut -d/ -f2)
|
||||
max_v=$(echo "$vals" | cut -d/ -f3)
|
||||
stddev_v=$(echo "$vals" | cut -d/ -f4)
|
||||
fi
|
||||
loss_v=$(grep -oP '\d+(?=% packet loss)' "$tmp" | head -1)
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
fi
|
||||
|
||||
all_min+=("${min_v:-0}")
|
||||
all_avg+=("${avg_v:-0}")
|
||||
all_max+=("${max_v:-0}")
|
||||
all_stddev+=("${stddev_v:-0}")
|
||||
all_loss+=("${loss_v:-100}")
|
||||
done
|
||||
|
||||
echo "# HELP network_ping_rtt_min_milliseconds Minimum ping RTT"
|
||||
echo "# TYPE network_ping_rtt_min_milliseconds gauge"
|
||||
for i in "${!labels[@]}"; do
|
||||
echo "network_ping_rtt_min_milliseconds{target=\"${labels[$i]}\",hostname=\"${HOSTNAME}\"} ${all_min[$i]}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_ping_rtt_avg_milliseconds Average ping RTT"
|
||||
echo "# TYPE network_ping_rtt_avg_milliseconds gauge"
|
||||
for i in "${!labels[@]}"; do
|
||||
echo "network_ping_rtt_avg_milliseconds{target=\"${labels[$i]}\",hostname=\"${HOSTNAME}\"} ${all_avg[$i]}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_ping_rtt_max_milliseconds Maximum ping RTT"
|
||||
echo "# TYPE network_ping_rtt_max_milliseconds gauge"
|
||||
for i in "${!labels[@]}"; do
|
||||
echo "network_ping_rtt_max_milliseconds{target=\"${labels[$i]}\",hostname=\"${HOSTNAME}\"} ${all_max[$i]}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_ping_rtt_stddev_milliseconds Ping RTT standard deviation (jitter)"
|
||||
echo "# TYPE network_ping_rtt_stddev_milliseconds gauge"
|
||||
for i in "${!labels[@]}"; do
|
||||
echo "network_ping_rtt_stddev_milliseconds{target=\"${labels[$i]}\",hostname=\"${HOSTNAME}\"} ${all_stddev[$i]}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_ping_packet_loss_percent Packet loss percentage"
|
||||
echo "# TYPE network_ping_packet_loss_percent gauge"
|
||||
for i in "${!labels[@]}"; do
|
||||
echo "network_ping_packet_loss_percent{target=\"${labels[$i]}\",hostname=\"${HOSTNAME}\"} ${all_loss[$i]}"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- Exporter timing ---
|
||||
local END_TIME DURATION
|
||||
END_TIME=$(date +%s.%N)
|
||||
DURATION=$(echo "$END_TIME - $START_TIME" | bc)
|
||||
|
||||
echo "# HELP network_exporter_duration_seconds Time to generate all metrics"
|
||||
echo "# TYPE network_exporter_duration_seconds gauge"
|
||||
echo "network_exporter_duration_seconds{hostname=\"${HOSTNAME}\"} ${DURATION}"
|
||||
|
||||
echo ""
|
||||
echo "# HELP network_exporter_last_run_timestamp Unix timestamp of last successful run"
|
||||
echo "# TYPE network_exporter_last_run_timestamp gauge"
|
||||
echo "network_exporter_last_run_timestamp{hostname=\"${HOSTNAME}\"} $(date +%s)"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# MAIN EXECUTION
|
||||
# ============================================================================
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "Error: This script must be run as root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$OUTPUT_FILE" ]; then
|
||||
local output_dir
|
||||
output_dir="$(dirname "$OUTPUT_FILE")"
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
local temp_file
|
||||
temp_file=$(mktemp "${output_dir}/.network_info.XXXXXX")
|
||||
|
||||
if ! generate_metrics > "$temp_file" 2>/dev/null; then
|
||||
rm -f "$temp_file"
|
||||
echo "ERROR: Failed to generate metrics" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local file_lines
|
||||
file_lines=$(wc -l < "$temp_file" 2>/dev/null || echo 0)
|
||||
|
||||
if [ "$file_lines" -lt 10 ]; then
|
||||
rm -f "$temp_file"
|
||||
echo "ERROR: Metrics file too small ($file_lines lines), keeping previous" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 644 "$temp_file"
|
||||
mv -f "$temp_file" "$OUTPUT_FILE"
|
||||
|
||||
echo "Metrics written to $OUTPUT_FILE ($file_lines lines)" >&2
|
||||
else
|
||||
generate_metrics
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user