Posting For records.
Note: These scripts tested against Elasticsearch 2.4.3 which is EOL.
These scripts may or may not work with newer versions of elastic.
1] Details:
A] Node1: 10.226.71.1 (Master + Data)
B] Node2: 10.226.71.2 (Data)
2] Step-by-Step NFS Setup on CentOS. (If not exsists.)
A] On node1 (NFS Server):
#sudo yum install -y nfs-utils
Create backup directory:
#sudo mkdir -p /mnt/es_backup
#sudo chown -R elasticsearch:elasticsearch /mnt/es_backup
#sudo chmod 750 /mnt/es_backup
Configure /etc/exports:
#echo "/mnt/es_backup 10.226.71.2(rw,sync,no_root_squash)" | sudo tee -a /etc/exports
Start and enable NFS services:
#sudo systemctl enable nfs-server
#sudo systemctl start nfs-server
#sudo exportfs -ra
#sudo systemctl restart nfs-server
Confirm export:
#exportfs -v
B] On node2
(NFS Client):
Install NFS packages:
sudo yum install -y nfs-utils
Create mount directory:
#sudo mkdir -p /mnt/es_backup
Mount the shared folder:
#sudo mount 10.226.71.1:/mnt/es_backup /mnt/es_backup
Make it permanent (optional):
#10.226.71.1:/mnt/es_backup /mnt/es_backup nfs defaults 0 0
Set Proper Permissions:
Make sure the `elasticsearch` user on both nodes can access /mnt/es_backup:
sudo chown -R elasticsearch:elasticsearch /mnt/es_backup
sudo chmod 750 /mnt/es_backup
3] Java Setup:
Note: You may face issue like below, therefore set compatible java version.
Unrecognized VM option 'UseParNewGC'
Error: Could not create the Java Virtual Machine.
A] Check current Java:
java -version
B] If version is NOT 1.8, install OpenJDK 8:
sudo apt-get install openjdk-8-jdk # Ubuntu/Debian
sudo yum install java-1.8.0-openjdk # CentOS/RHEL
C] Set JAVA_HOME for Elasticsearch:
# vi ~/.bashrc
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64
export PATH=$JAVA_HOME/bin:$PATH
# Save above & run command > source ~/.bashrc
D] Version must show something like:
java version "1.8.0_412"
E] If still unable to see the desire version number then,
sudo alternatives --install /usr/bin/java java /usr/lib/jvm/java-1.8.0-openjdk-*/bin/java 1
sudo alternatives --config java
# Second command will show available java versions, enter appropriate input after second command.
4] Ingest data:
# vim bulk_web_logs.json
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.1", "timestamp": "2025-06-13T10:00:00", "request": "GET /index.html HTTP/1.1", "status": 200, "bytes": 1043 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.2", "timestamp": "2025-06-13T10:01:00", "request": "POST /form HTTP/1.1", "status": 201, "bytes": 523 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.3", "timestamp": "2025-06-13T10:02:00", "request": "GET /about.html HTTP/1.1", "status": 404, "bytes": 234 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.4", "timestamp": "2025-06-13T10:03:00", "request": "GET /contact HTTP/1.1", "status": 200, "bytes": 872 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.5", "timestamp": "2025-06-13T10:04:00", "request": "GET /index.html HTTP/1.1", "status": 304, "bytes": 0 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.6", "timestamp": "2025-06-13T10:05:00", "request": "GET /style.css HTTP/1.1", "status": 200, "bytes": 643 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.7", "timestamp": "2025-06-13T10:06:00", "request": "GET /favicon.ico HTTP/1.1", "status": 404, "bytes": 123 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.8", "timestamp": "2025-06-13T10:07:00", "request": "POST /login HTTP/1.1", "status": 401, "bytes": 231 }
{ "index": { "_index": "web-logs", "_type": "log" } }
{ "clientip": "192.168.1.9", "timestamp": "2025-06-13T10:08:00", "request": "GET /dashboard HTTP/1.1", "status": 200, "bytes": 983 }
# Save the file and load.
# curl -XPOST "http://10.226.71.1:9200/_bulk" --data-binary @bulk_web_logs.json -H "Content-Type: application/json"
5] Configure Snapshot Repositor, Script for Backup & Restore (Snapshot):
A] Configure Snapshot Repository (Run once)
Note: /mnt/es_backup must exist on both nodes and be accessible.
curl -XPUT 'http://10.226.71.1:9200/_snapshot/my_backup' -d '{
"type": "fs",
"settings": {
"location": "/mnt/es_backup",
"compress": true
}
}'
> Add following in elasticsearch.yml:
path.repo: ["/mnt/es_backup"]
B1] Backup Script (backup.sh)
>#!/bin/bash
SNAPSHOT_NAME="snapshot-$(date +%Y-%m-%d_%H-%M)"
#SNAPSHOT_NAME="snapshot-$(date +%Y%m%d%H%M)"
REPO="my_backup"
ES_HOST="10.226.71.1:9200"
curl -XPUT "$ES_HOST/_snapshot/$REPO/$SNAPSHOT_NAME?wait_for_completion=true" -d '{
"indices": "*",
"ignore_unavailable": true,
"include_global_state": true
}'
B2] Backup script with delete older snapshots.
#!/bin/bash
# Config
REPO="my_backup"
ES_HOST="10.226.71.1:9200"
SNAPSHOT_NAME="snapshot-$(date +%Y-%m-%d_%H-%M)"
SNAPSHOT_DATE_FORMAT="+%Y-%m-%d_%H-%M"
RETENTION_DAYS=10
# Create a new snapshot
curl -XPUT "$ES_HOST/_snapshot/$REPO/$SNAPSHOT_NAME?wait_for_completion=true" -d '{
"indices": "*",
"ignore_unavailable": true,
"include_global_state": true
}'
# Get current time in epoch
now_epoch=$(date +%s)
# Get list of all snapshots
snapshots=$(curl -s "$ES_HOST/_snapshot/$REPO/_all" | grep -oP '"snapshot"\s*:\s*"\K[^"]+')
# Loop through snapshots and delete older than retention
for snap in $snapshots; do
# Extract timestamp from snapshot name
snap_date_str=$(echo "$snap" | sed -n 's/snapshot-\(.*\)/\1/p')
# Convert to epoch (only if matches expected date format)
if [[ $snap_date_str =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}$ ]]; then
snap_epoch=$(date -d "${snap_date_str//_/ }" +%s 2>/dev/null)
if [[ $? -eq 0 ]]; then
age_days=$(( (now_epoch - snap_epoch) / 86400 ))
if (( age_days > RETENTION_DAYS )); then
echo ""
echo "Deleting snapshot $snap (age: $age_days days)"
curl -XDELETE "$ES_HOST/_snapshot/$REPO/$snap"
fi
fi
fi
done
B3] Dedicated script to delete older snapshots.
#!/bin/bash
# Configuration
REPO="my_backup"
ES_HOST="10.226.71.1:9200"
RETENTION_DAYS=10
# Get current time in epoch
now_epoch=$(date +%s)
# Get list of all snapshots
snapshots=$(curl -s "$ES_HOST/_snapshot/$REPO/_all" | grep -oP '"snapshot"\s*:\s*"\K[^"]+')
# Loop through snapshots
for snap in $snapshots; do
# Extract timestamp from snapshot name (assumes format snapshot-YYYY-MM-DD_HH-MM)
snap_date_str=$(echo "$snap" | sed -n 's/snapshot-\(.*\)/\1/p')
if [[ $snap_date_str =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}$ ]]; then
snap_epoch=$(date -d "${snap_date_str//_/ }" +%s 2>/dev/null)
if [[ $? -eq 0 ]]; then
age_days=$(( (now_epoch - snap_epoch) / 86400 ))
if (( age_days > RETENTION_DAYS )); then
echo "Deleting snapshot $snap (age: $age_days days)"
curl -s -XDELETE "$ES_HOST/_snapshot/$REPO/$snap"
fi
fi
fi
done
C] Restore Script (restore.sh)
#!/bin/bash
SNAPSHOT_NAME=$1 # pass snapshot name as argument
REPO="my_backup"
ES_HOST="10.226.71.1:9200"
if [ -z "$SNAPSHOT_NAME" ]; then
echo "Usage: $0 <snapshot-name>"
exit 1
fi
curl -XPOST "$ES_HOST/_snapshot/$REPO/$SNAPSHOT_NAME/_restore" -d '{
"indices": "*",
"include_global_state": true,
"rename_pattern": "index_(.+)",
"rename_replacement": "restored_index_$1"
}'
6] Optional: Cron Job for Backup:
0 2 * * * /path/to/backup.sh >> /var/log/es_backup.log 2>&1
0 2 * * * /path/to/backup.sh > /dev/null 2>&1
7] To restore:
Backup files in "/mnt/es_backup/ " may looks like "snap-snapshot-2025-06-13_19-32.dat, meta-snapshot-2025-06-13_19-32.dat" . To restore, run following command.
# sh restore.sh snapshot-2025-06-13_19-32
8] Elasticsearch Start & Restart Script:
#start.sh
#!/bin/bash
># Navigate to the Elasticsearch folder
>cd /opt/elastic-2.4.3/elasticsearch-2.4.3
# Start Elasticsearch in background and write output to a log file
nohup ./bin/elasticsearch > logs/es.out 2>&1 &
#restart.sh
#!/bin/bash
ES_DIR="/opt/elastic-2.4.3/elasticsearch-2.4.3"
ES_BIN="$ES_DIR/bin/elasticsearch"
# Kill existing process
echo "Stopping Elasticsearch..."
pkill -f elasticsearch
# Wait a bit
sleep 5
# Start again in background
echo "Starting Elasticsearch..."
cd "$ES_DIR"
nohup $ES_BIN > logs/es.out 2>&1 &
echo "Elasticsearch restarted."