meta data for this page
  •  

TSM Smart Replicator

Ez a szkript a node replikációkat hivatott vezérelni úgy, hogy mindig egy megadott maximum darabszámú (REPLMAXNUM) replikációt futtat. Meghatározott időközönként (REFRESHRATE) figyeli, hogy hány replikációs processz fut épp, és akkor indítja a következőt, mikor ez a szám a REPLMAXNUM alá csökken. A node-ok listáját a szerverről olvassa ki, a REPLSTATE=ENABLED és REPLMODE=SEND/SYNCSEND paraméterű node-okkal dolgozik. Ha az INFINITERUN=true, akkor ha a node-ok listájának végére ér, kezdi elölről, friss node listával. Ha vannak node-ok, amiket ki szeretnénk venni az automatizált replikációból, azokat az EXCLUDENODES változóban kell felsorolni. Ha a REMEMBER_LAST_NODE=true, akkor a szkript leállítása esetén, következő induláskor nem kezdi előről a node listát, hanem megpróbálja folytatni az utoljára replikált node-tól, amit a LAST_NODE_FILE változóban megadott fájlban tárol.

tsm_smart_replicator.sh
#!/bin/sh
#                                                               #
# TSM Smart Replicator v1.4 (2026.03.26) - Ágoston Péter        #
#                                                               #
#################################################################
TSMSERVER=tsm1
TSMUSER=admin
TSMPASS=password
REPLMAXNUM=4   # konkurrens replikacios processzek szama max
INFINITERUN=true
REFRESHRATE=10
MAXSESSNUM=1
MAXPROCRUNTIME=5 # Max mennyi oraig futhat egy replikacio
MAXPROCRUNTIMEEXCLUDE='CLIENT0[1-3]-[TP]'  # Ezeket a node-okat nem lovi ki a MAXPROCRUNTIME eltelte utan sem
LOGFILE=/var/log/tsm_smart_replicator.log
REMEMBER_LAST_NODE=true
LAST_NODE_FILE=/tmp/tsm_smart_replicator.last_node
EXCLUDELOCKED=true
EXCLUDENODES=''
 
# ------------- Innen mar neked valoszinuleg nem kell piszkalni semmit, ha csak nem en vagy ----------
 
DSMADMC="dsmadmc -id=$TSMUSER -pa=$TSMPASS -se=$TSMSERVER -dataonly=y -displ=tabl"
 
if [[ $EXCLUDELOCKED = true ]]; then
#    SQL_OPTS=" and locked='NO' and not node_name like 'RMAN_%'"
    SQL_OPTS=" and n.locked='NO' "
fi
 
trap 'echo "$(date "+%Y.%m.%d %H:%M") PROGRAM TERMINATED" | tee -a $LOGFILE;kill $$' SIGINT SIGTERM;
 
