#! /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}.shecho "守护进程的文件名(不含后缀):[[ ${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/fireif [[ ! ${basePath} =~ ${BASE_PATH} ]]; then log_out "守护进程存放位置有误,执行失败!!!" E exitfi### # 杀死守护进程### 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_FILEsed -i '/watch_server/d' $FIND_FILEsed -i '/server_keeper/d' $FIND_FILEsed -i '/server/d' $FIND_FILEif [ $(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 2fiif [ $(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 2fiJAVA_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 和 kafkafunction 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}# 启动 redisfunction 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################ 示例 (末)################ftpServerftpserverftphttpServer httpServer.jar 1Ghttpserver httpServer.jar 1Ghttp httpServer.jar 1GHTTP httpServer.jar 1GMessageServer MessageServer.jar 2GFireAppServer FireAppServer.jar 2GCallServer CallServer.jar 2GDCPS_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# 启动所有服务mainexit 0