#! /bin/sh
#########################################################################
# 守护进程操作说明:
# 1.启动命令:nohup sh watch_server_v3.sh >/dev/null 2>&1 &
# 2.需将 watch_server_v3.sh 放在 [最大盘]/ICC/dahua/fire/server_keeper 下。
# 3.务必确保有且仅有当前守护进程正在运行。
# 4.如需新增服务,请在 serverList.sh 中按照相关说明添加相关服务。
# 5.启动守护进程后,务必确认当前路径下无 ERROR.log 产生。如有,请根
# 据提示解决相应问题。
#########################################################################
# 更新日志 2020-7-15 23:39:52 刘迎光
# 1.进一步降低使用和维护守护进程的难度。
# 2.优化脚本执行逻辑。新增服务后无需重启,即可被守护。
# 3.增加对守护脚本存放路径的强校验
#########################################################################
# TODO:定时清理日志(一天一次)
#########################################################################
# 守护进程的文件名(不含后缀)
watchPath=$(pwd)
watchFileName=${0} # 文件名(含后缀)
watchFileName=${watchFileName%.*} # 文件名(不含后缀)
watchFilePath=${watchPath}/${watchFileName}.sh
echo "守护进程的文件名(不含后缀):[[ ${watchFileName} ]]"
# 新服务基础路径、日志文件名称
basePath=$(
cd ..
pwd
)
time=$(date +%Y-%m-%d %H:%M:%S)
# 输出日志信息
# args-1:日志级别(ERROR, WARN, INFO)
# args-2:输出内容
function log_out() {
# 当前执行操作的文件
cur_file=$0
# 日志内容
logContent=$1
# 日志级别
LEVEL_CODE=$2
# 将字符串转成大写,再进行字符串比较
LEVEL_CODE=$(echo ${LEVEL_CODE} | tr [a-z] [A-Z])
logTime=$(date +'%Y-%m-%d %H:%M:%S')
# LEVEL_CODE 为空,则默认日志等级为 INFO
if [[ ! -n "${LEVEL_CODE}" ]]; then
LEVEL="INFO"
elif [[ "${LEVEL_CODE}" == D* ]]; then
LEVEL="DEBUG"
elif [[ "${LEVEL_CODE}" == I* ]]; then
LEVEL="INFO"
elif [[ "${LEVEL_CODE}" == W* ]]; then
LEVEL="WARN"
elif [[ "${LEVEL_CODE}" == E* ]]; then
LEVEL="ERROR"
else
LEVEL="INFO"
fi
echo "${logTime}:[$cur_file][${LEVEL}] ${logContent}"
echo "${logTime}:[$cur_file][${LEVEL}] ${logContent}" >>${LEVEL}.log
}
# 调用示例
# log_out "ip参数:$IP" i
# 校验文件位置是否正确,如果错误,则记录到日志中,并返回错误信息
BASE_PATH=/ICC/dahua/fire
if [[ ! ${basePath} =~ ${BASE_PATH} ]]; then
log_out "守护进程存放位置有误,执行失败!!!" E
exit
fi
### # 杀死守护进程
### function killWatch(){
### numServer=$(ps -ef | grep watch | grep -v "grep" | grep -v "watchdog")
### if [[ ${numServer} -gt 1 ]];then
### kill -9 $( ps -ef | grep watch | grep -v "grep" | grep -v "watchdog" | awk -F ' ' '{print $2}' )
### fi
###
### }
# 添加守护进程到开机启动中(服务器重启即会执行)
FIND_S="source /etc/profile"
FIND_STR="nohup sh ${watchFileName}.sh >/dev/null 2>&1 &"
# 开机启动项文件位置
FIND_FILE="/etc/rc.d/rc.local"
# 移除开机启动项中的相关内容
sed -i '/\/etc\/profile/d' $FIND_FILE
sed -i '/watch_server/d' $FIND_FILE
sed -i '/server_keeper/d' $FIND_FILE
sed -i '/server/d' $FIND_FILE
if [ $(grep -c "$FIND_S" $FIND_FILE) -eq '0' ]; then
chmod 777 /etc/rc.d/rc.local
echo "source /etc/profile" >>/etc/rc.d/rc.local
sleep 2
fi
if [ $(grep -c "watch_server" $FIND_FILE) -eq '0' ]; then
chmod 777 /etc/rc.d/rc.local
echo "cd ${watchPath}" >>/etc/rc.d/rc.local
sleep 2
chmod 777 /etc/rc.d/rc.local
echo "nohup sh ${watchFileName}.sh >/dev/null 2>&1 &" >>/etc/rc.d/rc.local
sleep 2
fi
JAVA_OPTS="-Xss512k -XX:MaxMetaspaceSize=1024M -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=75 -XX:ParallelGCThreads=4 -XX:+HeapDumpOnOutOfMemoryError"
# 检验服务是否启动的间隔时间
sleepTime=10
###########################################################
function start_kafka_zookeeper() {
serverName=zookeeper
path=${basePath}/${serverName}
zookeeper_start_file=${path}/bin/zookeeper-server-start.sh
zookeeper_stop_file=${path}/bin/zookeeper-server-stop.sh
zookeeper_cfg_file=${path}/config/zookeeper.properties
#判断对应 Kafka zookeeper 进程是否已经启动
if $(ps -ef | grep -v "grep" | grep ${path} | grep -q "zookeeper.properties"); then
log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
return
fi
log_out "启动 ${serverName} 开始,... "
cd ${path}
nohup bin/zookeeper-server-start.sh config/zookeeper.properties >/dev/null 2>&1 &
log_out "启动 zookeeper 完成 ... "
cd -
sleep 10
}
function start_kafka() {
serverName=kafka
path=${basePath}/${serverName}
#判断对应 kafka Server 进程是否已经启动
if $(ps -ef | grep ${path} | grep -q "kafka.Kafka"); then
log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
return
fi
cd ${path}
nohup bin/kafka-server-start.sh config/server.properties >/dev/null 2>&1 &
cd -
}
# 启动 zookeeper 和 kafka
function start_zookeeperAndKafka() {
serverName=kafka
path=${basePath}/${serverName}
if [ ! -d "${path}" ]; then
log_out "[[ ${serverName} ]] 不存在(或者 文件夹名称与标准服务名不一致),跳过..."
else
kafka_port=$(cat ${path}/config/server.properties | grep "^listeners" | awk -F ':' '{print $3}')
if [[ ! -n "${kafka_port}" ]]; then
log_out "未找到 [[ ${serverName} ]] 的端口 kafka_port !!!请检查 server.properties 中 是否包含 listeners " E
return
else
# log_out "kafka_port:${kafka_port}"
start_kafka_zookeeper
start_kafka
fi
fi
}
# 启动 redis
function start_redis() {
serverName=redis
path=${basePath}/${serverName}
if [ ! -d "${path}" ]; then
# log_out "没有该服务:[[ ${serverName} ]],无需启动"
log_out "[[ ${serverName} ]] 不存在(或者 文件夹名称与标准服务名不一致),跳过..."
else
redis_file=${path}/redis-server
redis_conf=${path}/redis.conf
#判断对应 redis 进程是否已经启动
if $(ps -ef | grep ${path} | grep -q redis-server); then
log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
return
fi
log_out "[[ ${serverName} ]] 未运行,开始启动... " W
cd ${path}
log_out "${redis_file} ${redis_conf} &"
${redis_file} ${redis_conf} &
echo "[[ ${serverName} ]] 启动完成... "
cd -
fi
}
#mysql添加守护
function start_mysql() {
serverName=mysql
path=${basePath}/${serverName}
if [ ! -d "${path}" ]; then
log_out "没有该服务:[[ mysql ]],无需启动"
else
#判断对应 mysql 进程是否已经启动
mysqlStatus=$(systemctl status mysqld | grep "Active: active")
if [[ ${mysqlStatus} == *active* ]]; then
# if [ -n ${mysqlStatus} ]; then
log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
return
else
log_out "[[ ${serverName} ]] 未运行,开始启动... " W
setenforce 0
sed -i 's/SELINUX=enforcing SELINUX=disabled/g' /etc/selinux/config
if [ -f "${path}/../../../../firecontroldata/mysql/mysql.sock.lock" ]; then
rm -rf ${path}/../../../../firecontroldata/mysql/mysql.sock.lock
fi
systemctl restart mysqld.service
echo "[[ ${serverName} ]] 启动完成... "
fi
fi
}
# 常用函数(启动 war 包服务)
function startWarServer() {
# 服务名称(new)
serverName=$1
serverPath=${basePath}/${serverName}
numServer=$(ps -aux | grep ${serverPath}/bin | grep -v "grep" | wc -l)
if [[ ${numServer} -lt 1 ]]; then
log_out "[[ ${serverName} ]] 未运行,开始启动... " W
cd ${serverPath}
bin/startup.sh
cd -
else
log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
fi
}
# 常用函数(启动 jar 包服务)
function startJarServer() {
# 服务名称(new)
serverName=$1
# jar 包名称
jarName=$2
# 限制内存大小(含单位:G)
limitXmx=$3
serverPath=${basePath}/${serverName}
jarPath=${serverPath}/${jarName}
# 去除单位(:G)
limitSize=${limitXmx%G*}
if [ ! -n "${limitSize}" ]; then
# 默认限制内存大小:1G
limitXmx=1G
elif [[ ${limitSize} -gt 5 ]]; then
log_out "${limitXmx} 过大,请确认是否正确!!!" E
fi
log_out "serverName=${serverName},jarName=${jarName},limitXmx=${limitXmx},serverPath=${serverPath},jarPath=${jarPath}"
numServer=$(ps -aux | grep ${jarPath} | grep -v "grep" | wc -l)
if [[ ${numServer} -lt 1 ]]; then
log_out "[[ ${serverName} ]] 未运行,开始启动... " W
cd ${serverPath}
nohup java -server -Xms512m -Xmx${limitXmx} ${JAVA_OPTS} -XX:HeapDumpPath=/logs/${serverName}.dump -jar ${jarPath} >/dev/null 2>&1 &
cd -
else
log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
fi
}
# 启动服务(war 包和 jar 包服务启动均使用该方法)
function startServer() {
serverName=$1
serverPath=${basePath}/{serverName}
if [ ! -d "${serverPath}" ]; then
log_out "[[ ${serverName} ]] 不存在(或者 文件夹名称与标准服务名不一致),跳过..."
else
FIND_FILE=${basePath}/${serverName}/bin
info="服务名称:[[ ${serverName} ]]"
if [[ -d "${FIND_FILE}" ]]; then
info=${info}",war 包启动"
startWarServer ${serverName}
else
packageName=$2
limitSize=$3
info=${info}",jar 包名称:[[ ${packageName} ]] ,限制内存大小:[[ ${limitSize} ]] "
startJarServer ${serverName} ${packageName} ${limitSize}
echo "${info}"
fi
fi
}
# 查询是否存在 serverList.sh,若不存在则创建,存在则跳过
function mkDir() {
file=$1
if [ -f ${file} ]; then
echo "[[ ${file} ]] 已存在,无需创建"
else
echo "[[ ${file} ]] 文件不存在,开始创建"
# 创建文件
touch ${file}
# 往文件中添加初始化的文件列表
echo "
#! /bin/sh
# 启动守护进程指令:nohup sh ${watchFileName}.sh >/dev/null 2>&1 &
# [注意事项]
# 1.禁止手动启动任何服务,否则可能导致服务启动异常。
# 2.启动守护进程后,务必观察当前文件夹下是否有 ERROR.log 文件产生。如有,务必根据提示修复存在问题。
# 3.新增服务后即被守护,无需重启守护进程。
################ 示例 (始)################
# 添加 war 包服务格式:
# 服务名称 war包名称(选填)
IFCS IFCS.war
# 添加 jar 包服务格式:
# 服务名称 jar包 限制最大内存(单位:G,选填)
DCPS_TCP DCPS.jar 1G
################ 示例 (末)################
ftpServer
ftpserver
ftp
httpServer httpServer.jar 1G
httpserver httpServer.jar 1G
http httpServer.jar 1G
HTTP httpServer.jar 1G
MessageServer MessageServer.jar 2G
FireAppServer FireAppServer.jar 2G
CallServer CallServer.jar 2G
DCPS_UDP DCPS_UDP.jar 1G
# IFCSI IFCSI.war
# IFCSI2.0 IFCSI.jar 2G
# DCPS-HTTP_YD1.0 DCPS-HTTP.jar 1G
# ONENET1.0 DCPS-HTTP.jar 1G
# ONENET1 DCPS-HTTP.jar 1G
# ONENET DCPS-HTTP.jar 1G
# DCPS-HTTP_YD1.1 DCPS-HTTP.jar 1G
# ONENET1.1 DCPS-HTTP.jar 1G
# DCPS-HTTP_DX DCPS-HTTP.jar 1G
# DXIOT DCPS-HTTP.jar 1G
" >${file}
log_out "创建 [[ ${file} ]] 文件结束"
fi
}
# 获取文件大小
function getFileSize() {
file=$1
# 获取文件大小(以 M 为单位)
fileSize=$(du -sb ${file} | awk '{print int($1/1024/1024)}')
echo "${fileSize}"
}
### TODO:清理日志(大小超过某值)
## 定时清理日志
#function cleanFile() {
#
# file=$1
#
# fielSize=$(getFileSize ${file})
# echo "${file} 大小:${fielSize}(M)"
#
# if [[ ${fielSize} -lt 100 ]]; then
# echo "${file} 小于 100M,无需清理"
# return
# else
# echo "${file} 大于 100M,清理"
# fi
#
#}
# 获取并启动服务(列表)
function readAndRunServerList() {
# 需要读取服务列表的文件名称(带文件类型,eg. serverList.sh)
serverListFile=$1
echo "服务列表文件:${serverListFile}"
# 读取文件(过滤掉 注释行、空行)
egrep -v "^\s*#|^\s*$" ${serverListFile} | while read xxx; do
serverName=$(echo ${xxx} | awk -F ' ' '{print $1}')
packageName=$(echo ${xxx} | awk -F ' ' '{print $2}')
limitSize=$(echo ${xxx} | awk -F ' ' '{print $3}')
startServer ${serverName} ${serverName} ${limitSize}
done
}
# 总的调用服务方法
function main() {
while true; do
# 启动 zookeeper 和 kafka
start_zookeeperAndKafka
# 启动 redis
start_redis
# 启动 mysql
start_mysql
# 调用方法(获取 服务列表)
readAndRunServerList serverList.sh
# cleanFile 文件名
echo "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [[ ${sleepTime} ]] 秒后开始下一轮检查 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "
echo "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [[ ${sleepTime} ]] 秒后开始下一轮检查 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "
echo "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [[ ${sleepTime} ]] 秒后开始下一轮检查 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "
sleep ${sleepTime}
done
}
#####################################################
#####################################################
#####################################################
#####################################################
#####################################################
#####################################################
# 创建文件
mkDir serverList.sh
# 启动所有服务
main
exit 0