Validator health check

This script runs a full system health report for your X1 validator: it checks CPU, Memory, Disk I/O, Network latency, Clock synchronization, and Vote Account activity — all in one run.

Overview

Check
Purpose

CPU / Load

Ensures node isn’t CPU-bound

Memory / Swap

Detects paging or low RAM

Disk I/O

Measures NVMe read/write latency

Network

Measures ping to rpc.mainnet.x1.xyz

NTP / Clock

Verifies system time sync

Vote Account

Confirms validator is actively voting


Usage

  1. Copy the full script below into a file named x1_health.sh:

    nano x1_health.sh
  2. Make it executable:

    chmod +x x1_health.sh
  3. Run:

    ./x1_health.sh

Full Script

#!/bin/bash
# === X1 Validator Health Report ===
# Checks CPU, Memory, Disk I/O, Network, NTP, and Vote Activity

set -euo pipefail

echo "=============================================="
echo "🧠 X1 Validator Health Report"
echo "=============================================="
echo ""

# --- CPU & Load ---
echo "🔹 CPU & Thread Load"
echo "   → Measures overall CPU load and idle capacity."
CPU_MODEL=$(lscpu | grep "Model name" | awk -F: '{print $2}' | sed 's/^[ \t]*//')
LOAD=$(uptime | awk -F'load average:' '{print $2}' | xargs)
CPU_LINE=$(top -bn1 | grep "%Cpu" | head -1)
CPU_IDLE=$(echo "$CPU_LINE" | awk '{for(i=1;i<=NF;i++){if($i=="id,"){print $(i-1)}}}' | sed 's/,//')
CPU_IDLE=${CPU_IDLE:-$(echo "$CPU_LINE" | awk '{print $8}' | sed 's/,//')}
echo "CPU Model: $CPU_MODEL"
echo "Load Average: $LOAD"
echo "CPU Idle: ${CPU_IDLE:-unknown}%"
echo ""

# --- Memory ---
echo "🔹 Memory"
echo "   → Shows total, used, and cached memory (checks swap usage)."
free -h | awk 'NR==1 || NR==2 {print}'
SWAP_USED=$(free -m | awk '/Swap/ {print $3}')
echo "Swap used: ${SWAP_USED} MB"
echo ""

# --- Network ---
echo "🔹 Network latency to X1 RPC"
echo "   → Tests latency and packet loss to rpc.mainnet.x1.xyz."
PING_OUT=$(ping -c5 rpc.mainnet.x1.xyz)
PING_AVG=$(echo "$PING_OUT" | grep "rtt" | awk -F'/' '{print $5}')
echo "$PING_OUT" | grep "packets transmitted"
echo "Average ping: ${PING_AVG} ms"
echo ""

# --- Disk I/O (accurate NVMe parser) ---
echo "🔹 Disk I/O (5s sample)"
echo "   → Monitors live NVMe latency and utilization during validator operation."
IOSTAT_OUT=$(iostat -xm 1 5 | awk '/nvme/ {line=$0} END{print line}')
if [ -n "$IOSTAT_OUT" ]; then
  echo "$IOSTAT_OUT"
  R_LAT=$(echo "$IOSTAT_OUT" | awk '{print $10}')
  W_LAT=$(echo "$IOSTAT_OUT" | awk '{print $14}')
  UTIL=$(echo "$IOSTAT_OUT" | awk '{print $NF}')
else
  R_LAT="N/A"
  W_LAT="N/A"
  UTIL="N/A"
  echo "(No NVMe device detected — skipping latency check)"
fi
echo ""
echo "Avg Read Latency: ${R_LAT:-N/A} ms"
echo "Avg Write Latency: ${W_LAT:-N/A} ms"
echo "Disk Utilization: ${UTIL:-N/A} %"
echo ""

# --- NTP / Clock ---
echo "🔹 NTP / Clock sync"
echo "   → Verifies system clock and NTP synchronization status."
timedatectl status | grep -E "System clock|NTP service|synchronized|Time zone"
echo ""

# --- Vote Account Status ---
echo "🔹 Vote Account Activity"
echo "   → Confirms validator vote-account is active and submitting votes."
DEFAULT_VOTE_PATH="$HOME/.config/solana/vote-account.json"
if [ -f "$DEFAULT_VOTE_PATH" ]; then
  VOTE_ADDR=$(solana address -k "$DEFAULT_VOTE_PATH" 2>/dev/null || true)