echo "$(date "+%Y.%m.%d %H:%M") PROGRAM START (TSMSERVER=$TSMSERVER, REPLMAXNUM=$REPLMAXNUM, INFINITERUN=$INFINITERUN, REFRESHRATE=${REFRESHRATE}m)" | tee -a $LOGFILE
LAST_NODE=$(cat $LAST_NODE_FILE)
LAST_NODE_IS_REAL=$($DSMADMC "select count(*) from nodes where node_name='$LAST_NODE'" | sed 's/[^0-9]//')
if [[ "$LAST_NODE_IS_REAL" -eq 0 ]]; then LAST_NODE=''; fi
FIRSTRUN=true
CYCLE=1
while [ $INFINITERUN = true ] || [ $FIRSTRUN = true ]; do
    ACT_NODE_NUM=0
    FIRSTRUN=false
    STARTTIME=$(date +"%s")
    STARTTIME=$(($STARTTIME / 60))
    echo "$(date "+%Y.%m.%d %H:%M") CYCLE START ($CYCLE)" | tee -a $LOGFILE
    REPL_NODE_NUM=`$DSMADMC "select count(n.node_name) from nodes n where n.repl_state='ENABLED' and n.repl_mode in ('SEND','SYNCSEND') $SQL_OPTS" | sed 's/[^0-9]*//'`
        $DSMADMC "select n.node_name from nodes n LEFT JOIN REPLICATIONVIEW r ON n.node_name=r.node_name where n.repl_state='ENABLED' and n.repl_mode in ('SEND','SYNCSEND') $SQL_OPTS group by n.node_name order by max(case when r.COMP_STATE='COMPLETE' then r.END_TIME else '1956-09-05-00.00.00' end)" | while read NODE; do
        # Megprobaljuk onnan folytatni, ahol utoljara abbahagytuk a kort
        if [ "$REMEMBER_LAST_NODE" = "true" ] && [ "$LAST_NODE_IS_REAL" -eq 1 ] && [ "$NODE" != "$LAST_NODE" ]; then
            echo "$(date "+%Y.%m.%d %H:%M") A $NODE node kihagyasa, mert folytatjuk onnan, ahol abbahagytuk." >> $LOGFILE
            ACT_NODE_NUM=$((ACT_NODE_NUM+1))
            continue;
        fi
        LAST_NODE_IS_REAL=0
        # Ha nem fut meg a node-ra replikacio, elinditjuk ra
        if [ $($DSMADMC "select count(*) from processes where status like '% $NODE.%'") -eq 0 ] && [ "$(echo $EXCLUDENODES | grep -c $NODE)" -eq 0 ]; then
            REPLNUM=$($DSMADMC "select count(*) from processes where process='Replicate Node'" | sed 's/[^0-9]//g')
            ACTREPLNODES=$($DSMADMC "select status from processes where process='Replicate Node'" | grep -v 'AN[SR]' | sed -e 's/\(^.*node.s. \)\([^.]*\)\(.*$\)/\2/' | sed ':a;N;$!ba;s/\n/, /g')
            echo ${ACTREPLNODES%%,*} > $LAST_NODE_FILE
                echo "$(date "+%Y.%m.%d %H:%M") Futo replikaciok szama: $REPLNUM ($ACT_NODE_NUM/$REPL_NODE_NUM) | Varakozik: $NODE | Replikacio alatt: $ACTREPLNODES" | tee -a $LOGFILE
            # Varunk, amig lesz replikacios "slot"
            while [ $REPLNUM -ge $REPLMAXNUM ]; do
                echo "$(date "+%Y.%m.%d %H:%M") ${REFRESHRATE}p varakozas..." | tee -a $LOGFILE
                sleep $(($REFRESHRATE*60))
                ONCE=0
                # Ha egy processz MAXPROCRUNTIME oranal regebb ota fut, kilojuk
                $DSMADMC "select process_num from processes where int((current_timestamp - start_time)hours + day(current_timestamp - start_time))>$MAXPROCRUNTIME and process='Replicate Node' and not REGEXP_LIKE(STATUS, 'Replicating node\(s\) '${MAXPROCRUNTIMEEXCL}\.')" | grep -o '^ *[0-9]*$' | grep -v 'AN[SR]' | sed 's/ *//' | while read PROCESS_NUM; do
                        if [ $ONCE -eq 0 ]; then echo "$(date "+%Y.%m.%d %H:%M") $MAXPROCRUNTIME oranal regebb ota futo replikaciok kilovese:" | tee -a $LOGFILE; fi
                                $DSMADMC "cancel proc $PROCESS_NUM" | tee -a $LOGFILE
                        if [ $ONCE -eq 0 ]; then echo "$(date "+%Y.%m.%d %H:%M") 1p varakozas..." | tee -a $LOGFILE; sleep 60; fi
                        ONCE=1
                done
                REPLNUM=$($DSMADMC "select count(*) from processes where process='Replicate Node'" | sed 's/[^0-9]//g')
                ACTREPLNODES=$($DSMADMC "select status from processes where process='Replicate Node'" | grep -v 'AN[SR]' | sed -e 's/\(^.*node.s. \)\([^.]*\)\(.*$\)/\2/' | sed ':a;N;$!ba;s/\n/, /g')
                echo "$(date "+%Y.%m.%d %H:%M") Futo replikaciok szama: $REPLNUM ($ACT_NODE_NUM/$REPL_NODE_NUM) | Varakozik: $NODE | Replikacio alatt: $ACTREPLNODES" | tee -a $LOGFILE
            done
            $DSMADMC "repl node $NODE maxsess=$MAXSESSNUM forcerecon=y" | tee -a $LOGFILE
            ACT_NODE_NUM=$((ACT_NODE_NUM+1))
            # Ha mar csak egy slot van, varunk egy percet, hatha nincs mit replikalni, hogy mehessunk tovabb
            if [ $(($REPLMAXNUM-$REPLNUM)) -eq 1 ]; then echo "$(date "+%Y.%m.%d %H:%M") 1p varakozas..." | tee -a $LOGFILE; sleep 60; fi
        else
            echo "$(date "+%Y.%m.%d %H:%M") A $NODE kihagyasra kerul, mert EXCLUDE-olva van, vagy mar epp fut ra replikacio." | tee -a $LOGFILE
        fi
        done
    ENDTIME=$(date +"%s")
    ENDTIME=$(($ENDTIME / 60))
    RUNTIME=$(($ENDTIME-$STARTTIME))
    echo "$(date "+%Y.%m.%d %H:%M") CYCLE END ($CYCLE) | RUNTIME: $(($RUNTIME / 60))h $(($RUNTIME % 60))m" | tee -a $LOGFILE
    echo | tee -a $LOGFILE
    echo "$(date "+%Y.%m.%d %H:%M") ${REFRESHRATE}p varakozas..." | tee -a $LOGFILE
    sleep $(($REFRESHRATE*60))
    CYCLE=$(($CYCLE + 1))
    LAST_NODE_IS_REAL=0
    >$LAST_NODE_FILE
    unset LAST_NODE
done
echo "$(date "+%Y.%m.%d %H:%M") PROGRAM END" | tee -a $LOGFILE

Systemd .service fájl:

/etc/systemd/system/tsm_smart_replicator.service
[Unit]
Description=IBM Tivoli Storage Manager Smart Replicator
After=local-fs.target network-online.target
 
[Service]
Type=simple
GuessMainPID=no
ExecStart=/scripts/tsm_smart_replicator.sh >/dev/null 2>&1 &
Restart=on-failure
 
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl enable tsm_smart_replicator
# systemctl start tsm_smart_replicator
# systemctl status tsm_smart_replicator