Ana içeriğe geç

Elasticsearch Index Temizleme Scripti

Bu doküman, Apinizer trafik index'leri (apinizer_api_traffic_*) üzerinde disk alanı kazanmak için kullanılan tek dosyalık es_cleanup.sh scriptini anlatır.

Script vi ile açılır, en üstteki AYAR BÖLÜMÜ doldurulur ve çalıştırılır. Yapılacak işlem ve işlemin kapsamı, hangi alanların doldurulduğuna göre otomatik belirlenir.

Önemli - Geri Alınamaz İşlemler

Script geri alınamaz işlemler yapar. Çalıştırmadan önce ilgili index'in snapshot / yedeğinin alınmış olduğundan emin olun. İşlem öncesi DRY_RUN="true" ile planı kontrol etmeniz önerilir.

Script index'in tamamını silmez; yalnızca alan temizler veya döküman siler.

1) Ön Koşullar

  • Elasticsearch sunucusuna erişim (IP:PORT) ve ilgili index üzerinde yazma/yönetim yetkisi
  • curl ve jq araçlarının kurulu olması
# jq kurulu değilse
sudo apt update
sudo apt install -y jq

2) Yapılacak İşlemin Belirlenmesi

Ayar bölümündeki iki işlem alanından yalnızca biri kullanılır:

Doldurulan alanYapılan işlemYöntem
FIELDS="fcrb,tba"Seçilen alanlar temizlenir, dökümanlar kalır_update_by_query
DELETE_DOCS="true"Eşleşen dökümanlar silinir_delete_by_query

İkisi aynı anda doldurulursa script hata verip durur.

3) İşlemin Kapsamının Belirlenmesi

Kapsam alanları opsiyoneldir. Boş bırakılan filtre uygulanmaz:

Doldurulan alan(lar)Kapsam
HiçbiriIndex'teki tüm dökümanlar (match_all)
START_TS + END_TSSadece o zaman aralığındaki dökümanlar
PROXY_VALUESadece o proxy'ye ait dökümanlar
Her ikisi birdenProxy ve zaman aralığının kesişimi

Dolu olan filtreler bir bool.filter içinde birleştirilir.

bilgi

Alan Adları ve Filtre Alanları

  • Temizlenecek alanlar, dökümanın _source içindeki anahtar adıyla birebir eşleşmelidir. Apinizer template'indeki kısaltmalar kullanılır (fcrb, tba …), açıklama isimleri değil. Disk kullanımının büyük kısmını text tipindeki body alanları oluşturur:
AlanAçıklama
fcrbFrom Client Body
tbaTo Backend Body
fbarbFrom Backend Body
tcbTo Client Body
  • Proxy filtresi apn (API Proxy Adı) veya api (API Proxy ID) alanı üzerinden yapılır.
  • Zaman filtresi @timestamp alanı üzerinden yapılır. Format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z' (örnek: 2025-01-01T00:00:00.000Z). START_TS ve END_TS birlikte doldurulmalıdır.

4) Data Stream Kullanılıyorsa (.ds- ile başlayan index'ler)

Apinizer log index'leri data stream olarak yapılandırılmış olabilir. Bu durumda gerçek veri, adı .ds- ile başlayan backing index'lerde tutulur:

.ds-apinizer-log-apiproxy-qa8-2026.07.09-000025
Data Stream Adı Değil, Backing Index Adı Girilmelidir

Elasticsearch data stream'leri append-only kabul eder; bir data stream adına doğrudan _update_by_query veya _delete_by_query çalıştırılamaz. Bu nedenle INDEX ayarına data stream adı (apinizer-log-apiproxy-qa8) değil, backing index adı (.ds-apinizer-log-apiproxy-qa8-2026.07.09-000025) yazılmalıdır.

Bir data stream'in backing index'leri rollover ile çoğalır. Tüm data stream'i temizlemek için backing index'lerin listesi alınır ve script her biri için ayrı ayrı çalıştırılır:

# Backing index listesi
curl -s -u "elastic:PAROLA" -k -X GET \
"https://ES_HOST:ES_PORT/_data_stream/apinizer-log-apiproxy-qa8?pretty" \
| jq -r '.data_streams[].indices[].index_name'
# Alternatif: _cat ile boyutlariyla birlikte
curl -s -u "elastic:PAROLA" -k -X GET \
"https://ES_HOST:ES_PORT/_cat/indices/.ds-apinizer-log-apiproxy-qa8-*?v&h=index,docs.count,store.size&s=index"
bilgi

Aktif Backing Index

Bir data stream'in en yeni backing index'i yazma yapılan index'tir. Temizleme sırasında yeni döküman gelmeye devam edeceğinden, işlem sonrası döküman sayısı beklenenden farklı olabilir. Bu normaldir; conflicts=proceed sayesinde işlem durmaz.

ILM politikası backing index'i cold/frozen fazına aldıysa index read-only olabilir. Script bu durumu algılar, write bloğunu geçici açar ve işlem sonunda eski durumuna geri koyar.

5) Alan Temizleme Yöntemi

