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:
@@ -0,0 +1,598 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Script Name: nfs-server-exporter.sh
|
||||
# Version: 1.0
|
||||
# Description: Prometheus exporter for NFS server metrics — export status,
|
||||
# thread pool utilization, per-operation counters, RPC errors,
|
||||
# connected clients, and server health
|
||||
#
|
||||
# Author: Phil Connor
|
||||
# Contact: contact@mylinux.work
|
||||
# Website: https://mylinux.work
|
||||
# License: MIT
|
||||
#
|
||||
# Prerequisites:
|
||||
# - NFS server running (nfs-kernel-server / nfs-utils)
|
||||
# - /proc/net/rpc/nfsd available
|
||||
# - /proc/fs/nfsd available
|
||||
# - exportfs command available
|
||||
# - netcat (nc) for HTTP mode
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./nfs-server-exporter.sh
|
||||
# sudo ./nfs-server-exporter.sh --http -p 9588
|
||||
# sudo ./nfs-server-exporter.sh --textfile
|
||||
#
|
||||
# Metrics Exported:
|
||||
# - nfsd_up - Exporter status (1=up, 0=down)
|
||||
# - nfsd_exports_total - Number of active exports
|
||||
# - nfsd_export_info{export,client,options} - Export configuration
|
||||
# - nfsd_threads_total - Configured NFS server threads
|
||||
# - nfsd_threads_busy - Threads currently handling requests
|
||||
# - nfsd_pool_packets_total{pool} - Packets received per pool
|
||||
# - nfsd_pool_sockets_enqueued_total{pool} - Sockets enqueued per pool
|
||||
# - nfsd_pool_threads_woken_total{pool} - Threads woken per pool
|
||||
# - nfsd_pool_threads_timedout_total{pool} - Thread timeouts per pool
|
||||
# - nfsd_rpc_calls_total - Total RPC calls received
|
||||
# - nfsd_rpc_bad_calls_total - Total bad RPC calls
|
||||
# - nfsd_rpc_bad_auth_total - Total bad auth attempts
|
||||
# - nfsd_rpc_bad_client_total - Total bad client calls
|
||||
# - nfsd_v3_ops_total{op} - NFSv3 per-operation counters
|
||||
# - nfsd_v4_ops_total{op} - NFSv4 per-operation counters
|
||||
# - nfsd_io_read_bytes_total - Total bytes read by server
|
||||
# - nfsd_io_write_bytes_total - Total bytes written by server
|
||||
# - nfsd_clients_total - Connected NFSv4 clients
|
||||
# - nfsd_file_handles_stale_total - Total stale file handle replies
|
||||
# - nfsd_exporter_duration_seconds - Script execution time
|
||||
# - nfsd_exporter_last_run_timestamp - Last successful run time
|
||||
#
|
||||
# Configuration:
|
||||
# Default HTTP port: 9588
|
||||
# Textfile directory: /var/lib/node_exporter
|
||||
#
|
||||
################################################################################
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# ============================================================================
|
||||
# CONFIGURATION VARIABLES
|
||||
# ============================================================================
|
||||
|
||||
TEXTFILE_DIR="/var/lib/node_exporter"
|
||||
OUTPUT_FILE=""
|
||||
HTTP_MODE=false
|
||||
HTTP_PORT=9588
|
||||
LOCK_FILE="/tmp/nfs-server-exporter.lock"
|
||||
PROC_NFSD="/proc/net/rpc/nfsd"
|
||||
NFSD_DIR="/proc/fs/nfsd"
|
||||
|
||||
# ============================================================================
|
||||
# LOGGING FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[INFO]${NC} $*" >&2; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*" >&2; }
|
||||
error(){ echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Export NFS server statistics as Prometheus metrics.
|
||||
|
||||
MODES:
|
||||
--textfile Write to node_exporter textfile collector
|
||||
--http Run HTTP server on port $HTTP_PORT
|
||||
|
||||
OPTIONS:
|
||||
-p, --port HTTP port (default: 9588)
|
||||
-o, --output Output file path
|
||||
|
||||
EXAMPLES:
|
||||
sudo $0 --textfile
|
||||
sudo $0 --http --port 9588
|
||||
sudo $0 -o /tmp/nfsd.prom
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help) show_usage ;;
|
||||
--textfile) OUTPUT_FILE="$TEXTFILE_DIR/nfsd.prom"; shift ;;
|
||||
--http) HTTP_MODE=true; shift ;;
|
||||
-p|--port) HTTP_PORT="$2"; shift 2 ;;
|
||||
-o|--output) OUTPUT_FILE="$2"; shift 2 ;;
|
||||
*) error "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
acquire_lock() {
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
local lock_pid
|
||||
lock_pid=$(cat "$LOCK_FILE" 2>/dev/null)
|
||||
if [ -n "$lock_pid" ] && kill -0 "$lock_pid" 2>/dev/null; then
|
||||
error "Another instance is running (PID $lock_pid)"
|
||||
return 1
|
||||
fi
|
||||
rm -f "$LOCK_FILE"
|
||||
fi
|
||||
echo $$ > "$LOCK_FILE"
|
||||
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check if NFS server is running and proc files are available
|
||||
check_nfsd() {
|
||||
if [ ! -f "$PROC_NFSD" ]; then
|
||||
error "$PROC_NFSD not found — is the NFS server running?"
|
||||
return 1
|
||||
fi
|
||||
if [ ! -d "$NFSD_DIR" ]; then
|
||||
error "$NFSD_DIR not found"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Get number of configured NFS threads
|
||||
# Returns: Thread count
|
||||
get_thread_count() {
|
||||
if [ -f "$NFSD_DIR/threads" ]; then
|
||||
cat "$NFSD_DIR/threads" 2>/dev/null | head -1
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get pool stats from /proc/fs/nfsd/pool_stats
|
||||
# Returns: Lines with "pool packets sockets_enqueued threads_woken threads_timedout"
|
||||
get_pool_stats() {
|
||||
if [ -f "$NFSD_DIR/pool_stats" ]; then
|
||||
# Skip header line
|
||||
tail -n +2 "$NFSD_DIR/pool_stats" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Get RPC stats from /proc/net/rpc/nfsd
|
||||
# The "rc" line: hits misses nocache
|
||||
# The "io" line: read write
|
||||
# The "rpc" line: calls badcalls badfmt badauth badclnt
|
||||
get_rpc_calls() {
|
||||
awk '/^rpc / { print $2 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
get_rpc_bad_calls() {
|
||||
awk '/^rpc / { print $3 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
get_rpc_bad_auth() {
|
||||
awk '/^rpc / { print $5 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
get_rpc_bad_client() {
|
||||
awk '/^rpc / { print $6 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
# Get server I/O bytes from /proc/net/rpc/nfsd "io" line
|
||||
get_io_read_bytes() {
|
||||
awk '/^io / { print $2 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
get_io_write_bytes() {
|
||||
awk '/^io / { print $3 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
# Get stale file handle count from /proc/net/rpc/nfsd "fh" line
|
||||
# fh: stale total_lookups anonlookups dirnocache nondir_nocache
|
||||
get_stale_handles() {
|
||||
awk '/^fh / { print $2 }' "$PROC_NFSD" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
# Get NFSv3 per-operation counters from /proc/net/rpc/nfsd
|
||||
# proc3 line: num_ops null getattr setattr lookup access readlink read write create mkdir symlink ...
|
||||
get_v3_ops() {
|
||||
awk '/^proc3 / {
|
||||
ops[1]="null"; ops[2]="getattr"; ops[3]="setattr"; ops[4]="lookup"
|
||||
ops[5]="access"; ops[6]="readlink"; ops[7]="read"; ops[8]="write"
|
||||
ops[9]="create"; ops[10]="mkdir"; ops[11]="symlink"; ops[12]="mknod"
|
||||
ops[13]="remove"; ops[14]="rmdir"; ops[15]="rename"; ops[16]="link"
|
||||
ops[17]="readdir"; ops[18]="readdirplus"; ops[19]="fsstat"; ops[20]="fsinfo"
|
||||
ops[21]="pathconf"; ops[22]="commit"
|
||||
n = $2 + 0
|
||||
for (i = 1; i <= n && i <= 22; i++) {
|
||||
printf "%s %s\n", ops[i], $(i + 2)
|
||||
}
|
||||
}' "$PROC_NFSD" 2>/dev/null
|
||||
}
|
||||
|
||||
# Get NFSv4 per-operation counters from /proc/net/rpc/nfsd
|
||||
# proc4ops line: num_ops op0 op1 op2 ...
|
||||
get_v4_ops() {
|
||||
awk '/^proc4ops / {
|
||||
ops[1]="op0-unused"; ops[2]="op1-unused"; ops[3]="access"; ops[4]="close"
|
||||
ops[5]="commit"; ops[6]="create"; ops[7]="delegpurge"; ops[8]="delegreturn"
|
||||
ops[9]="getattr"; ops[10]="getfh"; ops[11]="link"; ops[12]="lock"
|
||||
ops[13]="lockt"; ops[14]="locku"; ops[15]="lookup"; ops[16]="lookupp"
|
||||
ops[17]="nverify"; ops[18]="open"; ops[19]="openattr"; ops[20]="open_confirm"
|
||||
ops[21]="open_downgrade"; ops[22]="putfh"; ops[23]="putpubfh"; ops[24]="putrootfh"
|
||||
ops[25]="read"; ops[26]="readdir"; ops[27]="readlink"; ops[28]="remove"
|
||||
ops[29]="rename"; ops[30]="renew"; ops[31]="restorefh"; ops[32]="savefh"
|
||||
ops[33]="secinfo"; ops[34]="setattr"; ops[35]="setclientid"; ops[36]="setclientid_confirm"
|
||||
ops[37]="verify"; ops[38]="write"; ops[39]="release_lockowner"
|
||||
n = $2 + 0
|
||||
for (i = 1; i <= n && i <= 39; i++) {
|
||||
if (ops[i] !~ /unused/) {
|
||||
printf "%s %s\n", ops[i], $(i + 2)
|
||||
}
|
||||
}
|
||||
}' "$PROC_NFSD" 2>/dev/null
|
||||
}
|
||||
|
||||
# Get active exports
|
||||
# Tries /proc/fs/nfsd/exports first, then /var/lib/nfs/etab, then exportfs -v
|
||||
# Returns: Lines with "export client(options)" — one per line
|
||||
get_exports() {
|
||||
local raw=""
|
||||
|
||||
# /proc/fs/nfsd/exports is most reliable (kernel export table)
|
||||
if [ -f "$NFSD_DIR/exports" ]; then
|
||||
raw=$(grep '^/' "$NFSD_DIR/exports" 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Fall back to etab (userspace export table)
|
||||
if [ -z "$raw" ] && [ -f /var/lib/nfs/etab ]; then
|
||||
raw=$(grep '^/' /var/lib/nfs/etab 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Fall back to exportfs command
|
||||
if [ -z "$raw" ]; then
|
||||
raw=$(/usr/sbin/exportfs -v 2>/dev/null || exportfs -v 2>/dev/null)
|
||||
# Merge continuation lines
|
||||
raw=$(echo "$raw" | awk '
|
||||
/^\// {
|
||||
if (line) print line
|
||||
line = $0
|
||||
next
|
||||
}
|
||||
{ line = line " " $0 }
|
||||
END { if (line) print line }
|
||||
')
|
||||
fi
|
||||
|
||||
echo "$raw" | sed 's/[[:space:]]\+/ /g' | sed 's/^ //' | grep -v '^$'
|
||||
}
|
||||
|
||||
# Count active exports
|
||||
get_export_count() {
|
||||
local count
|
||||
count=$(get_exports | wc -l)
|
||||
echo "${count:-0}"
|
||||
}
|
||||
|
||||
# Count connected NFSv4 clients
|
||||
get_client_count() {
|
||||
if [ -d "$NFSD_DIR/clients" ]; then
|
||||
local count
|
||||
count=$(ls -1 "$NFSD_DIR/clients" 2>/dev/null | wc -l)
|
||||
echo "${count:-0}"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# METRIC GENERATION
|
||||
# ============================================================================
|
||||
|
||||
generate_metrics() {
|
||||
local script_start
|
||||
script_start=$(date +%s)
|
||||
|
||||
if ! check_nfsd; then
|
||||
cat <<EOF
|
||||
# HELP nfsd_up NFS server exporter status
|
||||
# TYPE nfsd_up gauge
|
||||
nfsd_up 0
|
||||
EOF
|
||||
return
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_up NFS server exporter status
|
||||
# TYPE nfsd_up gauge
|
||||
nfsd_up 1
|
||||
|
||||
EOF
|
||||
|
||||
# Export count and info
|
||||
local export_count
|
||||
export_count=$(get_export_count)
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_exports_total Number of active NFS exports
|
||||
# TYPE nfsd_exports_total gauge
|
||||
nfsd_exports_total $export_count
|
||||
|
||||
# HELP nfsd_export_info Export configuration information
|
||||
# TYPE nfsd_export_info gauge
|
||||
EOF
|
||||
|
||||
while IFS= read -r line; do
|
||||
[ -z "$line" ] && continue
|
||||
local export_path client_opts client opts
|
||||
export_path=$(echo "$line" | awk '{print $1}')
|
||||
client_opts=$(echo "$line" | awk '{print $2}')
|
||||
client="${client_opts%%(*}"
|
||||
opts="${client_opts#*(}"
|
||||
opts="${opts%)}"
|
||||
[ -z "$export_path" ] && continue
|
||||
echo "nfsd_export_info{export=\"$export_path\",client=\"$client\",options=\"$opts\"} 1"
|
||||
done < <(get_exports)
|
||||
|
||||
echo ""
|
||||
|
||||
# Thread pool metrics
|
||||
local threads
|
||||
threads=$(get_thread_count)
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_threads_total Configured NFS server threads
|
||||
# TYPE nfsd_threads_total gauge
|
||||
nfsd_threads_total ${threads:-0}
|
||||
|
||||
EOF
|
||||
|
||||
# Pool stats
|
||||
local has_pool_stats=false
|
||||
if [ -f "$NFSD_DIR/pool_stats" ]; then
|
||||
has_pool_stats=true
|
||||
fi
|
||||
|
||||
if [ "$has_pool_stats" = true ]; then
|
||||
cat <<EOF
|
||||
# HELP nfsd_pool_packets_total Packets received per thread pool
|
||||
# TYPE nfsd_pool_packets_total counter
|
||||
EOF
|
||||
# pool_stats format: pool_num packets sockets_enqueued threads_woken threads_timedout
|
||||
while read -r pool_num packets sockets_enqueued threads_woken threads_timedout; do
|
||||
[ -z "$pool_num" ] && continue
|
||||
echo "nfsd_pool_packets_total{pool=\"$pool_num\"} $packets"
|
||||
done < <(get_pool_stats)
|
||||
|
||||
echo ""
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_pool_sockets_enqueued_total Sockets enqueued per thread pool
|
||||
# TYPE nfsd_pool_sockets_enqueued_total counter
|
||||
EOF
|
||||
while read -r pool_num packets sockets_enqueued threads_woken threads_timedout; do
|
||||
[ -z "$pool_num" ] && continue
|
||||
echo "nfsd_pool_sockets_enqueued_total{pool=\"$pool_num\"} $sockets_enqueued"
|
||||
done < <(get_pool_stats)
|
||||
|
||||
echo ""
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_pool_threads_woken_total Threads woken per thread pool
|
||||
# TYPE nfsd_pool_threads_woken_total counter
|
||||
EOF
|
||||
while read -r pool_num packets sockets_enqueued threads_woken threads_timedout; do
|
||||
[ -z "$pool_num" ] && continue
|
||||
echo "nfsd_pool_threads_woken_total{pool=\"$pool_num\"} $threads_woken"
|
||||
done < <(get_pool_stats)
|
||||
|
||||
echo ""
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_pool_threads_timedout_total Thread timeouts per thread pool
|
||||
# TYPE nfsd_pool_threads_timedout_total counter
|
||||
EOF
|
||||
while read -r pool_num packets sockets_enqueued threads_woken threads_timedout; do
|
||||
[ -z "$pool_num" ] && continue
|
||||
echo "nfsd_pool_threads_timedout_total{pool=\"$pool_num\"} $threads_timedout"
|
||||
done < <(get_pool_stats)
|
||||
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# RPC stats
|
||||
local rpc_calls rpc_bad rpc_bad_auth rpc_bad_client
|
||||
rpc_calls=$(get_rpc_calls)
|
||||
rpc_bad=$(get_rpc_bad_calls)
|
||||
rpc_bad_auth=$(get_rpc_bad_auth)
|
||||
rpc_bad_client=$(get_rpc_bad_client)
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_rpc_calls_total Total RPC calls received
|
||||
# TYPE nfsd_rpc_calls_total counter
|
||||
nfsd_rpc_calls_total ${rpc_calls:-0}
|
||||
|
||||
# HELP nfsd_rpc_bad_calls_total Total bad RPC calls
|
||||
# TYPE nfsd_rpc_bad_calls_total counter
|
||||
nfsd_rpc_bad_calls_total ${rpc_bad:-0}
|
||||
|
||||
# HELP nfsd_rpc_bad_auth_total Total bad authentication attempts
|
||||
# TYPE nfsd_rpc_bad_auth_total counter
|
||||
nfsd_rpc_bad_auth_total ${rpc_bad_auth:-0}
|
||||
|
||||
# HELP nfsd_rpc_bad_client_total Total bad client calls
|
||||
# TYPE nfsd_rpc_bad_client_total counter
|
||||
nfsd_rpc_bad_client_total ${rpc_bad_client:-0}
|
||||
|
||||
EOF
|
||||
|
||||
# Server I/O bytes
|
||||
local io_read io_write
|
||||
io_read=$(get_io_read_bytes)
|
||||
io_write=$(get_io_write_bytes)
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_io_read_bytes_total Total bytes read by NFS server
|
||||
# TYPE nfsd_io_read_bytes_total counter
|
||||
nfsd_io_read_bytes_total ${io_read:-0}
|
||||
|
||||
# HELP nfsd_io_write_bytes_total Total bytes written by NFS server
|
||||
# TYPE nfsd_io_write_bytes_total counter
|
||||
nfsd_io_write_bytes_total ${io_write:-0}
|
||||
|
||||
EOF
|
||||
|
||||
# Stale file handles
|
||||
local stale
|
||||
stale=$(get_stale_handles)
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_file_handles_stale_total Total stale file handle replies
|
||||
# TYPE nfsd_file_handles_stale_total counter
|
||||
nfsd_file_handles_stale_total ${stale:-0}
|
||||
|
||||
EOF
|
||||
|
||||
# NFSv3 per-operation counters
|
||||
local v3_data
|
||||
v3_data=$(get_v3_ops)
|
||||
|
||||
if [ -n "$v3_data" ]; then
|
||||
cat <<EOF
|
||||
# HELP nfsd_v3_ops_total NFSv3 per-operation call count
|
||||
# TYPE nfsd_v3_ops_total counter
|
||||
EOF
|
||||
while read -r op count; do
|
||||
[ -z "$op" ] && continue
|
||||
echo "nfsd_v3_ops_total{op=\"$op\"} ${count:-0}"
|
||||
done <<< "$v3_data"
|
||||
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# NFSv4 per-operation counters
|
||||
local v4_data
|
||||
v4_data=$(get_v4_ops)
|
||||
|
||||
if [ -n "$v4_data" ]; then
|
||||
cat <<EOF
|
||||
# HELP nfsd_v4_ops_total NFSv4 per-operation call count
|
||||
# TYPE nfsd_v4_ops_total counter
|
||||
EOF
|
||||
while read -r op count; do
|
||||
[ -z "$op" ] && continue
|
||||
echo "nfsd_v4_ops_total{op=\"$op\"} ${count:-0}"
|
||||
done <<< "$v4_data"
|
||||
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Connected clients
|
||||
local clients
|
||||
clients=$(get_client_count)
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_clients_total Connected NFSv4 clients
|
||||
# TYPE nfsd_clients_total gauge
|
||||
nfsd_clients_total ${clients:-0}
|
||||
|
||||
EOF
|
||||
|
||||
# Exporter runtime
|
||||
local script_end script_duration
|
||||
script_end=$(date +%s)
|
||||
script_duration=$((script_end - script_start))
|
||||
|
||||
cat <<EOF
|
||||
# HELP nfsd_exporter_duration_seconds Time to generate all metrics
|
||||
# TYPE nfsd_exporter_duration_seconds gauge
|
||||
nfsd_exporter_duration_seconds $script_duration
|
||||
|
||||
# HELP nfsd_exporter_last_run_timestamp Unix timestamp of last successful run
|
||||
# TYPE nfsd_exporter_last_run_timestamp gauge
|
||||
nfsd_exporter_last_run_timestamp $script_end
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# HTTP SERVER MODE
|
||||
# ============================================================================
|
||||
|
||||
run_http_server() {
|
||||
log "Starting NFS server exporter on port $HTTP_PORT..."
|
||||
|
||||
if ! command -v nc >/dev/null 2>&1; then
|
||||
error "netcat (nc) required for HTTP mode"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
{
|
||||
read -r request
|
||||
if [[ "$request" =~ ^GET\ /metrics ]]; then
|
||||
echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain; version=0.0.4\r\n\r"
|
||||
generate_metrics
|
||||
else
|
||||
echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r"
|
||||
echo "<html><head><title>NFS Server Exporter</title></head><body><h1>NFS Server Prometheus Exporter</h1><p><a href=\"/metrics\">Metrics</a></p></body></html>"
|
||||
fi
|
||||
} | nc -l -p "$HTTP_PORT" -q 1 2>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# MAIN EXECUTION
|
||||
# ============================================================================
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
if ! acquire_lock; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$HTTP_MODE" = true ]; then
|
||||
run_http_server
|
||||
elif [ -n "$OUTPUT_FILE" ]; then
|
||||
local output_dir
|
||||
output_dir="$(dirname "$OUTPUT_FILE")"
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
local temp_file
|
||||
temp_file=$(mktemp "${output_dir}/.nfsd_metrics.XXXXXX")
|
||||
|
||||
if ! generate_metrics > "$temp_file" 2>/dev/null; then
|
||||
rm -f "$temp_file"
|
||||
error "Failed to generate metrics"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local file_lines
|
||||
file_lines=$(wc -l < "$temp_file" 2>/dev/null || echo 0)
|
||||
|
||||
if [ "$file_lines" -lt 5 ]; then
|
||||
rm -f "$temp_file"
|
||||
error "Metrics file too small ($file_lines lines), keeping previous"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 644 "$temp_file"
|
||||
mv -f "$temp_file" "$OUTPUT_FILE"
|
||||
|
||||
log "Metrics written to $OUTPUT_FILE ($file_lines lines)"
|
||||
else
|
||||
generate_metrics
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user