#!/usr/bin/env bash
set -uo pipefail
#
# Check numeric OIDs against an SNMP v2c agent.
#
# Usage:
# ./validate-oids.sh <input-file> <agent-address> \
# <existing-output> <removed-output>
#
# Example:
# ./validate-oids.sh \
# aqnos_oids.txt \
# 192.168.100.100 \
# existing_oids.txt \
# removed_oids.txt
#
# SNMP settings:
# Version: v2c
# Community: public
#
if [[ $# -ne 4 ]]; then
echo "Usage: $0 <input-file> <agent-address> <existing-output> <removed-output>" >&2
exit 1
fi
INPUT_FILE="$1"
AGENT="$2"
EXISTING_FILE="$3"
REMOVED_FILE="$4"
COMMUNITY="public"
if [[ ! -f "$INPUT_FILE" ]]; then
echo "Error: input file does not exist: $INPUT_FILE" >&2
exit 1
fi
if ! command -v snmpwalk >/dev/null 2>&1; then
echo "Error: snmpwalk is not installed." >&2
exit 1
fi
# Clear/create output files.
: > "$EXISTING_FILE"
: > "$REMOVED_FILE"
TOTAL=0
KEPT=0
REMOVED=0
ERRORS=0
while IFS= read -r oid || [[ -n "$oid" ]]; do
# Remove Windows CR.
oid="${oid%$'\r'}"
# Remove leading/trailing whitespace.
oid="${oid#"${oid%%[![:space:]]*}"}"
oid="${oid%"${oid##*[![:space:]]}"}"
# Ignore blank lines.
[[ -z "$oid" ]] && continue
((TOTAL += 1))
echo "Checking: $oid" >&2
#
# Run snmpwalk and capture both output and exit status.
#
# Using "if" here prevents a non-zero snmpwalk exit code
# from terminating the script.
#
if output=$(
snmpwalk \
-v2c \
-c "$COMMUNITY" \
-t 2 \
-r 1 \
"$AGENT" \
"$oid" \
2>&1
); then
status=0
else
status=$?
fi
#
# OID explicitly doesn't exist.
#
if grep -Eqi \
'No Such Object|No Such Instance|NoSuchObject|NoSuchInstance' \
<<< "$output"
then
echo " REMOVED: no such object/instance" >&2
echo "$oid" >> "$REMOVED_FILE"
((REMOVED += 1))
continue
fi
#
# Successful SNMP query.
#
if [[ $status -eq 0 ]]; then
echo " EXISTS" >&2
echo "$oid" >> "$EXISTING_FILE"
((KEPT += 1))
continue
fi
#
# Unexpected error:
# timeout, unreachable agent, authentication problem, etc.
#
# We do NOT classify the OID as missing because the failure
# does not prove that the OID itself does not exist.
#
echo " ERROR: could not determine OID status" >&2
echo " $output" >&2
((ERRORS += 1))
done < "$INPUT_FILE"
echo >&2
echo "========================================" >&2
echo "Validation finished" >&2
echo "========================================" >&2
echo "Agent: $AGENT" >&2
echo "Input: $INPUT_FILE" >&2
echo "Existing OIDs: $EXISTING_FILE" >&2
echo "Removed OIDs: $REMOVED_FILE" >&2
echo >&2
echo "Checked: $TOTAL" >&2
echo "Existing: $KEPT" >&2
echo "Removed: $REMOVED" >&2
echo "Other errors: $ERRORS" >&2