FIELD_MODE ayarı iki değer alır:

DeğerDavranış
remove (varsayılan)Alan _source'tan komple silinir
emptyAlan kalır, içeriği boş string ("") olur

Script painless içinde alanı containsKey() kontrolüyle işler. Böylece ilgili alanı zaten bulunmayan dökümanlar boş yere yeniden yazılmaz (gereksiz reindex ve _version artışı önlenir).

boolean changed = false;
if (ctx._source.containsKey('fcrb')) { ctx._source.remove('fcrb'); changed = true; }
if (!changed) { ctx.op = 'noop'; }
bilgi

ctx.op = 'noop' Neden Var?

_update_by_query, painless script _source'u hiç değiştirmese bile eşleşen her dökümanı yeniden yazar. Bu, gereksiz _version artışına, yeni segment oluşmasına ve boşa I/O harcanmasına yol açar.

Script, hiçbir alan değişmediğinde ctx.op = 'noop' atar; Elasticsearch bu dökümanlara hiç dokunmaz.

Pratik etkisi: aynı temizlik ikinci kez çalıştırıldığında (alanlar zaten silinmişse) tüm dökümanlar noops olarak raporlanır, disk ve CPU harcanmaz:

{"total":1387,"updated":0,"noops":1387,"deleted":0,"failures":[]}

Bu koruma olmasaydı aynı çalıştırma updated: 1387 gösterir ve 1387 döküman boşuna yeniden yazılırdı.

Alanın Dökümanda Kalmasını İstiyorsanız

Alanın silinmesini değil, yalnızca içeriğinin boşaltılmasını istiyorsanız (alan _source çıktısında görünmeye devam etsin, dökümanların şema yapısı bozulmasın) FIELD_MODE="empty" kullanın.

İki yöntemin karşılaştırması:

remove (varsayılan)empty
_source içindeki anahtarTamamen kaldırılır"fcrb": "" olarak kalır
Disk kazanımıEn yüksekSınırlı
API/dashboard çıktısıAlan hiç dönmezAlan boş string ile döner
exists sorgusu eşleşir mi?HayırEvet (boş string bir değerdir)

Disk alanı kazanmak birincil amaç olduğundan remove tercih edilmelidir. empty, yalnızca alanın çıktıda görünmeye devam etmesi gereken özel durumlarda kullanılmalıdır.

6) Güvenlik ve Kontrol Ayarları

AyarAçıklama
ES_PASSBoş bırakılırsa çalışma anında sorulur. Parolanın dosyada saklanmaması önerilir.
ES_USERKümede güvenlik kapalıysa (xpack.security.enabled: false) boş bırakılır; -u parametresi hiç kullanılmaz.
DRY_RUN"true" ise hiçbir değişiklik yapılmaz; plan, etkilenecek döküman sayısı ve üretilecek sorgu/painless script ekrana basılır.
SKIP_CONFIRM"true" ise onay sorulmaz. Yalnızca otomasyon için, dikkatli kullanılmalıdır.
FORCE_MERGE"true" ise işlem sonrası disk alanını geri kazanmak için force merge çalıştırılır.

Script ayrıca:

  • Çalıştırdığı her curl komutunu >> curl ... formatında ekrana basar; parolayı maskeler (kullanici:****).
  • İşlem öncesi _count ile etkilenecek döküman sayısını gösterir ve yes onayı ister.
  • Index read-only ise write bloğunu geçici açar, işlem sonunda önceki durumuna geri koyar.
  • https seçilirse self-signed sertifikalar için -k parametresini otomatik ekler.

