Since the update of June 18th, all LibreNMS alerts were reset to unaknowledged. I had about 180 unacknowledged alerts
At first I began to acknowledge each alert one by one, but I quickly became tired of it. I looked around but couldn’t find a way to quickly acknowledge all outstanding alerts. So I turned to Claude.ai and it gave me this bash script:
#!/bin/bash
# Configuration
API_TOKEN="YOUR-API-TOKEN-HERE"
LIBRENMS_URL="https://your-librenms-address-here"
# Function to acknowledge a single alert
ack_alert() {
local alert_id=$1
local note="$2"
echo "Acknowledging alert ID: $alert_id"
if [ -n "$note" ]; then
RESPONSE=$(curl -s -k -X PUT \
-H "X-Auth-Token: $API_TOKEN" \
-d "note=$note" \
"$LIBRENMS_URL/api/v0/alerts/$alert_id")
else
RESPONSE=$(curl -s -k -X PUT \
-H "X-Auth-Token: $API_TOKEN" \
"$LIBRENMS_URL/api/v0/alerts/$alert_id")
fi
if echo "$RESPONSE" | jq -e '.status == "ok"' > /dev/null 2>&1; then
echo "✓ Successfully acknowledged alert $alert_id"
else
echo "✗ Failed to acknowledge alert $alert_id"
echo " Response: $RESPONSE"
fi
}
# Function to acknowledge multiple alerts
ack_multiple_alerts() {
local alert_ids=("$@")
local success_count=0
local fail_count=0
echo "=== Acknowledging ${#alert_ids[@]} alerts ==="
echo ""
for alert_id in "${alert_ids[@]}"; do
if ack_alert "$alert_id"; then
((success_count++))
else
((fail_count++))
fi
sleep 0.5 # Small delay to avoid overwhelming the API
done
echo ""
echo "=== Summary ==="
echo "Successfully acknowledged: $success_count"
echo "Failed: $fail_count"
}
# Function to acknowledge all active alerts
ack_all_alerts() {
echo "=== Fetching all active alerts for acknowledgment ==="
RESPONSE=$(curl -s -k -H "X-Auth-Token: $API_TOKEN" "$LIBRENMS_URL/api/v0/alerts?state=1")
if ! echo "$RESPONSE" | jq -e '.status == "ok"' > /dev/null 2>&1; then
echo "Error: Failed to fetch alerts"
echo "Response: $RESPONSE"
exit 1
fi
ALERT_IDS=($(echo "$RESPONSE" | jq -r '.alerts[].id'))
TOTAL_COUNT=${#ALERT_IDS[@]}
if [ $TOTAL_COUNT -eq 0 ]; then
echo "No active alerts to acknowledge!"
exit 0
fi
echo "Found $TOTAL_COUNT active alerts"
echo ""
read -p "Are you sure you want to acknowledge ALL $TOTAL_COUNT alerts? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
ack_multiple_alerts "${ALERT_IDS[@]}"
else
echo "Operation cancelled"
fi
}
# Function to acknowledge alerts from a specific date
ack_alerts_by_date() {
local target_date="$1"
echo "=== Fetching alerts from $target_date ==="
RESPONSE=$(curl -s -k -H "X-Auth-Token: $API_TOKEN" "$LIBRENMS_URL/api/v0/alerts?state=1")
if ! echo "$RESPONSE" | jq -e '.status == "ok"' > /dev/null 2>&1; then
echo "Error: Failed to fetch alerts"
echo "Response: $RESPONSE"
exit 1
fi
# Filter alerts by date and get their IDs
ALERT_IDS=($(echo "$RESPONSE" | jq -r --arg date "$target_date" '
.alerts[] |
select(.timestamp | startswith($date)) |
.id'))
TOTAL_COUNT=${#ALERT_IDS[@]}
if [ $TOTAL_COUNT -eq 0 ]; then
echo "No active alerts found for date: $target_date"
echo ""
echo "Available dates in current alerts:"
echo "$RESPONSE" | jq -r '.alerts[].timestamp' | cut -d' ' -f1 | sort | uniq -c | sort -nr
exit 0
fi
echo "Found $TOTAL_COUNT active alerts from $target_date"
echo ""
# Show a preview of the alerts
echo "Preview of alerts from $target_date:"
echo "$RESPONSE" | jq -r --arg date "$target_date" '
.alerts[] |
select(.timestamp | startswith($date)) |
" ID: " + (.id | tostring) + " - " + .timestamp +
(if .hostname then " (" + .hostname + ")" else "" end)' | head -10
if [ $TOTAL_COUNT -gt 10 ]; then
echo " ... and $((TOTAL_COUNT - 10)) more"
fi
echo ""
read -p "Acknowledge all $TOTAL_COUNT alerts from $target_date? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
ack_multiple_alerts "${ALERT_IDS[@]}"
else
echo "Operation cancelled"
fi
}
# Function to acknowledge alerts from a date range
ack_alerts_by_date_range() {
local start_date="$1"
local end_date="$2"
echo "=== Fetching alerts from $start_date to $end_date ==="
RESPONSE=$(curl -s -k -H "X-Auth-Token: $API_TOKEN" "$LIBRENMS_URL/api/v0/alerts?state=1")
if ! echo "$RESPONSE" | jq -e '.status == "ok"' > /dev/null 2>&1; then
echo "Error: Failed to fetch alerts"
echo "Response: $RESPONSE"
exit 1
fi
# Filter alerts by date range
ALERT_IDS=($(echo "$RESPONSE" | jq -r --arg start "$start_date" --arg end "$end_date" '
.alerts[] |
select((.timestamp | strptime("%Y-%m-%d %H:%M:%S") | mktime) >= ($start | strptime("%Y-%m-%d") | mktime) and
(.timestamp | strptime("%Y-%m-%d %H:%M:%S") | mktime) <= (($end + " 23:59:59") | strptime("%Y-%m-%d %H:%M:%S") | mktime)) | .id'))
TOTAL_COUNT=${#ALERT_IDS[@]}
if [ $TOTAL_COUNT -eq 0 ]; then
echo "No active alerts found between $start_date and $end_date"
exit 0
fi
echo "Found $TOTAL_COUNT active alerts between $start_date and $end_date"
echo ""
read -p "Acknowledge all $TOTAL_COUNT alerts from this date range? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
ack_multiple_alerts "${ALERT_IDS[@]}"
else
echo "Operation cancelled"
fi
}
# Function to show usage
show_usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -a, --all Acknowledge all active alerts"
echo " -i, --ids ID1,ID2,... Acknowledge specific alert IDs (comma-separated)"
echo " -d, --date YYYY-MM-DD Acknowledge all alerts from a specific date"
echo " -r, --range START_DATE END_DATE Acknowledge alerts from date range (YYYY-MM-DD format)"
echo " -n, --note 'text' Add a note to the acknowledgment"
echo " -h, --help Show this help message"
echo ""
echo "Examples:"
echo " $0 --all # Acknowledge all alerts"
echo " $0 --ids 27194,27195,27196 # Acknowledge specific alerts"
echo " $0 --date 2025-06-23 # Acknowledge all alerts from today"
echo " $0 --date 2025-06-22 # Acknowledge all alerts from yesterday"
echo " $0 --range 2025-06-20 2025-06-22 # Acknowledge alerts from date range"
echo " $0 --date 2025-06-23 --note 'Maintenance' # Acknowledge with note"
echo ""
echo "Date formats:"
echo " - Use YYYY-MM-DD format (e.g., 2025-06-23)"
echo " - Times are included automatically (full day for single date)"
echo ""
}
# Parse command line arguments
ACKNOWLEDGE_ALL=false
ALERT_IDS=()
NOTE=""
TARGET_DATE=""
START_DATE=""
END_DATE=""
while [[ $# -gt 0 ]]; do
case $1 in
-a|--all)
ACKNOWLEDGE_ALL=true
shift
;;
-i|--ids)
IFS=',' read -ra ALERT_IDS <<< "$2"
shift 2
;;
-d|--date)
TARGET_DATE="$2"
shift 2
;;
-r|--range)
START_DATE="$2"
END_DATE="$3"
shift 3
;;
-n|--note)
NOTE="$2"
shift 2
;;
-h|--help)
show_usage
exit 0
;;
*)
echo "Unknown option: $1"
show_usage
exit 1
;;
esac
done
# Main logic
if [ "$ACKNOWLEDGE_ALL" = true ]; then
ack_all_alerts
elif [ ${#ALERT_IDS[@]} -gt 0 ]; then
echo "Note: $NOTE"
ack_multiple_alerts "${ALERT_IDS[@]}"
elif [ -n "$TARGET_DATE" ]; then
# Validate date format
if ! date -d "$TARGET_DATE" >/dev/null 2>&1; then
echo "Error: Invalid date format. Use YYYY-MM-DD (e.g., 2025-06-23)"
exit 1
fi
ack_alerts_by_date "$TARGET_DATE"
elif [ -n "$START_DATE" ] && [ -n "$END_DATE" ]; then
# Validate date formats
if ! date -d "$START_DATE" >/dev/null 2>&1 || ! date -d "$END_DATE" >/dev/null 2>&1; then
echo "Error: Invalid date format. Use YYYY-MM-DD (e.g., 2025-06-23)"
exit 1
fi
ack_alerts_by_date_range "$START_DATE" "$END_DATE"
else
echo "No action specified."
show_usage
exit 1
Usage instructions:
$ ./ack_alerts.sh
No action specified.
Usage: ./ack_alerts.sh [OPTIONS]
Options:
-a, --all Acknowledge all active alerts
-i, --ids ID1,ID2,... Acknowledge specific alert IDs (comma-separated)
-d, --date YYYY-MM-DD Acknowledge all alerts from a specific date
-r, --range START_DATE END_DATE Acknowledge alerts from date range (YYYY-MM-DD format)
-n, --note 'text' Add a note to the acknowledgment
-h, --help Show this help message
Examples:
./ack_alerts.sh --all # Acknowledge all alerts
./ack_alerts.sh --ids 27194,27195,27196 # Acknowledge specific alerts
./ack_alerts.sh --date 2025-06-23 # Acknowledge all alerts from today
./ack_alerts.sh --date 2025-06-22 # Acknowledge all alerts from yesterday
./ack_alerts.sh --range 2025-06-20 2025-06-22 # Acknowledge alerts from date range
./ack_alerts.sh --date 2025-06-23 --note 'Maintenance' # Acknowledge with note
Date formats:
- Use YYYY-MM-DD format (e.g., 2025-06-23)
- Times are included automatically (full day for single date)
I ran the script for those alerts and it acknowledged every single one of them.
Here’s the log of another run I did today:
$ ./ack_alerts.sh --date 2025-06-25
=== Fetching alerts from 2025-06-25 ===
Found 6 active alerts from 2025-06-25
Preview of alerts from 2025-06-25:
ID: 26986 - 2025-06-25 20:12:33 (10.132.32.50)
ID: 26987 - 2025-06-25 20:12:33 (10.132.32.50)
ID: 27007 - 2025-06-25 15:23:00 (10.33.64.50)
ID: 27059 - 2025-06-25 14:40:30 (10.33.200.23)
ID: 27078 - 2025-06-25 14:37:13 (10.33.200.15)
ID: 27052 - 2025-06-25 14:27:32 (10.33.200.16)
Acknowledge all 6 alerts from 2025-06-25? (y/N): y
=== Acknowledging 6 alerts ===
Acknowledging alert ID: 26986
✓ Successfully acknowledged alert 26986
Acknowledging alert ID: 26987
✓ Successfully acknowledged alert 26987
Acknowledging alert ID: 27007
✓ Successfully acknowledged alert 27007
Acknowledging alert ID: 27059
✓ Successfully acknowledged alert 27059
Acknowledging alert ID: 27078
✓ Successfully acknowledged alert 27078
Acknowledging alert ID: 27052
✓ Successfully acknowledged alert 27052
=== Summary ===
Successfully acknowledged: 6
Failed: 0