else
  VOTE_FILE=$(find "$HOME/.config/solana" -maxdepth 1 -type f -name "*vote*.json" | head -n1 || true)
  if [ -n "$VOTE_FILE" ]; then
    VOTE_ADDR=$(solana address -k "$VOTE_FILE" 2>/dev/null || true)
  else
    VOTE_ADDR=""
  fi
fi

if [ -n "$VOTE_ADDR" ]; then
  echo "Detected vote account: $VOTE_ADDR"
  VOTE_INFO=$(solana vote-account "$VOTE_ADDR" 2>/dev/null || true)

  ROOT_SLOT=$(echo "$VOTE_INFO" | awk '/Root Slot:/ {print $3; exit}')
  LAST_VOTE=$(echo "$VOTE_INFO" | awk '/^- slot:/ {print $3; exit}')
  EPOCH_NUM=$(echo "$VOTE_INFO" | awk '/^- epoch:/ {print $3; exit}')

  echo "Root Slot: ${ROOT_SLOT:-N/A}"
  echo "Last Vote Slot: ${LAST_VOTE:-N/A}"
  echo "Epoch: ${EPOCH_NUM:-N/A}"

  if [[ "$LAST_VOTE" =~ ^[0-9]+$ ]]; then
    echo "Vote activity: ✅ Active (recent votes found)"
    VOTE_STATUS="✅ Voting active"
  else
    echo "Vote activity: ⚠️ No recent votes found"
    VOTE_STATUS="⚠️ Voting inactive"
  fi
else
  echo "⚠️ No vote-account.json found in ~/.config/solana/"
  VOTE_STATUS="⚠️ No vote account detected"
fi
echo ""

# --- Summary ---
echo "=============================================="
echo "✅ SUMMARY REPORT"
echo "=============================================="

if (( $(echo "$CPU_IDLE < 30" | bc -l) )); then CPU_STATUS="⚠️ High CPU usage"; else CPU_STATUS="✅ CPU OK"; fi
if (( SWAP_USED > 200 )); then MEM_STATUS="⚠️ Swap in use"; else MEM_STATUS="✅ Memory OK"; fi
if (( $(echo "$PING_AVG > 50" | bc -l) )); then NET_STATUS="⚠️ High latency"; else NET_STATUS="✅ Network OK"; fi
if [[ "$R_LAT" =~ ^[0-9.]+$ ]] && (( $(echo "$R_LAT > 2" | bc -l) )) || [[ "$W_LAT" =~ ^[0-9.]+$ ]] && (( $(echo "$W_LAT > 2" | bc -l) )); then
  DISK_STATUS="⚠️ Slow disk I/O"
else
  DISK_STATUS="✅ Disk OK"
fi
if timedatectl status | grep -q "synchronized: yes"; then CLOCK_STATUS="✅ Clock synced"; else CLOCK_STATUS="⚠️ NTP not synced"; fi

printf "%-15s %s\n" "CPU:" "$CPU_STATUS"
printf "%-15s %s\n" "Memory:" "$MEM_STATUS"
printf "%-15s %s\n" "Network:" "$NET_STATUS"
printf "%-15s %s\n" "Disk I/O:" "$DISK_STATUS"
printf "%-15s %s\n" "Clock:" "$CLOCK_STATUS"
printf "%-15s %s\n" "Vote:" "$VOTE_STATUS"
echo ""
echo "Done."
echo "=============================================="

Example Output

🧠 X1 Validator Health Report
CPU Model: AMD Ryzen 9 9900X 12-Core Processor
Load Average: 5.62, 5.58, 5.47
CPU Idle: 78.3%

Avg Read Latency: 0.15 ms
Avg Write Latency: 0.23 ms
Disk Utilization: 8.3 %

🔹 Vote Account Activity
Detected vote account: 7oTGUhJt72GgGczT5KzQsqEcnuiHz8Wd9Wo5ZsKmR4hX
Root Slot: 6163567
Last Vote Slot: 6163611
Epoch: 40
Vote activity: ✅ Active (recent votes found)

==============================================
✅ SUMMARY REPORT
==============================================
CPU:        ✅ CPU OK
Memory:     ✅ Memory OK
Network:    ✅ Network OK
Disk I/O:   ✅ Disk OK
Clock:      ✅ Clock synced
Vote:       ✅ Voting active
Done.
==============================================

Notes

  • Run it as your validator user (not root) for accurate environment checks.

  • Requires: bc, sysstat, and solana CLI in $PATH. Install with:

    sudo apt install -y bc sysstat

Last updated