7) Script

#!/bin/bash
# ============================================================================
# Apinizer - Elasticsearch Index Temizleme Scripti
# es_cleanup.sh
# ----------------------------------------------------------------------------
# Tum temizleme senaryolarini tek dosyada toplar.
# Scripti "vi es_cleanup.sh" ile acin, asagidaki AYAR BOLUMUNU doldurun.
# Hangi alanlari doldurdugunuza gore islem ve kapsam otomatik belirlenir.
#
# ISLEM (birini secin):
# FIELDS dolu -> secilen ALANLAR temizlenir (dokumanlar kalir)
# DELETE_DOCS="true" -> eslesen DOKUMANLAR silinir
#
# KAPSAM (opsiyonel, bos birakilanlar uygulanmaz):
# START_TS + END_TS -> sadece bu zaman araligindaki dokumanlar
# PROXY_VALUE -> sadece bu proxy'ye ait dokumanlar
# ikisi de bos -> index'teki TUM dokumanlar
#
# Not: Bu script index'in tamamini SILMEZ; yalnizca alan temizler
# veya dokuman siler.
#
# KULLANIM:
# vi es_cleanup.sh # AYAR BOLUMUNU doldurun
# chmod +x es_cleanup.sh
# ./es_cleanup.sh
# ============================================================================


# ############################################################################
# # AYAR BOLUMU (BURAYI DOLDURUN) #
# ############################################################################

# ---- Baglanti (ZORUNLU) ----------------------------------------------------
ES_HOST="10.10.10.10:9200" # IP:PORT
ES_PROTO="https" # http | https

# ---- Kimlik dogrulama (OPSIYONEL) ------------------------------------------
# Kumede guvenlik kapaliysa (xpack.security.enabled: false) ikisini de
# BOS birakin; -u parametresi hic kullanilmaz.
# ES_PASS bos birakilirsa calisma aninda sorulur (parolayi dosyada
# saklamak istemiyorsaniz onerilir).
ES_USER="elastic"
ES_PASS=""

# ---- Index (ZORUNLU) -------------------------------------------------------
INDEX="apinizer_api_traffic_v2"

# ############################################################################
# # ISLEM SECIMI - Asagidakilerden SADECE BIRINI kullanin #
# ############################################################################

# ---- ISLEM A: Alanlari temizle ---------------------------------------------
# Virgulle ayrilir. Dokumanin _source anahtarlariyla birebir eslesmelidir.
# Apinizer body alanlari (disk kullaniminin buyuk kismi):
# fcrb = From Client Body
# tba = To Backend Body
# fbarb = From Backend Body
# tcb = To Client Body
# BOS birakilirsa alan temizleme yapilmaz.
FIELDS="fcrb,tba,fbarb,tcb"

# Alan temizleme yontemi:
# "remove" -> alan _source'tan komple silinir (varsayilan, en yuksek disk kazanimi)
# "empty" -> alan kalir, icerigi "" olur (disk kazanimi sinirli)
FIELD_MODE="remove"

# ---- ISLEM B: Dokumanlari sil ----------------------------------------------
# "true" yapilirsa, asagidaki kapsama uyan DOKUMANLAR SILINIR.
# FIELDS ile ayni anda kullanilamaz (FIELDS'i bosaltin).
DELETE_DOCS="false"

# ############################################################################
# # KAPSAM (OPSIYONEL) - Bos birakilan filtre uygulanmaz #
# ############################################################################

# ---- Zaman araligi ---------------------------------------------------------
# Format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
# IKISI DE bos -> zaman filtresi yok (tum zamanlar)
# Biri dolu digeri bos birakilamaz.
START_TS="" # ornek: 2025-01-01T00:00:00.000Z
END_TS="" # ornek: 2025-02-01T00:00:00.000Z

# ---- Proxy -----------------------------------------------------------------
# PROXY_VALUE bos -> proxy filtresi yok (tum proxy'ler)
# PROXY_FIELD: apn = API Proxy Adi | api = API Proxy ID
PROXY_FIELD="apn"
PROXY_VALUE="" # ornek: MyProxy

# ############################################################################
# # DAVRANIS #
# ############################################################################

