#! /bin/bash . /usr/src/m2/framework/bash_functions.sh if [ -e /etc/mor/system.conf ]; then SYSTEM="mor" else SYSTEM="m2" fi LOG_FILE=/var/log/$SYSTEM/elasticsearch_resync.log SERVER_ID=$(sed 's/ //g' /etc/$SYSTEM/system.conf | grep server_id | awk -F"=" '{print $2}') MAIN_DB_IP=`sed 's/ //g' /etc/$SYSTEM/system.conf | grep MAIN_DB_IP | awk -F"=" '{print $2}'` DAY_RESYNC_TIMEOUT_MINUTES=60 DEBUG=0 FULL=0 PERIOD=0 FULL_ARG_STRING="" PERIOD_ARG_STRING="" MIN_CALLDATE="" MAX_CALLDATE="" ES_DB_HOST="" log() { DATE=$(date +"%Y-%m-%d %H:%M:%S") MSG=$1 echo "[$DATE] $MSG" >> $LOG_FILE } debug () { if [ "$DEBUG" == "1" ]; then log "$1" fi } mysql() { DATA=$(MYSQL_PWD="$DB_PASSWORD" /usr/bin/mysql -h "$ES_DB_HOST" -u "$DB_USERNAME" $P_OPT "$DB_NAME" "$@") echo $DATA } es_db_data_matches() { local day=$1 local es_count=$2 local db_count=$3 local current_day=$(date +"%Y-%m-%d") local yesterday=$(date +"%Y-%m-%d" -d "1 day ago") local matches=1 # Special case when resyncing current day and yesterday (due to active calls) if [ "$day" == "$current_day" ] || [ "$day" == "$yesterday" ]; then if [ $es_count -lt $db_count ] && [ $db_count -gt 0 ]; then matches=0 else matches=1 fi else if [ $es_count -eq $db_count ]; then matches=1 else matches=0 fi fi echo "$matches" } check_es_status() { if ! service elasticsearch status &> /dev/null; then echo "Elasticsearch is not running, exiting..." exit 1 fi } ############################################################################### #################################### MAIN ##################################### ############################################################################### PATH=$PATH:/usr/sbin:/sbin:/usr/bin # Maybe another instance is already running? pidof -o %PPID -x $0 > /dev/null && echo "Script $0 is already running" && exit 1 echo "" echo "Available options:" echo " elasticsearch resync - resync only missing data" echo " elasticsearch resync 2021-01-01 2021-01-15 - resync only missing data on selected period" echo " elasticsearch resync full - force full resync (delete all ES data and resync)" echo " elasticsearch resync full 2021-01-01 2021-01-15 - delete ES data on selected period and then resync it" echo "" set_database_variables # Reset log echo "" > $LOG_FILE # Exit if elasticsearch is not running check_es_status # Check arguments for arg in "$@" do arg_lower=`echo "$arg" | awk '{print tolower($0)}'` # Show debug messages? if [ "$arg_lower" == "debug" ]; then DEBUG=1 fi # Force full resync? if [ "$arg_lower" == "full" ]; then FULL=1 fi # Got resync period? if date -d "$arg_lower" &> /dev/null; then if [ "$MIN_CALLDATE" == "" ]; then MIN_CALLDATE=$arg_lower elif [ "$MAX_CALLDATE" == "" ]; then MAX_CALLDATE=$arg_lower fi fi done if [ "$MAIN_DB_IP" != "" ]; then ES_DB_HOST=$MAIN_DB_IP else ES_DB_HOST=$DB_HOST fi # If both dates are set, then we are resyncing period if [ "$MIN_CALLDATE" != "" ] && [ "$MAX_CALLDATE" != "" ]; then PERIOD=1 MIN_CALLDATE=$(echo $MIN_CALLDATE | cut -c1-10) MAX_CALLDATE=$(echo $MAX_CALLDATE | cut -c1-10) fi if [ "$FULL" == "1" ]; then FULL_ARG_STRING="full " fi if [ "$PERIOD" == "1" ]; then PERIOD_ARG_STRING=" for period $MIN_CALLDATE - $MAX_CALLDATE" fi if [ "$PERIOD" == "0" ]; then MIN_CALLDATE=$(mysql -sNe "SELECT SUBSTR(MIN(calldate), 1, 10) FROM calls") MAX_CALLDATE=$(mysql -sNe "SELECT SUBSTR(MAX(calldate), 1, 10) FROM calls") if [ "$MIN_CALLDATE" == "0000-00-00" ]; then echo "Found 0000-00-00 calldate in calls table, something is wrong, exiting..." log "Found 0000-00-00 calldate in calls table, something is wrong, exiting..." exit 1 fi if [ "$MAX_CALLDATE" == "NULL" ] || [ "$MIN_CALLDATE" == "NULL" ] || [ "$MAX_CALLDATE" == "" ] || [ "$MIN_CALLDATE" == "" ]; then echo "No calls in database? Aborting..." log "No calls in database? Aborting..." exit 0 fi fi DAYS=$(mysql -sNe "SELECT DATEDIFF('$MAX_CALLDATE 00:00:00', '$MIN_CALLDATE 00:00:00')") log "----------------------------------" log "Min calldate: $MIN_CALLDATE" log "Max calldate: $MAX_CALLDATE" log "Days to check: $(expr $DAYS + 1)" log "----------------------------------" log "Starting elasticsearch ${FULL_ARG_STRING}resync${PERIOD_ARG_STRING}..." log "----------------------------------" if [ "$FULL" == "1" ] && [ "$PERIOD" == "0" ]; then elasticsearch index delete &> /dev/null sleep 2 elasticsearch index create &> /dev/null fi # For development environment host_name=`hostname` if [ "$host_name" == "dev.kolmisoft.com" ]; then curl --silent --show-error --connect-timeout 3 -XPOST "http://127.0.0.1:9200/_aliases" -d ' { "actions" : [ { "add" : { "index" : "mor", "alias" : "m2" } } ] }' &> /dev/null fi echo "Starting elasticsearch ${FULL_ARG_STRING}resync${PERIOD_ARG_STRING}..." echo "" echo "Script will now run in background, check log $LOG_FILE" echo "If you want to stop script, execute command killall -9 $(basename $0)" # Run in background (for i in $(seq 0 ${DAYS}); do RESYNC_DAY=$(date -I -d "${MAX_CALLDATE} -$i days") if [ "$FULL" == "1" ] && [ "$PERIOD" == "1" ]; then # Delete ES data curl -XDELETE "http://localhost:9200/${DB_NAME}/calls/_query?q=calldate:\[$RESYNC_DAY\T00:00:00+TO+$RESYNC_DAY\T23:59:59\]" &> /dev/null sleep 3 fi DB_COUNT=$(mysql -sNe "SELECT COUNT(id) FROM calls WHERE calldate BETWEEN '$RESYNC_DAY 00:00:00' and '$RESYNC_DAY 23:59:59'") ES_COUNT=$(curl -s -XGET "localhost:9200/${DB_NAME}/calls/_count?q=calldate:\[$RESYNC_DAY\T00:00:00+TO+$RESYNC_DAY\T23:59:59\]&pretty" | grep count | cut -d"," -f1 | cut -d" " -f5) PREV_ES_COUNT=0 if [ "$(es_db_data_matches $RESYNC_DAY $ES_COUNT $DB_COUNT)" == "0" ]; then log "Resyncing $RESYNC_DAY, DB calls: $DB_COUNT, ES calls: $ES_COUNT" START_TIME=$(date +%s) # Delete ES data curl -XDELETE "http://localhost:9200/${DB_NAME}/calls/_query?q=calldate:\[$RESYNC_DAY\T00:00:00+TO+$RESYNC_DAY\T23:59:59\]" &> /dev/null sleep 3 # Resync interval elasticsearch resync interval "$RESYNC_DAY" "$RESYNC_DAY" &> /dev/null while [ "$(es_db_data_matches $RESYNC_DAY $ES_COUNT $DB_COUNT)" == "0" ]; do CURRENT_TIME=$(date +%s) TOTAL_SECONDS_RUNNING=$(expr $CURRENT_TIME - $START_TIME) MINUTES_RUNNING=$(expr $TOTAL_SECONDS_RUNNING / 60) SECONDS_RUNNING=$(expr $TOTAL_SECONDS_RUNNING - $MINUTES_RUNNING \* 60) if [ $MINUTES_RUNNING -gt $DAY_RESYNC_TIMEOUT_MINUTES ]; then log "Tried to resync period $RESYNC_DAY but failed to finish in $DAY_RESYNC_TIMEOUT_MINUTES minutes (ES count: $ES_COUNT, DB count: $DB_COUNT)" log "Exiting script..." exit 1 fi PREV_ES_COUNT=$ES_COUNT ES_COUNT=$(curl -s -XGET "localhost:9200/${DB_NAME}/calls/_count?q=calldate:\[$RESYNC_DAY\T00:00:00+TO+$RESYNC_DAY\T23:59:59\]&pretty" | grep count | cut -d"," -f1 | cut -d" " -f5) if [ "$PREV_ES_COUNT" != "$ES_COUNT" ] || [ "$DEBUG" == "1" ]; then log " -- progress $ES_COUNT/$DB_COUNT (elapsed time ${MINUTES_RUNNING}min ${SECONDS_RUNNING}sec)" fi sleep 3 done else log "Nothing to resync for $RESYNC_DAY, DB calls: $DB_COUNT, ES calls: $ES_COUNT" fi # Start syncing when first (latest) day is resynced if [ "$FULL" == "1" ] && [ "$PERIOD" == "0" ] && [ "$i" == "0" ]; then elasticsearch sync start &> /dev/null sleep 2 fi done log "Finished") &