Elasticsearch Index Cleanup Shell Script (Auto-Delete Old Indices)

elasticsearch index cleanup shell script

Log-shipping setups (Filebeat, Logstash) typically create one Elasticsearch index per day, like logs-2026.07.10. Left alone, these fill the disk. This script queries the cluster’s index list via the REST API and deletes anything older than your retention window — no Curator install needed.

What this script does

  • Lists indices matching a name pattern via the Elasticsearch/OpenSearch REST API
  • Parses the date suffix and compares it against a retention window
  • Deletes matching indices older than N days with a single curl call each
  • Dry-run mode to preview what would be deleted before enabling real deletes
  • Works against Elasticsearch or OpenSearch — both expose the same index-delete API

Prerequisites

  • curl and jq installed
  • Network access to the cluster’s HTTP API (usually port 9200)
  • An index naming pattern with a sortable date suffix, e.g. `logs-YYYY.MM.DD`

Step 1: Save the script

sudo nano /usr/local/bin/es-index-cleanup.sh
sudo chmod +x /usr/local/bin/es-index-cleanup.sh

Step 2: Full script (scroll to read)

es-index-cleanup.sh
#!/usr/bin/env bash
set -euo pipefail

ES_HOST="http://localhost:9200"
INDEX_PREFIX="logs-"
RETENTION_DAYS=30
DRY_RUN="${DRY_RUN:-false}"
LOG="/var/log/es-index-cleanup.log"

log(){ echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; }

command -v jq >/dev/null 2>&1 || { log "ERROR: jq not installed"; exit 1; }

cutoff=$(date -d "-${RETENTION_DAYS} days" +%Y.%m.%d 2>/dev/null || date -v-"${RETENTION_DAYS}"d +%Y.%m.%d)

log "Checking indices matching '${INDEX_PREFIX}*' older than ${RETENTION_DAYS} days (cutoff ${cutoff})"

indices=$(curl -s "${ES_HOST}/_cat/indices/${INDEX_PREFIX}*?h=index" | sort)

count=0
while read -r index; do
  [[ -z "$index" ]] && continue
  date_part="${index#"$INDEX_PREFIX"}"
  if [[ "$date_part" < "$cutoff" ]]; then
    age_days=$(( ( $(date +%s) - $(date -d "${date_part//./-}" +%s 2>/dev/null || echo 0) ) / 86400 ))
    if [[ "$DRY_RUN" == "true" ]]; then
      log "[DRY RUN] Would delete index: $index (age ${age_days}d)"
    else
      log "Deleting index: $index (age ${age_days}d)"
      curl -s -X DELETE "${ES_HOST}/${index}" >/dev/null
      count=$((count + 1))
    fi
  fi
done <<< "$indices"

log "Cleanup completed: ${count} indices removed"

Scroll inside the box to read the full script.

Step 3: Configure settings

  • ES_HOST — cluster endpoint, e.g. http://localhost:9200
  • INDEX_PREFIX — pattern prefix to match, e.g. logs-
  • RETENTION_DAYS — delete indices dated older than this
  • DRY_RUN — set to true to log deletions without executing them
Elasticsearch index cleanup shell script deleting old log indices
Elasticsearch index cleanup shell script deleting old log indices

Step 4: Test manually

DRY_RUN=true sudo /usr/local/bin/es-index-cleanup.sh
sudo /usr/local/bin/es-index-cleanup.sh

Schedule with cron

sudo crontab -e

Add:

0 3 * * * /usr/local/bin/es-index-cleanup.sh >> /var/log/es-index-cleanup.log 2>&1

Related tutorials

Terminal screenshot is an original illustration created for Gnome IT Solutions (blog.gnomeitsolutions.com).