FORCE_MERGE="true" # Islem sonrasi disk alanini geri kazanmak icin
DRY_RUN="false" # "true" -> degisiklik yapmaz, sadece plani gosterir
SKIP_CONFIRM="false" # "true" -> onay sormaz (otomasyon; DIKKATLI KULLANIN)

# ############################################################################
# # AYAR BOLUMU SONU - ASAGISINA DOKUNMAYIN #
# ############################################################################


set -o pipefail

die() { echo "HATA: $*" >&2; exit 1; }

# ---------------------------------------------------------------------------
# Ayar dogrulama
# ---------------------------------------------------------------------------
command -v jq >/dev/null 2>&1 || die "'jq' kurulu degil. Kurun: sudo apt install -y jq"

[ -z "$ES_HOST" ] && die "ES_HOST bos olamaz."
[ -z "$INDEX" ] && die "INDEX bos olamaz."
[[ "$ES_PROTO" != "http" && "$ES_PROTO" != "https" ]] && die "ES_PROTO 'http' veya 'https' olmali."
[[ "$FIELD_MODE" != "remove" && "$FIELD_MODE" != "empty" ]] && die "FIELD_MODE 'remove' veya 'empty' olmali."
[[ "$PROXY_FIELD" != "apn" && "$PROXY_FIELD" != "api" ]] && die "PROXY_FIELD 'apn' veya 'api' olmali."

# Zaman araligi: ya ikisi de dolu ya ikisi de bos
[ -n "$START_TS" ] && [ -z "$END_TS" ] && die "START_TS dolu ama END_TS bos."
[ -z "$START_TS" ] && [ -n "$END_TS" ] && die "END_TS dolu ama START_TS bos."

# Islem secimi: tam olarak biri
if [ -n "$FIELDS" ] && [ "$DELETE_DOCS" == "true" ]; then
die "FIELDS ile DELETE_DOCS ayni anda kullanilamaz. Ya alanlari temizleyin ya dokumanlari silin."
fi
if [ -z "$FIELDS" ] && [ "$DELETE_DOCS" != "true" ]; then
die "Yapilacak islem yok. FIELDS doldurun veya DELETE_DOCS=\"true\" yapin."
fi

# ---------------------------------------------------------------------------
# Parola: dosyada bos birakildiysa calisma aninda sorulur
# ---------------------------------------------------------------------------
if [ -n "$ES_USER" ] && [ -z "$ES_PASS" ]; then
read -s -p "Elasticsearch parolasi ($ES_USER): " ES_PASS
echo ""
fi

BASE_URL="$ES_PROTO://$ES_HOST"
CURL_OPTS=(-s)
[ -n "$ES_USER" ] && CURL_OPTS+=(-u "$ES_USER:$ES_PASS") # Basic Auth (varsa)
[ "$ES_PROTO" == "https" ] && CURL_OPTS+=(-k) # https + self-signed

# Calistirilan curl komutunu (parola maskeli) ekrana basar
run_curl() {
local shown=() arg
for arg in "$@"; do
if [ -n "$ES_USER" ] && [[ "$arg" == "$ES_USER:$ES_PASS" ]]; then
shown+=("$ES_USER:****")
else
shown+=("$arg")
fi
done
echo ">> curl ${shown[*]}" >&2
curl "$@"
}

