====== LoadBalancer - BASH-Skript ======
**__Diese Skripte befinden sich z.Z. noch in der Testphase!__**
Vorbereitungen:
> cp /etc/ldirectord.cf /var/tmp/
> aptitude purge ldirectord
> aptitude update && aptitude install ifenslave net-tools ethtool wget ipvsadm
> cp /var/tmp/ldirectord.cf /etc/
so werden die neuen Skripte manuell benutzt:
/root/bin/LB_Modus.sh Start
/root/bin/LB_Modus.sh Stop
/root/bin/LB_Modus.sh Check
/root/bin/LB_Dienst.sh [Start|Restart|Reload]
/root/bin/LB_Dienst.sh [Stop|Halt]
=== Beschreibung der einzelnen Skript-Aufrufe ===
**''/root/bin/LB_Modus.sh Start''**
- dieser Aufruf fährt die öffentlichen IP's (virtuelle IP's) auf dem lo-IF hoch
- und bindet die internen IP's (realen IP's) an die öffentlichen IP's (virtuelle IP's)
**''/root/bin/LB_Modus.sh Stop''**
- dieser Aufruf trennt die internen IP's (realen IP's) von den öffentlichen IP's (virtuelle IP's)
- und fährt die öffentlichen IP's (virtuelle IP's) auf dem lo-IF runter
**''/root/bin/LB_Modus.sh Check''**
- dieser Aufruf kontrolliert einmal alle Verbindungen und setzt entsprechend die „Route“
**''/root/bin/LB_Dienst.sh [Start|Restart|Reload]''**
- dieser Aufruf führt den Aufruf ''/root/bin/LB_Modus.sh Start'' einmal aus
- leg die Datei ''/run/LB_Dienst.run'' an
- und führt anschließend das Kommando ''/root/bin/LB_Modus.sh Check'' zyklisch aus
- der zyklische Check läuft nur solange, wie die Datei ''/run/LB_Dienst.run'' existiert und in ihr die erwartete Zahl steht
**''/root/bin/LB_Dienst.sh [Stop|Halt]''**
- dieser Aufruf löscht die Datei ''/run/LB_Dienst.run''
- und führt anschließend das Kommando ''/root/bin/LB_Modus.sh Stop'' aus
===== Skripte =====
==== /root/bin/LB_Modus.sh ====
#!/bin/bash
#
# Betriebs-Modus
#
#set -x
#==============================================================================#
VERSION="v2015060900"
#------------------------------------------------------------------------------#
### damit auch alle Programme gefunden werden
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ARBEITSVERZEICHNIS="$(dirname ${0})"
#------------------------------------------------------------------------------#
### Monitor
#
# ipvsadm -Ln -c
# ipvsadm -Ln --timeout
# ipvsadm -Ln --daemon
# ipvsadm -Ln --stats
# ipvsadm -Ln --rate
# ipvsadm -Ln --thresholds
# ipvsadm -Ln --persistent-conn
#
#------------------------------------------------------------------------------#
### CFG-Block
#
# #INTERFACENAME:kunvictorv
# virtual=kundenservice.victorvox.de:80
# real=swvictor31lo.oqrm.public:80 gate
# real=swvictor21.oqrm.public:80 gate
# real=swvictor11.oqrm.public:80 gate
# service=http
# request="frei/ldirector.php"
# receive="Servicewelten.kundenservice.victorvox.de.71174"
# scheduler=wlc
# persistent=30
# protocol=tcp
# checktype=negotiate
#==============================================================================#
#==============================================================================#
### Funktionen
#------------------------------------------------------------------------------#
vorbereitung()
{
#----------------------------------------------------------------------#
### hier werden die CFG-Bloecke in Zeilen umgewandelt
###
### virtual=www.telco.de:80|real=symshtelco21.oqrm.public:80 gate|real=symshtelco11.oqrm.public:80 gate|real=symshtelco31lo.oqrm.public:80 gate|service=http|request="ldirector.php"|receive="SymfonyWebshop.www.telco.de.72980"|scheduler=wlc|persistent=30|protocol=tcp|checktype=negotiate
LDIRECTORD_CF="$(cat /etc/ldirectord.cf | sed 's/^[ \t]*//' | grep -Ev '^$|^#' | tr -s '\n' '|' | sed 's/|virtual=/\nvirtual=/g;s/|[ \t]*/|/g' | fgrep 'virtual=')"
export LDIRECTORD_CF
if [ -z "${LDIRECTORD_CF}" ] ; then
echo "In der Datei '/etc/ldirectord.cf' sind keine verwertbaren Verbindungsdaten enthalten."
echo "ABBRUCH!"
exit 1
fi
### nur zum testen
#echo "
#LDIRECTORD_CF='${LDIRECTORD_CF}'
#"
#------------------------------------------------------------------------------#
#------------------------------------------------------------------------------#
### hier werden die vorgesehenen Interface-Namen ermittelt
###
### www.telco.de wwwtelco
INTERFACENAME="$(cat /etc/ldirectord.cf | grep -FA1 INTERFACENAME | tr -s '\n' '|' | tr -s '#' '\n' | sed 's/:/|/g;s/virtual=//' | awk -F'|' '{print $3,$2}')"
export INTERFACENAME
if [ -z "${INTERFACENAME}" ] ; then
echo "In der Datei '/etc/ldirectord.cf' sind keine verwertbaren IF-Label enthalten."
echo "ABBRUCH!"
exit 1
fi
### nur zum testen
#echo "
#INTERFACENAME='${INTERFACENAME}'
#"
#exit 0
#------------------------------------------------------------------------------#
### hier werden die Hostnamen zu IP's aufgelöst
IP_FQDN="$(cat /etc/ldirectord.cf | sed 's/^[ \t]*//' | grep -E '^virtual=|^real=|^fallback=' | sed 's/[=:]/ /g' | awk '{print $2}' | sort | uniq | while read FQDN
do
### hier wird der FQDN in eine IP umgewandelt bzw. die IP uebernommen
IPADR="$(host ${FQDN} | fgrep 'has address' | awk '{print $NF}')"
if [ -z "${IPADR}" ] ; then
IPADR="${FQDN}"
fi
#----------------------------------------------------------------------#
echo "${IPADR}|${FQDN}"
done)"
export IP_FQDN
### nur zum testen
#echo "
#IP_FQDN='${IP_FQDN}'
#"
#exit 0
#------------------------------------------------------------------------------#
###
### der hier ist recht langsam und muss schneller werden
###
### hier werden die entsprechenden lo:interface-Namen vor die Zeilen gesetzt
LDIRECTORD_IFN_CF="$(echo "${LDIRECTORD_CF}" | grep -Ev '^$' | while read ZEILE
do
#----------------------------------------------------------------------#
unset BLOCK
BLOCK="$(echo "${ZEILE}" | tr -s '|' '\n')"
VIRTUAL="$(echo "${BLOCK}" | grep -F 'virtual=' | sed 's/virtual=//;s/:[0-9]*//')"
IFNAME="$(echo "${INTERFACENAME}" | grep -E "^${VIRTUAL}" | awk '{print $2}')"
### hier wird der FQDN in eine IP umgewandelt bzw. die IP uebernommen
VIPADR="$(echo "${IP_FQDN}" | grep -E "[|]${VIRTUAL}$" | awk -F'|' '{print $1}')"
#----------------------------------------------------------------------#
echo "${IFNAME}|${VIPADR}|${ZEILE}"
done)"
export LDIRECTORD_IFN_CF
if [ -z "${LDIRECTORD_IFN_CF}" ] ; then
echo "Die Daten aus der Datei '/etc/ldirectord.cf' sind nicht verwertbar."
echo "ABBRUCH!"
exit 1
fi
#echo "${LDIRECTORD_IFN_CF}" > /tmp/LDIRECTORD_IFN_CF.txt
echo "${LDIRECTORD_IFN_CF}" > /tmp/ipvsadm_Cluster.txt
#exit 0
#------------------------------------------------------------------------------#
#------------------------------------------------------------------------------#
### hier werden die lo:interface-Namen, die z.Z. montiert sind, ermittelt
###
IST_IPLOIF="$(ip a show dev lo | awk '/scope global/{print $2,$NF}')"
export IST_IPLOIF
IST_ALLELOIP="$(echo "${IST_IPLOIF}" | awk '{print $1}')"
export IST_ALLELOIP
IST_ALLELOIF="$(echo "${IST_IPLOIF}" | awk '{print $2}')"
export IST_ALLELOIF
}
#------------------------------------------------------------------------------#
#==============================================================================#
### Modus
case "${1}" in
[Ss][Tt][Aa][Rr][Tt])
vorbereitung
${ARBEITSVERZEICHNIS}/LB_Start.sh
echo "${0} ${1}" | logger -t LoadBalancer
shift
;;
[Ss][Tt][Oo][Pp])
${ARBEITSVERZEICHNIS}/LB_Stop.sh
echo "${0} ${1}" | logger -t LoadBalancer
shift
;;
[Cc][Hh][Ee][Cc][Kk])
vorbereitung
${ARBEITSVERZEICHNIS}/LB_Check.sh
shift
;;
[Ss][Tt][Aa][Tt][Uu][Ss])
ipvsadm -Ln
echo
ip a show dev lo | fgrep 'lo:'
echo
ps ax | fgrep -v grep | fgrep LB_Dienst
shift
;;
*)
echo "${0} Start"
echo "${0} Stop"
echo "${0} Check"
shift
exit 1
;;
esac
==== /root/bin/LB_Start.sh ====
#!/bin/bash
#
# Start
#
#set -x
#==============================================================================#
VERSION="v2015052100"
#------------------------------------------------------------------------------#
### damit auch alle Programme gefunden werden
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
#------------------------------------------------------------------------------#
### dieses Skript kann nicht einzeln gestartet werden
if [ -z "${LDIRECTORD_IFN_CF}" ] ; then
ARBEITSVERZEICHNIS="$(dirname ${0})"
echo "
${ARBEITSVERZEICHNIS}/LB_Modus.sh Start
${ARBEITSVERZEICHNIS}/LB_Modus.sh Stop
${ARBEITSVERZEICHNIS}/LB_Modus.sh Check
"
exit 1
fi
#==============================================================================#
### Funktionen
#------------------------------------------------------------------------------#
ip_out()
{
if [ -z "$(echo "${1}" | grep -E '[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*')" ] ; then
host ${1} | awk '{print $NF}'
else
echo ${1}
fi
}
#------------------------------------------------------------------------------#
#------------------------------------------------------------------------------#
### hier werden die lo:interface-Namen, die nicht in der CFG-Datei stehen,
### entfernt
###
#echo "
#LDIRECTORD_IFN_CF='${LDIRECTORD_IFN_CF}'
#"
TEMPDATEI="$(mktemp /tmp/LB_Start_XXXXXXXX)"
echo "${LDIRECTORD_IFN_CF}" | grep -Ev '^$' | awk -F'|' '{print $2}' | sort | uniq | while read IPNM
do
### egal was es ist, es wird eine IP ausgegeben
ip_out ${IPNM}
done | awk '{print " "$1"/"}' > ${TEMPDATEI}
#exit
#
# inet 10.31.2.178/32 brd 10.31.2.178 scope global lo:kontoch
# inet 193.227.192.234/32 brd 193.227.192.234 scope global lo:lizi_b2c
ip addr show dev lo | fgrep "scope global" | fgrep -vf ${TEMPDATEI} | while read ZEILE
do
# _INET VIPADR _BR _IP _SCOPE _GLOBAL UEIFLABEL
# oder
# _INET VIPADR _SCOPE _GLOBAL UEIFLABEL
VIPADR="$(echo "${ZEILE}" | awk '{print $2}' | grep -E '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*')"
_IPADR="$(echo "${VIPADR}" | sed 's#/.*##')"
IFLABEL="$(echo "${ZEILE}" | awk '{print $NF}' | grep -F ':')"
#echo "VIPADR='${VIPADR}'"
if [ -n "${VIPADR}" ] ; then
#echo "================================================================"
### Verbindungen aus dem LB entfernen
ipvsadm -Ln | fgrep "${_IPADR}:" | awk '{print $2}' | while read VIPPORT
do
ipvsadm -Lnt "${VIPPORT}" | grep -F '> ' | grep -E '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*' | awk '{print $2}' | while read RIPPORT
do
echo "-e -t ${VIPPORT} -r ${RIPPORT} -w 0
-d -t ${VIPPORT} -r ${RIPPORT}
-D -t ${VIPPORT}" | logger -t LoadBalancer
echo "-e -t ${VIPPORT} -r ${RIPPORT} -w 0
-d -t ${VIPPORT} -r ${RIPPORT}
-D -t ${VIPPORT}" | ipvsadm -R #2>/dev/null
done
done
if [ -n "${IFLABEL}" ] ; then
echo "ip addr del ${VIPADR} dev lo label ${IFLABEL}" | logger -t LoadBalancer
ip addr del ${VIPADR} dev lo label ${IFLABEL}
else
echo "ip addr del ${VIPADR} dev lo" | logger -t LoadBalancer
ip addr del ${VIPADR} dev lo
fi
fi
done
rm -f ${TEMPDATEI}
#==============================================================================#
echo "${LDIRECTORD_IFN_CF}" | while read ZEILE
do
#----------------------------------------------------------------------#
#echo "-----------------------------------------------------------------"
unset BLOCK
BLOCK="$(echo "${ZEILE}" | tr -s '|' '\n')"
IFNAME="$(echo "${ZEILE}" | grep -Ev '^$' | awk -F'|' '{print $1}' | head -n1)"
VIPADR="$(echo "${ZEILE}" | grep -Ev '^$' | awk -F'|' '{print $2}' | head -n1)"
VIRTUAL="$(echo "${BLOCK}" | grep -F 'virtual=' | sed 's/virtual=//;s/:[0-9]*//' | awk '{print $1}')"
### hier wird (wegen der Einfachheit) der Port von "virtual" auch fuer "real" verwendet
TCPPORTS="$(echo "${BLOCK}" | grep -F 'virtual=' | awk -F':' '{print $NF}' | awk '{print $1}')"
ALLEREALIPS="$(echo "${BLOCK}" | grep -F 'real=' | sed 's/real=//;s/:[0-9]*//' | awk '{print $1}')"
FALLBACK="$(echo "${BLOCK}" | grep -F 'fallback=' | sed 's/fallback=//;s/:[0-9]*//' | awk '{print $1}')"
SCHEDULER="$(echo "${BLOCK}" | grep -F 'scheduler=' | sed 's/scheduler=//' | awk '{print $1}')"
PERSISTENT="$(echo "${BLOCK}" | grep -F 'persistent=' | sed 's/persistent=//;s/["]//g' | awk '{print $1}')"
PROTOCOL="$(echo "${BLOCK}" | grep -F 'protocol=' | sed 's/protocol=//;s/["]//g' | awk '{print $1}')"
#----------------------------------------------------------------------#
### hier werden fehlende externe IPs an lo montiert
if [ -n "${IFNAME}" ] ; then
#ip addr | fgrep "${VIPADR}/32"
if [ -z "$(ip addr | fgrep "${VIPADR}/32")" ] ; then
#------------------------------------------------------#
# ip addr add 193.227.192.136/32 dev lo label lo:wwwtelco
# ip addr del 193.227.192.136/32 dev lo label lo:wwwtelco
ip addr add ${VIPADR}/32 dev lo label lo:${IFNAME}
if [ -z "$(ip addr | fgrep "${VIPADR}/32")" ] ; then
echo "Fehler: ${VIPADR}/32 - lo:${IFNAME}"
fi
fi
fi
#----------------------------------------------------------------------#
### hier werden die Server-Verbindungen aktiviert
(for TPORT in ${TCPPORTS}
do
echo "-A -t ${VIPADR}:${TPORT} -s ${SCHEDULER} -p ${PERSISTENT}"
for REAL_IP in ${ALLEREALIPS} ${FALLBACK}
do
echo "-a -t ${VIPADR}:${TPORT} -r ${REAL_IP}:${TPORT} -m"
echo "-e -t ${VIPADR}:${TPORT} -r ${REAL_IP}:${TPORT} -w 0"
done
done) | ipvsadm -R 2>/dev/null
done
==== /root/bin/LB_Stop.sh ====
#!/bin/bash
#
# Stop
#
#set -x
#==============================================================================#
VERSION="v2015060900"
#------------------------------------------------------------------------------#
### damit auch alle Programme gefunden werden
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
RUN="/run/LB_Dienst.run"
#==============================================================================#
### laufende Auftraege beenden
rm -f ${RUN} /tmp/ipvsadm_Check_* /tmp/LB_Check-Dienst_* /tmp/ipvsadm_Cluster.txt
#==============================================================================#
ipvsadm -Ln | awk '{print $1,$2}' | sed 's/[-][>]//g' | tr -s '\n' ' ' | sed 's/TCP/\nTCP/g' | grep -E '^TCP ' | while read TCP V_IPADR ALLE_REAL_IPS
do
#----------------------------------------------------------------------#
VIPADR="$(echo "${V_IPADR}" | sed 's/[:][0-9][0-9]*/ /g;s/[ \t]$//')"
TCPPORTS="$(echo "${V_IPADR}" | awk -F':' '{print $NF}')"
ALLEREALIPS="$(echo "${ALLE_REAL_IPS}" | sed 's/[:][0-9][0-9]*/ /g;s/[ \t]$//')"
#----------------------------------------------------------------------#
### hier werden die Server-Verbindungen aktiviert
(for TPORT in ${TCPPORTS}
do
for REAL_IP in ${ALLEREALIPS}
do
echo "-d -t ${VIPADR}:${TPORT} -r ${REAL_IP}:${TPORT}"
done
echo "-D -t ${VIPADR}:${TPORT}"
done) | ipvsadm -R 2>/dev/null
done
#------------------------------------------------------------------------------#
###
### hier werden alle lo:interfaces entfernt
###
ip a show dev lo | awk '/scope global/{print $2,$NF}' | while read LOIP LOIF
do
# echo "ip addr del ${LOIP} dev lo label ${LOIF}"
ip addr del ${LOIP} dev lo label ${LOIF}
done
#==============================================================================#
==== /root/bin/LB_Check.sh ====
#!/bin/bash
#
# Check
#
#set -x
#==============================================================================#
VERSION="v2015060900"
#------------------------------------------------------------------------------#
### damit auch alle Programme gefunden werden
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
WGETOPTS="-4 -l 0 --no-check-certificate --no-proxy --no-dns-cache --no-cache --no-cookies --no-http-keep-alive --ignore-length --max-redirect=0 --unlink -T 2 -t 1 -nc"
#------------------------------------------------------------------------------#
#
# Die Verbindungsüberprüfung wird auf eine Anzahl von Prozessen verteilt,
# die in dieser Variablen gespeichert wird.
#
# Sollte diese Variable leer sein, wird die Anzahl der CPU-Kerne verwendet.
#PROZESSE=8
if [ -z "${PROZESSE}" ] ; then
PROZESSE="$(grep -E '^processor' /proc/cpuinfo | wc -l)"
fi
#------------------------------------------------------------------------------#
### dieses Skript kann nicht einzeln gestartet werden
if [ -z "${LDIRECTORD_IFN_CF}" ] ; then
ARBEITSVERZEICHNIS="$(dirname ${0})"
echo "
${ARBEITSVERZEICHNIS}/LB_Modus.sh Start
${ARBEITSVERZEICHNIS}/LB_Modus.sh Stop
${ARBEITSVERZEICHNIS}/LB_Modus.sh Check
"
exit 1
fi
#==============================================================================#
### Funktionen
#------------------------------------------------------------------------------#
ip_out()
{
if [ -z "$(echo "${1}" | grep -E '[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*')" ] ; then
host ${1} | awk '{print $NF}'
else
echo ${1}
fi
}
#------------------------------------------------------------------------------#
check_now()
{
cat "${1}" | while read ZEILE
do
#----------------------------------------------------------------------#
#IFNAME="$(echo "${ZEILE}" | grep -Ev '^$' | awk -F'|' '{print $1}' | head -n1)"
VIPADR="$(echo "${ZEILE}" | grep -Ev '^$' | awk -F'|' '{print $2}' | head -n1)"
unset BLOCK
BLOCK="$(echo "${ZEILE}" | tr -s '|' '\n')"
VIRTUAL="$(echo "${BLOCK}" | grep -F 'virtual=' | sed 's/virtual=//;s/:[0-9]*//' | awk '{print $1}')"
### hier wird (wegen der Einfachheit) der Port von "virtual" auch fuer "real" verwendet
TPORT="$(echo "${BLOCK}" | grep -F 'virtual=' | awk -F':' '{print $NF}' | awk '{print $1}')"
ALLEREALIPS="$(echo "${BLOCK}" | grep -F 'real=' | sed 's/real=//;s/:[0-9]*//' | awk '{print $1}')"
#FALLBACK="$(echo "${BLOCK}" | grep -F 'fallback=' | sed 's/fallback=//;s/:[0-9]*//' | awk '{print $1}')"
FALLBACK="$(echo "${BLOCK}" | grep -F 'fallback=' | sed 's/fallback=//;' | awk '{print $1}')"
#SCHEDULER="$(echo "${BLOCK}" | grep -F 'scheduler=' | sed 's/scheduler=//' | awk '{print $1}')"
SERVICE="$(echo "${BLOCK}" | grep -F 'service=' | sed 's/service=//;s/["]//g' | awk '{print $1}')"
REQUEST="$(echo "${BLOCK}" | grep -F 'request=' | sed 's/request=//;s/["]//g' | awk '{print $1}')"
RECEIVE="$(echo "${BLOCK}" | grep -F 'receive=' | sed 's/receive=//;s/["]//g' | awk '{print $1}')"
#PERSISTENT="$(echo "${BLOCK}" | grep -F 'persistent=' | sed 's/persistent=//;s/["]//g' | awk '{print $1}')"
#PROTOCOL="$(echo "${BLOCK}" | grep -F 'protocol=' | sed 's/protocol=//;s/["]//g' | awk '{print $1}')"
#----------------------------------------------------------------------#
### hier wird die FallBack-Verbindung wieder entfernt
#echo "FALLBACK='${FALLBACK}'" >> /tmp/Check.log ; sync
if [ -z "${FALLBACK}" ] ; then
FB_AUS=""
else
FBEINTAG="$(echo "${FALLBACK}" | awk -F':' '{print $1}')"
FBADR="$(ip_out ${FBEINTAG})"
FBPORT="$(echo "${FALLBACK}" | awk -F':' '{print $2}')"
FB_EIN="-a -t ${VIPADR}:${TPORT} -r ${FBADR}:${FBPORT} -m
-e -t ${VIPADR}:${TPORT} -r ${FBADR}:${FBPORT} -w 1"
FB_AUS="-e -t ${VIPADR}:${TPORT} -r ${FBADR}:${FBPORT} -w 0
-d -t ${VIPADR}:${TPORT} -r ${FBADR}:${FBPORT}"
fi
#----------------------------------------------------------------------#
(for REAL_IP in ${ALLEREALIPS}
do
TEMP="/tmp/ipvsadm_Check_$(head -c 1000 /dev/urandom | tr -cd '[:alnum:]' | cut -b-12)"
#--------------------------------------------------------------#
### hier wird der FQDN der REAL-Hosts in eine IP umgewandelt bzw. die IP uebernommen
RIPADR="$(echo "${IP_FQDN}" | fgrep "|${REAL_IP}" | awk -F'|' '{print $1}')"
if [ -z "${RIPADR}" ] ; then
RIPADR="${REAL_IP}"
fi
#==============================================================#
### hier wird der IST-Zustand einer LB-Verbindung zum Real-Server ausgelesen
#echo "3: ipvsadm -Ln | fgrep \"${RIPADR}:${TPORT}\"" >> /tmp/Check.log ; sync
#echo "#-> 0: ipvsadm -Ln | fgrep '${RIPADR}:${TPORT}'" >> /tmp/Check.log ; sync
IST_WEIGHT="$(ipvsadm -Lnt ${VIPADR}:${TPORT} | fgrep "${RIPADR}:${TPORT}" | awk '/Route/{sub(".*Route","");print $1}' | head -n 1)"
if [ -z "${IST_WEIGHT}" ] ; then
IST_WEIGHT="$(ipvsadm -Ln | fgrep "${RIPADR}:${TPORT}" | awk '/Masq/{sub(".*Masq","");print $1}' | head -n 1)"
if [ "${IST_WEIGHT}" = "1" ] ; then
IST_WEIGHT="1"
else
IST_WEIGHT="0"
fi
fi
if [ -n "${IST_WEIGHT}" ] ; then
#echo "5: RIPADR:TPORT='${RIPADR}:${TPORT}'" >> /tmp/Check.log ; sync
#------------------------------------------------------#
if [ "smtp" = "${SERVICE}" ] ; then
#
# SMTP
#
#echo "----------------------------------------" >> /tmp/Check.log ; sync
#echo "6: wget ${WGETOPTS} -O ${TEMP} http://${RIPADR}:${TPORT}/${REQUEST}" >> /tmp/Check.log ; sync
wget -q ${WGETOPTS} -O ${TEMP} http://${RIPADR}:${TPORT}/${REQUEST}
BEKOMMEN="$(cat ${TEMP} | awk '/^220 /{print $1}' | head -n1 ; rm -f ${TEMP})"
#echo "BEKOMMEN='${BEKOMMEN}'" >> /tmp/Check.log ; sync
if [ "${BEKOMMEN}" = "220" ] ; then
if [ "${IST_WEIGHT}" = "0" ] ; then
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 1 (Weight 1)" | logger -t LoadBalancer
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 1"
fi
else
if [ "${IST_WEIGHT}" = "1" ] ; then
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 0 (Weight 0)" | logger -t LoadBalancer
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 0"
fi
fi
else
#
# HTTP / HTTPS
#
#echo "----------------------------------------" >> /tmp/Check.log ; sync
#echo "7: wget ${WGETOPTS} -O ${TEMP} ${SERVICE}://${RIPADR}:${TPORT}/${REQUEST}" >> /tmp/Check.log ; sync
VERBUNDEN="$(wget ${WGETOPTS} -O ${TEMP} ${SERVICE}://${RIPADR}:${TPORT}/${REQUEST} 2>&1 | awk '/connected|verbunden/{print $NF}')"
#echo "8: VERBUNDEN='${VERBUNDEN}'" >> /tmp/Check.log ; sync
BEKOMMEN="$(cat ${TEMP} | grep -Ev '^$' | sed 's/^[ \t]//g;s/[ \t]$//g' ; rm -f ${TEMP})"
#echo "9: BEKOMMEN='${BEKOMMEN}' | RECEIVE='${RECEIVE}'" >> /tmp/Check.log ; sync
if [ "${VERBUNDEN}" = "connected." -o "${VERBUNDEN}" = "verbunden." ] ; then
#echo "- ipvsadm: 1" >> /tmp/Check.log ; sync
if [ -z "${RECEIVE}" ] ; then
#echo "- ipvsadm: 2" >> /tmp/Check.log ; sync
if [ "${IST_WEIGHT}" = "0" ] ; then
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 1 (Weight 1)" | logger -t LoadBalancer
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 1"
fi
else
#echo "- ipvsadm: 4" >> /tmp/Check.log ; sync
if [ "${RECEIVE}" = "${BEKOMMEN}" ] ; then
#echo "- ipvsadm: 05" >> /tmp/Check.log ; sync
if [ "${IST_WEIGHT}" = "0" ] ; then
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 1 (Weight 1)" | logger -t LoadBalancer
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 1"
fi
else
#echo "- ipvsadm: 07" >> /tmp/Check.log ; sync
if [ "${IST_WEIGHT}" = "1" ] ; then
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 0 (Weight 0)" | logger -t LoadBalancer
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 0"
fi
fi
fi
else
if [ "${IST_WEIGHT}" = "1" ] ; then
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 0 (Weight 0)" | logger -t LoadBalancer
echo "-e -t ${VIPADR}:${TPORT} -r ${RIPADR}:${TPORT} -w 0"
fi
fi
fi
fi
#==============================================================#
### FallBack
if [ -n "${FALLBACK}" ] ; then
IPVSADM_LNT="$(ipvsadm -Lnt ${VIPADR}:${TPORT} | fgrep Route)"
ROUTE_SUM="$(echo "${IPVSADM_LNT}" | sed 's/.*Route//' | awk '{z=$1;s+=z}END{print s}')"
ROUTE_CL="$(echo "${IPVSADM_LNT}" | grep -Fv "> ${FBADR}:" | sed 's/.*Route//' | awk '{z=$1;s+=z}END{print s}')"
ROUTE_FB="$(echo "${IPVSADM_LNT}" | grep -F "> ${FBADR}:")"
if [ "${ROUTE_CL}" -eq "0" ] ; then
if [ -z "${ROUTE_FB}" ] ; then
echo "Added fallback server: ${FBADR}:${FBPORT}" | logger -t LoadBalancer
echo "${FB_EIN}"
fi
else
if [ -n "${ROUTE_FB}" ] ; then
echo "Deleted fallback server: ${FBADR}:${FBPORT}" | logger -t LoadBalancer
echo "${FB_AUS}"
fi
fi
fi
done) | ipvsadm -R #2>/dev/null
done
rm -f ${1}
### wenn Schluss ist, dann muss auch Schluss sein
if [ "${STARTZEIT}" != "$(cat ${RUN} 2>/dev/null)" ]
then
echo "Ende von ${STARTZEIT}"
exit 0
fi
}
#==============================================================================#
### Run
###
### Bearbeitung je Cluster
### mit mehreren Prozessen
### maximale Anzahl der Prozesse = ${PROZESSE}
###
echo "${LDIRECTORD_IFN_CF}" | nl | while read NR CLUSTER
do
#----------------------------------------------------------------------#
### es duerfen nur max. soviele Prozesse laufen,
### wie CPU-Kerne im System stecken
ANZAHL_LAUFEN="$(ps alx | fgrep -v grep | fgrep "/bin/bash /root/bin/LB_Check.sh" | wc -l)"
#echo "ANZAHL_LAUFEN=${ANZAHL_LAUFEN}"
while (( ${ANZAHL_LAUFEN} >= ${PROZESSE} ))
do
sleep 0.1
ANZAHL_LAUFEN="$(ps alx | fgrep -v grep | fgrep "/bin/bash /root/bin/LB_Check.sh" | wc -l)"
#echo "ANZAHL_LAUFEN=${ANZAHL_LAUFEN}"
done
#----------------------------------------------------------------------#
### wenn Schluss ist, dann muss auch Schluss sein
while [ "${STARTZEIT}" != "$(cat ${RUN} 2>/dev/null)" ]
do
exit 0
done
#----------------------------------------------------------------------#
### Start
DATENDATEI="/tmp/ipvsadm_Cluster_Check_${NR}"
echo "${CLUSTER}" > ${DATENDATEI}
( check_now ${DATENDATEI} ) &
done
==== /root/bin/LB_Dienst.sh ====
#!/bin/bash
#
# Hintergrunddienst zur Überwachung
#
# dieses Skript startet/stoppt Verbindungsüberwachung
#
#==============================================================================#
VERSION="v2015060900"
#------------------------------------------------------------------------------#
### damit auch alle Programme gefunden werden
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ARBEITSVERZEICHNIS="$(dirname ${0})"
RUN="/run/LB_Dienst.run"
export RUN
STARTZEIT="$(date +'%s')"
export STARTZEIT
WARTEZEIT="1" # Wartezeit zwischen den Checks in Sekunden
#==============================================================================#
### Funktionen
#------------------------------------------------------------------------------#
lbstop()
{
rm -f ${RUN}
${ARBEITSVERZEICHNIS}/LB_Modus.sh Stop
}
#==============================================================================#
### Start/Stop
case "${1}" in
[Ss][Tt][Aa][Rr][Tt]|[Rr][Ee][Ll][Oo][Aa][Dd])
AKTION=START
shift
;;
[Ss][Tt][Oo][Pp]|[Hh][Aa][Ll][Tt])
lbstop
shift
;;
[Rr][Ee][Ss][Tt][Aa][Rr][Tt])
lbstop
AKTION=START
shift
;;
[Ss][Tt][Aa][Tt][Uu][Ss])
${ARBEITSVERZEICHNIS}/LB_Modus.sh status
shift
;;
*)
echo "${0} [Start|Restart|Reload]"
echo "${0} [Stop|Halt]"
echo "${0} [Status]"
shift
exit 1
;;
esac
#------------------------------------------------------------------------------#
if [ "${AKTION}" = START ] ; then
#======================================================================#
echo "
#----------------------------------------------------------------------#
### checken
${ARBEITSVERZEICHNIS}/LB_Modus.sh Start
echo "${STARTZEIT}" > ${RUN}
while [ \"${STARTZEIT}\" = \"\$(cat ${RUN} 2>/dev/null)\" ]
do
${ARBEITSVERZEICHNIS}/LB_Modus.sh Check
sleep ${WARTEZEIT}
done
#----------------------------------------------------------------------#
### sauber machen
rm -f /tmp/LB_${STARTZEIT}
" > /tmp/LB_Check-Dienst_${STARTZEIT}
chmod 0755 /tmp/LB_Check-Dienst_${STARTZEIT}
screen -dmS LB_Check-Dienst_${STARTZEIT} /tmp/LB_Check-Dienst_${STARTZEIT}
#======================================================================#
fi
#==============================================================================#
==== /etc/init.d/lb_dienst ====
#!/bin/sh
#
### BEGIN INIT INFO
# Short-Description: Monitor virtual services provided by LB-Dienst.sh
# Provides: lb_dienst
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
#
# Author: Yoda
#
# init script for LB-Dienst.sh
#
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
NAME=LB_Dienst.sh
DAEMON="/root/bin/$NAME"
CONFIG=""
test -x $DAEMON || exit 0
test -x /var/lock/subsys || mkdir -p /var/lock/subsys
. /lib/lsb/init-functions
CONFIG_FILE=""
#[ -f "$CONFIG" ] && . "$CONFIG"
#CONFIG_FILE="${CONFIG_FILE:=/etc/ldirectord.cf}"
test -f ${CONFIG_FILE}
RC=$?
if [ $RC -ne 0 ] ; then
log_warning_msg "No configuration file found, doing nothing."
exit 0
fi
case "$1" in
start|stop|restart|reload|halt|status)
log_daemon_msg "Running $NAME" "$1"
##exec "$DAEMON" "$CONFIG_FILE" $1
exec "$DAEMON" $1
RC=$?
log_end_msg $RC
exit $RC
;;
*)
echo "Usage: /etc/init.d/$NAME" \
"{start|restart|reload|stop|halt|status}" >&2
exit 1
;;
esac
den neuen Dienst bootfest machen:
# chmod 0755 /etc/init.d/lb_dienst
# update-rc.d lb_dienst defaults
Adding system startup for /etc/init.d/lb_dienst ...
/etc/rc0.d/K20lb_dienst -> ../init.d/lb_dienst
/etc/rc1.d/K20lb_dienst -> ../init.d/lb_dienst
/etc/rc6.d/K20lb_dienst -> ../init.d/lb_dienst
/etc/rc2.d/S20lb_dienst -> ../init.d/lb_dienst
/etc/rc3.d/S20lb_dienst -> ../init.d/lb_dienst
/etc/rc4.d/S20lb_dienst -> ../init.d/lb_dienst
/etc/rc5.d/S20lb_dienst -> ../init.d/lb_dienst
==== /root/bin/watch.sh ====
#!/bin/bash
watch 'uptime; md5sum /etc/ldirectord.cf* ; echo ; ps -ef | fgrep -v "grep" | egrep "ldirectord /etc/ldirectord.cf [sr][te][asl][rto][ta]"; ipvsadm -ln | fgrep "Route 1" | wc -l; echo; fgrep "fallback" /var/log/syslog | tail -n3; ipvsadm -l | fgrep "Route 0";'
==== /etc/ldirectord.cf ====
checktimeout=3
checkinterval=10
autoreload=yes
logfile="local0"
quiescent=yes
#INTERFACENAME:domain
virtual=www.domain.de:80
real=ttshop01.public:80 gate
real=ttshop02.public:80 gate
fallback=fallback01.oqrm.public:80 gate
service=http
request="ldirector.php"
receive="www.domain.de"
scheduler=wlc
persistent=30
protocol=tcp
checktype=negotiate
virtual=www.domain.de:443
real=ttshop01.public:443 gate
real=ttshop02.public:443 gate
fallback=fallback01.public:443 gate
service=https
request="ldirector.php"
receive="www.domain.de"
scheduler=wlc
persistent=30
protocol=tcp
checktype=negotiate
Die Namensauflösung muss funktionieren, sonst funktioniert garnichts!
> host www.domain.de
www.domain.de has address 203.202.201.200
wenn der LB gestartet ist, dann ist die letzte Zeile hier zu sehen (mit dem INTERFACENAME -> ''domain''):
> ip a show dev lo
1: lo: mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet 203.202.201.200/32 scope global lo:domain
dieser Test, stellt sicher, dass das System kein ro-Dateisystem hat, was bei einem Fehlerhaften System auftreten kann:
www.domain.de