Scripts d'Automatisation pour la Gestion des Services sous Linux
Dans le cadre des opérations système quotidiennes, l'utilisation de scripts Shell combinant des fonctions, des structures conditionnelles et des instructions case permet d'automatiser le déploiemant et la gestion des services middleware. Nous présentons plusieurs scripts essentiels pour l'administration système.
一、Script de Gestion du Service Tomcat
Pour les environnemenst comportant plusieurs instances Tomcat, il est recommandé de créer des scripts dédiés dans le répertoire /etc/init.d/, chacun ciblant un port spécifique. L'exemple suivant concerne un script pour Tomcat sur le port 8080 :
#!/bin/bash
#chkconfig: 345 99 10
#description: Demarrage automatique de Tomcat
# /etc/init.d/tomcatd
# Tomcat auto-start
# Source function library.
source /etc/init.d/functions
RETVAL=0
nom_instance=tomcat_8080
# Verification de JAVA_HOME
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/
export CATALINA_HOME=/usr/local/${nom_instance}
# Rechargement de la configuration systemd
systemctl daemon-reload
demarrer()
{
if [ -f ${CATALINA_HOME}/bin/startup.sh ];
then
echo $"Demarrage de Tomcat"
if [ root = `whoami` ];
then
${CATALINA_HOME}/bin/startup.sh
else
su - root -c "${CATALINA_HOME}/bin/startup.sh"
fi
RETVAL=$?
echo " OK"
return ${RETVAL}
fi
}
arreter()
{
if [ -f ${CATALINA_HOME}/bin/shutdown.sh ];
then
echo $"Arret de Tomcat"
${CATALINA_HOME}/bin/shutdown.sh
RETVAL=$?
sleep 1
ps -ef|grep ${nom_instance}|egrep -v 'grep|init' | grep ${CATALINA_HOME}|awk '{print $2}'|xargs kill -9
mv ${CATALINA_HOME}/logs/catalina.out ${CATALINA_HOME}/logs/catalina.out_`date '+%Y%m%d_%H_%M_%S'`
find ${CATALINA_HOME}/logs/ -mtime +10 -exec rm -rf {} \;
echo " OK"
return ${RETVAL}
fi
}
etat()
{
port=$(echo ${nom_instance}|awk -F _ '{print$2}')
pid=$(lsof -i:$port|awk 'NR==2{print$2}')
if [ -z $pid ]
then
echo -e "\033[40;31m${nom_instance} est arrete\033[0m"
else
echo ${nom_instance} est en cours d'execution
fi
}
cas "$1" in
demarrer)
demarrer
;;
arreter)
arreter
;;
redemarrer)
echo $"Redemarrage de Tomcat"
arreter
sleep 1
demarrer
;;
etat)
etat
;;
*)
echo $"Utilisation: $0 {demarrer|arreter|redemarrer|etat}"
exit 1
;;
esac
exit ${RETVAL}
Utilisation du script :
[root@localhost ~]# chmod 755 /etc/init.d/tomcat_8080
[root@localhost ~]# /etc/init.d/tomcat_8080 redemarrer
Redemarrage de tomcat_8080 (via systemctl): [ OK ]
[root@localhost ~]# /etc/init.d/tomcat_8080 etat
tomcat_8080 est en cours d'execution
[root@localhost ~]# /etc/init.d/tomcat_8080 arreter
Arret de tomcat_8080 (via systemctl): [ OK ]
二、Script de Déploiement d'un Cluster Zookeeper
Ce script permet un déploiement automatisé et reconfigurable d'un cluster Zookeeper :
#!/bin/bash
source /etc/profile
java -version
if [ "$?" -ne 0 ]; then
echo "JDK non installe, merci d installer JDK"
exit 1
fi
while getopts "a:b:n:l:c:f:m:h" opts
do
case $opts in
a)
#APP_NAME: code du projet
APP_NAME=$OPTARG
;;
b)
#MODULE_NAME: nom du module
MODULE_NAME=$OPTARG
;;
n)
#ZK_SRVNUM: nombre de serveurs Zookeeper
ZK_SRVNUM=$OPTARG
;;
l)
#ZK_IPLIST: liste des adresses IP des serveurs
ZK_IPLIST=$OPTARG
;;
c)
#ZKCLIENT_PORT: port d acces client
ZKCLIENT_PORT=$OPTARG
;;
f)
#ZKLEADER_PORT: port de communicationFollower-Leader
ZKLEADER_PORT=$OPTARG
;;
m)
#ZKCOM_PORT: port d election du leader
ZKCOM_PORT=$OPTARG
;;
h)
echo -e "OPTIONS:\n-a: code du projet (obligatoire)\n-b: nom du module (optionnel, vide par defaut)\n-n: nombre de serveurs (optionnel, 3 par defaut)"
echo -e "-l: liste des adresses IP (obligatoire, separes par des virgules)"
echo -e "-c: port client (optionnel, 2181 par defaut)"
echo -e "-f: port de communication (optionnel, 2888 par defaut)"
echo -e "-m: port d election (optionnel, 3888 par defaut)"
exit 1
;;
?)
echo "options manquantes"
exit 1
;;
esac
done
# Valeurs par defaut
ZK_SRVNUM=${ZK_SRVNUM:-3}
ZKCLIENT_PORT=${ZKCLIENT_PORT:-2181}
ZKLEADER_PORT=${ZKLEADER_PORT:-2888}
ZKCOM_PORT=${ZKCOM_PORT:-3888}
# Variables communes
ZKSAVDIR="/usr/local/src/zookeeper"
ZKNAME="zookeeper-3.4.8"
# Validation des parametres
if [ -z ${APP_NAME} ]||[ -z ${ZK_IPLIST} ];then
echo "Parametres manquants"
exit 1
elif [ ${ZK_SRVNUM} -ne 1 ]&&[ ${ZK_SRVNUM} -ne 3 ]&&[ ${ZK_SRVNUM} -ne 5 ];then
echo "Nombre de serveurs incorrect"
exit 1
fi
IPLIST_NUM=`echo ${ZK_IPLIST}|awk -F"," '{print NF}'`
if [ ${ZK_SRVNUM} -ne ${IPLIST_NUM} ];then
echo "Incompatibilite entre la liste IP et le nombre de serveurs"
exit 1
fi
APP_NAME=`echo ${APP_NAME} | tr '[A-Z]' '[a-z]'`
# Verification de la correspondance ports/IP
CPORT_NUM=`echo ${ZKCLIENT_PORT}|awk -F"," '{print NF}'`
LPORT_NUM=`echo ${ZKLEADER_PORT}|awk -F"," '{print NF}'`
EPORT_NUM=`echo ${ZKCOM_PORT}|awk -F"," '{print NF}'`
if [ ${CPORT_NUM} -gt 1 ];then
if [ ${IPLIST_NUM} -ne ${CPORT_NUM} ]||[ ${IPLIST_NUM} -ne ${LPORT_NUM} ]||[ ${IPLIST_NUM} -ne ${EPORT_NUM} ];then
echo "Incompatibilite entre les listes de ports et d IPs"
exit 1
fi
rm -f /home/workapp/zkinfo.cfg
for ((i=1;i<=${ZK_SRVNUM};i++)); do
eval IP_$i='`echo ${ZK_IPLIST}|awk -F, "{ print $"$i" }"`'
eval PORT_$i='`echo ${ZKCLIENT_PORT}|awk -F, "{ print $"$i" }"`'
eval LPORT_$i='`echo ${ZKLEADER_PORT}|awk -F, "{ print $"$i" }"`'
eval EPORT_$i='`echo ${ZKCOM_PORT}|awk -F, "{ print $"$i" }"`'
eval PORTTMP=\$PORT_$i
[ -z ${MODULE_NAME} ]&&eval ZKHOME="/opt/${APP_NAME}/zookeeper_\$PORT_$i"||eval ZKHOME="/opt/${APP_NAME}/zookeeper_${MODULE_NAME}_\$PORT_$i"
[ -z ${MODULE_NAME} ]&&eval DATA_LOGDIR="/var/log/${APP_NAME}/zookeeper_\$PORT_$i"||eval DATA_LOGDIR="/var/log/${APP_NAME}/zookeeper_${MODULE_NAME}_\$PORT_$i"
DATA_DIR="${ZKHOME}/data"
eval echo "$i,\$IP_$i,\$PORT_$i,\$LPORT_$i,\$EPORT_$i,${ZKHOME},${DATA_LOGDIR},${DATA_DIR}">>/home/workapp/zkinfo.cfg
done
else
[ -z ${MODULE_NAME} ]&&ZKHOME="/opt/${APP_NAME}/zookeeper"||ZKHOME="/opt/${APP_NAME}/zookeeper_${MODULE_NAME}"
[ -z ${MODULE_NAME} ]&&DATA_LOGDIR="/var/log/${APP_NAME}/zookeeper"||DATA_LOGDIR="/var/log/${APP_NAME}/zookeeper_${MODULE_NAME}"
DATA_DIR="${ZKHOME}/data"
fi
# Journal d installation
INSTALL_LOG="/home/workapp/zookeeperinstall.log"
echo "APP_NAME is ${APP_NAME}"|tee -a ${INSTALL_LOG}
echo "ZK_Server_num is ${ZK_SRVNUM}"|tee -a ${INSTALL_LOG}
echo "ZK_Server IP is ${ZK_IPLIST}"|tee -a ${INSTALL_LOG}
# Recuperation de l IP locale
HOST_IP=`ip a|grep global|awk '{print $2}'|awk -F"/" '{print $1}'`
echo "Local IP is ${HOST_IP}"|tee -a ${INSTALL_LOG}
# Verification MD5
md5Now=`md5sum ${ZKSAVDIR}/${ZKNAME}.tar.gz|awk '{print $1}'`
md5Save=`cat ${ZKSAVDIR}/${ZKNAME}.tar.gz.md5`
if [ "${md5Now}" != "${md5Save}" ];then
echo "Echec de la verification MD5!"|tee -a ${INSTALL_LOG}
exit 1
else
echo "Verification MD5 reussie!"|tee -a ${INSTALL_LOG}
fi
# Fonction d installation
function installer_zk {
echo "=================`date '+%Y%m%d %H:%M:%S'` Debut installation ZooKeeper....==============="|tee -a ${INSTALL_LOG}
if [ ! -e /opt/${APP_NAME}/ ]; then
mkdir -p /opt/${APP_NAME}
fi
tar -xzf ${ZKSAVDIR}/${ZKNAME}.tar.gz -C /opt/${APP_NAME}/
mv /opt/${APP_NAME}/${ZKNAME} ${ZKHOME}
mkdir -p ${DATA_DIR}
mkdir -p ${DATA_LOGDIR}
cp ${ZKHOME}/conf/zoo_sample.cfg ${ZKHOME}/conf/zoo.cfg
# Personnalisation de la configuration
sed -i "s/clientPort=2181/clientPort=${ZKCLIENT_PORT}/g" ${ZKHOME}/conf/zoo.cfg
sed -i "s#dataDir=/tmp/zookeeper#dataDir=${DATA_DIR}#g" ${ZKHOME}/conf/zoo.cfg
sed -i "/dataLogDir/s/^/#/" ${ZKHOME}/conf/zoo.cfg
echo "dataLogDir=${DATA_LOGDIR}" >>${ZKHOME}/conf/zoo.cfg
sed -i "s#/var/log/zookeeper#${DATA_LOGDIR}#g" ${ZKHOME}/conf/zookeeper-env.sh
sed -i "s#/var/log/zookeeper#${DATA_LOGDIR}#g" ${ZKHOME}/conf/java.env
# Configuration du cluster
if [ ${ZK_SRVNUM} -eq 3 ]||[ ${ZK_SRVNUM} -eq 5 ];then
if [ ${CPORT_NUM} -eq 1 ];then
for ((i=1;i<=${ZK_SRVNUM};i++));do
eval IP_$i='`echo ${ZK_IPLIST}|awk -F, "{ print $"$i" }"`'
eval IPTMP=\$IP_$i
eval echo "server.${i}=\$IP_$i:${ZKLEADER_PORT}:${ZKCOM_PORT}">>${ZKHOME}/conf/zoo.cfg
if [ "$HOST_IP" == "$IPTMP" ];then
ZK_ID=${i}
else
continue
fi
done
else
ZK_ID=${NUM}
while read ZK_INFO;do
echo ${ZK_INFO}|awk -F, '{print "server."$1"="$2":"$4":"$5}'>>${ZKHOME}/conf/zoo.cfg
done</home/workapp/zkinfo.cfg
fi
echo "${ZK_ID}" >${DATA_DIR}/myid
echo "zookeeper ID is ${ZK_ID}"|tee -a ${INSTALL_LOG}
fi
chown -R workapp:workapp ${ZKHOME}
chown -R workapp:workapp ${DATA_LOGDIR}
}
function verifier_installation {
retval=$?
if [ $retval -eq 0 ];then
echo "`date '+%Y%m%d %H:%M:%S'` installation zookeeper REUSSIE!"|tee -a ${INSTALL_LOG}
else
echo "`date '+%Y%m%d %H:%M:%S'` installation zookeeper ECHOUEE!"|tee -a ${INSTALL_LOG}
fi
}
function demarrer_verifier {
su - workapp -c "sh ${ZKHOME}/bin/zkServer.sh start"
sleep 10
su - workapp -c "sh ${ZKHOME}/bin/zkServer.sh status"
netstat -anp|grep ${ZKCLIENT_PORT}
}
# Execution selon le mode de configuration
if [ ${CPORT_NUM} -eq 1 ];then
installer_zk
verifier_installation
demarrer_verifier
else
while read ZK_INFO;do
NUM=`echo ${ZK_INFO}|awk -F, '{print $1}'`
IP=`echo ${ZK_INFO}|awk -F, '{print $2}'`
ZKCLIENT_PORT=`echo ${ZK_INFO}|awk -F, '{print $3}'`
ZKHOME=`echo ${ZK_INFO}|awk -F, '{print $6}'`
DATA_LOGDIR=`echo ${ZK_INFO}|awk -F, '{print $7}'`
DATA_DIR=`echo ${ZK_INFO}|awk -F, '{print $8}'`
if [ "$IP" == "$HOST_IP" ];then
installer_zk
verifier_installation
demarrer_verifier
else
continue
fi
done</home/workapp/zkinfo.cfg
fi
rm -f /home/workapp/zkinfo.cfg
三、Script d'Installation Automatisee Multi-Services
Ce script propose un menu interactif pour le deploiement de differents services :
#!/bin/bash
source /etc/init.d/functions
BASE_DIR=/usr/local/src
read -p "Veuillez saisir un chiffre entre 1 et 8:" NUM
expr $NUM + 1 >/dev/null 2>&1
if [ "$?" -ne 0 ]
then
echo "Veuillez saisir {1|2|3|4|5|6|7|8}"
exit 1
fi
function installer_nginx (){
echo "Debut de l'installation de Nginx. Veuillez patienter...."
yum install -y gcc gcc-c++ pcre-devel zlib-devel openssl-devel >/dev/null 2>&1
cd $BASE_DIR
wget http://nginx.org/download/nginx-1.12.2.tar.gz >/dev/null 2>&1
useradd -M -s /sbin/nologin nginx
tar -zvxf nginx-1.12.2.tar.gz >/dev/null 2>&1
cd $BASE_DIR/nginx-1.12.2/
./configure --prefix=/usr/local/nginx --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre --with-http_ssl_module --with-http_gzip_static_module --user=nginx --group=nginx >/dev/null 2>&1
if [ "$?" -eq 0 ];then
make && make install >/dev/null 2>&1
fi
if [ -f /usr/local/nginx/sbin/nginx ];then
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin
/usr/local/nginx/sbin/nginx
echo "Installation de Nginx terminee avec succes!"
fi
}
function installer_apache (){
echo "Debut de l'installation d'Apache. Veuillez patienter...."
yum install httpd -y >/dev/null 2>&1
if [ "$?" -eq 0 ]
then
echo "Installation d'Apache terminee avec succes!"
else
echo "Echec de l'installation d'Apache."
fi
}
function installer_mysql (){
echo "Debut de l'installation de MySQL. Veuillez patienter...."
rpm -e $(/bin/rpm -qa | grep mysql|xargs) --nodeps >/dev/null 2>&1
rpm -e $(/bin/rpm -qa | grep mariadb|xargs) --nodeps >/dev/null 2>&1
yum -y install make gcc-c++ cmake bison-devel ncurses-devel >/dev/null 2>&1
mkdir -p /usr/local/boost && cd /usr/local/boost
wget http://www.sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz >/dev/null 2>&1
tar -zvxf boost_1_59_0.tar.gz >/dev/null 2>&1
/usr/sbin/groupadd mysql
/usr/sbin/useradd -g mysql mysql -M -s /sbin/nologin
mkdir -p /data/mysql/data
cd $BASE_DIR
wget -c http://ftp.ntu.edu.tw/MySQL/Downloads/MySQL-5.7/mysql-5.7.28.tar.gz >/dev/null 2>&1
tar -zxvf mysql-5.7.28.tar.gz >/dev/null 2>&1
cd mysql-5.7.28/
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql/data -DSYSCONFDIR=/usr/local/mysql -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DWITH_READLINE=1 -DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DEXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_BOOST=/usr/local/boost >/dev/null 2>&1
if [ "$?" -eq 0 ];then
make && make install >/dev/null 2>&1
fi
chown -R mysql:mysql /usr/local/mysql
chown -R mysql:mysql /data/mysql
/usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/mysql/data --user=mysql --initialize >/dev/null 2>&1
cat > /usr/local/mysql/my.cnf << EOF
[client]
port = 3306
socket = /usr/local/mysql/var/mysql.sock
[mysqld]
port = 3306
socket = /usr/local/mysql/var/mysql.sock
basedir = /usr/local/mysql/
datadir = /data/mysql/data
pid-file = /data/mysql/data/mysql.pid
user = mysql
bind-address = 0.0.0.0
server-id = 1
sync_binlog=1
log_bin = mysql-bin
skip-name-resolve
max_connections = 3000
table_open_cache = 512
max_allowed_packet = 16M
default_storage_engine = InnoDB
innodb_file_per_table = 1
innodb_buffer_pool_size = 40960M
log_error = /data/mysql/data/mysql-error.log
slow_query_log = 1
long_query_time = 1
slow_query_log_file = /data/mysql/data/mysql-slow.log
EOF
cd /usr/local/mysql && mkdir var
chown -R mysql.mysql var
cp support-files/mysql.server /etc/init.d/mysql
chmod 755 /etc/init.d/mysql
chkconfig mysql on
service mysql start >/dev/null 2>&1
echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
source /etc/profile
mkdir -p /var/lib/mysql
ln -s /usr/local/mysql/var/mysql.sock /var/lib/mysql/mysql.sock
chown -R mysql:mysql /var/lib/mysql
sed -i '/\[mysqld]/a\skip-grant-tables' /usr/local/mysql/my.cnf
service mysql restart >/dev/null 2>&1
/usr/local/mysql/bin/mysql -p" " -e "update mysql.user set authentication_string=password('mysql@123') where user='root';" -e "flush privileges;"
sed -i '/skip-grant-tables/d' /usr/local/mysql/my.cnf
chown -R mysql:mysql /usr/local/mysql
chown -R mysql:mysql /data/mysql
service mysql restart >/dev/null 2>&1
if [ "$?" -eq 0 ];then
echo "Installation de MySQL terminee avec succes! Mot de passe initial: mysql@123"
fi
}
cas $NUM in
1)
installer_nginx
;;
2)
installer_apache
;;
3)
installer_mysql
;;
esac
Remarques importantes
Pour le script d'installation automatisee, les paquets d'installation doivent etre telecharges prealablement dans le repertoire specifie par ${BASE_DIR} afin d'optimiser l'execution du script. Il est egalement possible d'adapter les sources de telechargement selon votre environnement reseau.