# ---------------------------------------------------------------------------
# Sorgu uretimi: dolu olan filtreler bool.filter icinde birlestirilir.
# Hicbir filtre yoksa match_all -> index'teki tum dokumanlar.
# ---------------------------------------------------------------------------
build_query() {
local filters=()
[ -n "$PROXY_VALUE" ] && filters+=("{\"term\":{\"$PROXY_FIELD\":\"$PROXY_VALUE\"}}")
[ -n "$START_TS" ] && filters+=("{\"range\":{\"@timestamp\":{\"gte\":\"$START_TS\",\"lte\":\"$END_TS\"}}}")

if [ ${#filters[@]} -eq 0 ]; then
echo '{"match_all":{}}'
else
local joined
joined=$(IFS=,; echo "${filters[*]}")
echo "{\"bool\":{\"filter\":[$joined]}}"
fi
}

# ---------------------------------------------------------------------------
# Painless script uretimi
# FIELD_MODE="remove" -> alan _source'tan komple silinir
# FIELD_MODE="empty" -> alan kalir, icerigi "" olur
#
# containsKey kontrolu, alani zaten olmayan dokumanlarda islem yapilmasini onler.
#
# ctx.op = 'noop': Hicbir alan degismediyse Elasticsearch dokumani hic yeniden
# yazmaz. Bu olmadan _update_by_query, script _source'u degistirmese bile her
# eslesen dokumani reindex eder (gereksiz _version artisi, segment copu, I/O).
# Ozellikle ayni temizlik ikinci kez calistirildiginda onemlidir; o calismada
# tum dokumanlar "noops" olarak raporlanir ve disk/CPU harcanmaz.
# ---------------------------------------------------------------------------
build_field_script() {
local input="$1" IFS=',' fields s="" f
read -r -a fields <<< "$input"
s="boolean changed = false; "
for f in "${fields[@]}"; do
f=$(echo "$f" | xargs)
[ -z "$f" ] && continue
if [ "$FIELD_MODE" == "remove" ]; then
s+="if (ctx._source.containsKey('$f')) { ctx._source.remove('$f'); changed = true; } "
else
s+="if (ctx._source.containsKey('$f') && ctx._source.$f != '') { ctx._source.$f = ''; changed = true; } "
fi
done
s+="if (!changed) { ctx.op = 'noop'; }"
echo "$s"
}

QUERY=$(build_query)

# ---------------------------------------------------------------------------
# Ozet
# ---------------------------------------------------------------------------
echo "===================================================================="
echo " YAPILACAK ISLEM"
echo "===================================================================="
echo " Sunucu : $BASE_URL"
echo " Kimlik : ${ES_USER:-<auth yok>}"
echo " Index : $INDEX"
if [ -n "$FIELDS" ]; then
if [ "$FIELD_MODE" == "remove" ]; then
echo " Islem : ALANLAR _source'TAN KOMPLE SILINECEK"
else
echo " Islem : ALANLARIN ICERIGI BOSALTILACAK (\"\")"
fi
echo " Alanlar : $FIELDS"
else
echo " Islem : DOKUMANLAR SILINECEK"
fi
echo " Kapsam :"
if [ -n "$PROXY_VALUE" ]; then
echo " proxy : $PROXY_FIELD = $PROXY_VALUE"
else
echo " proxy : (filtre yok, tum proxy'ler)"
fi
if [ -n "$START_TS" ]; then
echo " zaman : $START_TS -> $END_TS"
else
echo " zaman : (filtre yok, tum zamanlar)"
fi
if [ -z "$PROXY_VALUE" ] && [ -z "$START_TS" ]; then
echo " ==> Index'teki TUM dokumanlar islenecek."
fi
echo " Force merge : $FORCE_MERGE"
[ "$DRY_RUN" == "true" ] && echo " DRY_RUN : true (hicbir degisiklik yapilmayacak)"
echo "===================================================================="
echo ""

# ---------------------------------------------------------------------------
# Etkilenecek dokuman sayisi
# ---------------------------------------------------------------------------
echo "Etkilenecek dokuman sayisi kontrol ediliyor..."
COUNT=$(run_curl "${CURL_OPTS[@]}" -X POST "$BASE_URL/$INDEX/_count" \
-H 'Content-Type: application/json' -d "{\"query\":$QUERY}" | jq -r '.count')
echo "Etkilenecek dokuman sayisi: $COUNT"
echo ""

if [ -z "$COUNT" ] || [ "$COUNT" == "null" ]; then
die "Dokuman sayisi alinamadi. Baglanti bilgilerini ve index adini kontrol edin."
fi
if [ "$COUNT" == "0" ]; then
echo "Eslesen dokuman yok. Yapilacak islem yok."
exit 0
fi

# ---------------------------------------------------------------------------
# DRY_RUN
# ---------------------------------------------------------------------------
if [ "$DRY_RUN" == "true" ]; then
echo "DRY_RUN - calistirilacak sorgu:"
echo " $QUERY"
if [ -n "$FIELDS" ]; then
echo "DRY_RUN - calistirilacak painless script:"
echo " $(build_field_script "$FIELDS")"
fi
echo ""
echo "DRY_RUN aktif oldugundan hicbir degisiklik yapilmadi."
exit 0
fi

# ---------------------------------------------------------------------------
# Onay
# ---------------------------------------------------------------------------
if [ "$SKIP_CONFIRM" != "true" ]; then
read -p "Devam etmek icin 'yes' yazin: " CONFIRM
[ "$CONFIRM" != "yes" ] && { echo "Islem iptal edildi."; exit 1; }
echo ""
fi

# ---------------------------------------------------------------------------
# Write blogu / force merge yardimcilari
# ---------------------------------------------------------------------------
open_write() {
local wb
wb=$(run_curl "${CURL_OPTS[@]}" -X GET "$BASE_URL/$INDEX/_settings" \
| jq -r ".[\"$INDEX\"].settings.index.blocks.write")
if [ "$wb" == "true" ]; then
echo "Index read-only, write aciliyor..."
run_curl "${CURL_OPTS[@]}" -X PUT "$BASE_URL/$INDEX/_settings" \
-H 'Content-Type: application/json' -d '{"index.blocks.write": false}'
echo ""
RESTORE_READONLY="true"
else
RESTORE_READONLY="false"
fi
}
restore_write() {
if [ "$RESTORE_READONLY" == "true" ]; then
echo "Index tekrar read-only olarak ayarlaniyor..."
run_curl "${CURL_OPTS[@]}" -X PUT "$BASE_URL/$INDEX/_settings" \
-H 'Content-Type: application/json' -d '{"index.blocks.write": true}'
echo ""
fi
}
force_merge() {
[ "$FORCE_MERGE" != "true" ] && return
echo "Force merge calistiriliyor..."
run_curl "${CURL_OPTS[@]}" -X POST "$BASE_URL/$INDEX/_forcemerge?only_expunge_deletes=true&pretty" \
| tee forcemerge_result.json
echo ""
}

# ---------------------------------------------------------------------------
# Islem
# ---------------------------------------------------------------------------
open_write

if [ -n "$FIELDS" ]; then
SCRIPT=$(build_field_script "$FIELDS")
run_curl "${CURL_OPTS[@]}" -X POST "$BASE_URL/$INDEX/_update_by_query?conflicts=proceed&wait_for_completion=true" \
-H 'Content-Type: application/json' \
-d "{\"script\":{\"source\":\"$SCRIPT\",\"lang\":\"painless\"},\"query\":$QUERY}" \
| tee update_result.json
else
run_curl "${CURL_OPTS[@]}" -X POST "$BASE_URL/$INDEX/_delete_by_query?conflicts=proceed&wait_for_completion=true" \
-H 'Content-Type: application/json' -d "{\"query\":$QUERY}" \
| tee delete_result.json
fi
echo ""

force_merge
restore_write

# Ipucu komutu, calisma sirasinda kullanilan curl parametreleriyle ayni
# olacak sekilde uretilir (auth varsa -u, https ise -k).
HINT_AUTH=""
HINT_K=""
[ -n "$ES_USER" ] && HINT_AUTH="-u \"$ES_USER:PAROLA\" "
[ "$ES_PROTO" == "https" ] && HINT_K="-k "

echo "===================================================================="
echo "Islem tamamlandi."
echo "Not: Buyuk indexlerde disk alaninin hemen geri bosalmamasi normaldir."
echo "Index boyutunu kontrol etmek icin:"
echo " curl -s ${HINT_AUTH}${HINT_K}-X GET \"$BASE_URL/$INDEX/_stats/store?pretty\" | jq -r '._all.primaries.store.size_in_bytes'"
echo "===================================================================="

8) Çalıştırma

vi es_cleanup.sh # AYAR BÖLÜMÜNÜ doldurun
chmod +x es_cleanup.sh
./es_cleanup.sh

Örnek Ayarlar

Belirli bir proxy'nin, belirli tarih aralığındaki body alanlarını sil (data stream backing index üzerinde):

INDEX=".ds-apinizer-log-apiproxy-qa8-2026.07.09-000025"
FIELDS="tba,tcb"
FIELD_MODE="remove"
DELETE_DOCS="false"
START_TS="2026-07-09T13:10:00.600Z"
END_TS="2026-07-09T14:13:00.600Z"
PROXY_FIELD="apn"
PROXY_VALUE="testm"

Index'teki tüm dökümanların body alanlarını sil (filtresiz):

INDEX="apinizer_api_traffic_v2"
FIELDS="fcrb,tba,fbarb,tcb"
DELETE_DOCS="false"
START_TS=""
END_TS=""
PROXY_VALUE=""

Belirli tarih aralığındaki dökümanları tamamen sil:

INDEX="apinizer_api_traffic_v2"
FIELDS=""
DELETE_DOCS="true"
START_TS="2025-01-01T00:00:00.000Z"
END_TS="2025-02-01T00:00:00.000Z"
PROXY_VALUE=""

9) Örnek Çalışma Çıktısı

