Files
nym/scripts/test-nodes-pings.sh

97 lines
2.7 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
API_URL="${API_URL:-https://validator.nymtech.net/api/v1/nym-nodes/described}"
CONCURRENCY="${CONCURRENCY:-64}" # how many pings in flight
PING_TIMEOUT="${PING_TIMEOUT:-7}" # seconds to wait for a single echo reply
PING_RETRIES="${PING_RETRIES:-1}" # additional attempts after the first failure
RETRY_DELAY="${RETRY_DELAY:-1}" # seconds to wait between attempts
OK_CSV="ping_works.csv"
BAD_CSV="ping_not_working.csv"
# check deps for sanity
need() { command -v "$1" >/dev/null 2>&1 || { echo "Missing '$1'"; exit 1; }; }
need curl
need jq
need xargs
need nl
need ping
# fetch /described to json
echo "Fetching gateways description from: ${API_URL}"
tmp_json="$(mktemp)"
trap 'rm -f "$tmp_json" "$ip_list" "$num_list"' EXIT
curl -fsSL --retry 3 --retry-delay 1 --compressed "$API_URL" -o "$tmp_json"
# extract IPs
ip_list="$(mktemp)"
jq -r '
.data[]?
| (.description.host_information.ip_address? // [])[]
' "$tmp_json" \
| awk '
# very permissive IPv4/IPv6 syntax filters (we let ping validate the rest)
function is_ipv4(s){ return (s ~ /^[0-9]{1,3}(\.[0-9]{1,3}){3}$/) }
function is_ipv6(s){ return (index(s,":") > 0) }
{ if(is_ipv4($0) || is_ipv6($0)) print $0 }
' \
| sort -u > "$ip_list"
TOTAL="$(wc -l < "$ip_list" | tr -d '[:space:]')"
if [[ "$TOTAL" -eq 0 ]]; then
echo "No IP addresses found in API response. Exiting."
exit 1
fi
echo "Collected ${TOTAL} unique IP addresses to probe."
# outputs
printf "ip\n" > "$OK_CSV"
printf "ip\n" > "$BAD_CSV"
num_list="$(mktemp)"
nl -ba "$ip_list" > "$num_list"
# probe function executed in parallel via xargs
export PING_TIMEOUT OK_CSV BAD_CSV TOTAL PING_RETRIES RETRY_DELAY
probe_one() {
IFS=',' read -r idx ip <<< "$1"
# returns 0 = success, 1 = failure after retries
do_ping_with_retry() {
local ip="$1"
local attempts=$((1 + PING_RETRIES))
local i
for ((i=1; i<=attempts; i++)); do
if [[ "$ip" == *:* ]]; then
ping -6 -c 1 -W "$PING_TIMEOUT" "$ip" >/dev/null 2>&1 && return 0
else
ping -c 1 -W "$PING_TIMEOUT" "$ip" >/dev/null 2>&1 && return 0
fi
# wait before next try if not the last attempt
(( i < attempts )) && sleep "$RETRY_DELAY"
done
return 1
}
if do_ping_with_retry "$ip"; then
printf "%s\n" "$ip" >> "$OK_CSV"
printf "[%s/%s] ping ok %s\n" "$idx" "$TOTAL" "$ip"
else
printf "%s\n" "$ip" >> "$BAD_CSV"
printf "[%s/%s] ping failed %s\n" "$idx" "$TOTAL" "$ip"
fi
}
export -f probe_one
awk '{printf "%s,%s\n",$1,$2}' "$num_list" \
| xargs -P "$CONCURRENCY" -n 1 -I{} bash -c 'probe_one "$@"' _ {}
echo "Done. Results:"
echo " $(($(wc -l < "$OK_CSV") - 1)) reachable -> $OK_CSV"
echo " $(($(wc -l < "$BAD_CSV") - 1)) not reachable -> $BAD_CSV"