Script önce yapılacak işlemin özetini ve etkilenecek döküman sayısını gösterir:

====================================================================
YAPILACAK ISLEM
====================================================================
Sunucu : https://10.10.10.10:9200
Kimlik : elastic
Index : apinizer_api_traffic_v2
Islem : ALANLAR _source'TAN KOMPLE SILINECEK
Alanlar : fcrb,tba,fbarb,tcb
Kapsam :
proxy : apn = MyProxy
zaman : 2025-01-01T00:00:00.000Z -> 2025-02-01T00:00:00.000Z
Force merge : true
====================================================================

Etkilenecek dokuman sayisi kontrol ediliyor...
>> curl -s -u elastic:**** -k -X POST https://10.10.10.10:9200/apinizer_api_traffic_v2/_count ...
Etkilenecek dokuman sayisi: 4210

Devam etmek icin 'yes' yazin: yes

>> curl -s -u elastic:**** -k -X GET https://10.10.10.10:9200/apinizer_api_traffic_v2/_settings
Index read-only, write aciliyor...
>> curl -s -u elastic:**** -k -X POST https://10.10.10.10:9200/apinizer_api_traffic_v2/_update_by_query?...
{"took":1482,"timed_out":false,"total":2294,"updated":2294,"deleted":0,"batches":3,"version_conflicts":0,"noops":0,...,"failures":[]}

Force merge calistiriliyor...
{
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
}
}
Index tekrar read-only olarak ayarlaniyor...
====================================================================
Islem tamamlandi.
====================================================================

DRY_RUN="true" ile çalıştırıldığında hiçbir değişiklik yapılmaz, yalnızca plan gösterilir:

DRY_RUN - calistirilacak sorgu:
{"bool":{"filter":[{"term":{"apn":"MyProxy"}},{"range":{"@timestamp":{"gte":"2025-01-01T00:00:00.000Z","lte":"2025-02-01T00:00:00.000Z"}}}]}}
DRY_RUN - calistirilacak painless script:
if (ctx._source.containsKey('fcrb')) { ctx._source.remove('fcrb'); } if (ctx._source.containsKey('tba')) { ctx._source.remove('tba'); } ...

DRY_RUN aktif oldugundan hicbir degisiklik yapilmadi.
bilgi

Çıktının Yorumlanması

  • total — sorguyla eşleşen döküman sayısı
  • updated / deleted — gerçekten güncellenen / silinen döküman sayısı
  • noops — değişiklik gerekmediği için dokunulmayan döküman sayısı (alanlar zaten temizlenmişse beklenen değerdir)
  • version_conflictsconflicts=proceed sayesinde işlem durmaz; sıfırdan büyükse eşzamanlı yazma olmuştur
  • failures — boş dizi olmalıdır; dolu ise işlem kısmen başarısızdır
  • _shards.failed — force merge sonucunda 0 olmalıdır

10) Doğrulama

İşlem sonrası index boyutu kontrol edilir:

curl -s -u "elastic:PAROLA" -k -X GET "https://ES_HOST:ES_PORT/INDEX/_stats/store?pretty" \
| jq -r '._all.primaries.store.size_in_bytes'
Disk Boşalması

Büyük index'lerde disk alanının hemen geri boşalmaması normaldir. Force merge yüksek I/O maliyeti oluşturduğundan, işlemlerin iş yükünün düşük olduğu saatlerde çalıştırılması önerilir.

bilgi

Script update_result.json, delete_result.json ve forcemerge_result.json çıktı dosyalarını çalıştığı dizinde oluşturur.