1. #! /bin/sh
    2. #########################################################################
    3. # 守护进程操作说明:
    4. # 1.启动命令:nohup sh watch_server_v3.sh >/dev/null 2>&1 &
    5. # 2.需将 watch_server_v3.sh 放在 [最大盘]/ICC/dahua/fire/server_keeper 下。
    6. # 3.务必确保有且仅有当前守护进程正在运行。
    7. # 4.如需新增服务,请在 serverList.sh 中按照相关说明添加相关服务。
    8. # 5.启动守护进程后,务必确认当前路径下无 ERROR.log 产生。如有,请根
    9. # 据提示解决相应问题。
    10. #########################################################################
    11. # 更新日志 2020-7-15 23:39:52 刘迎光
    12. # 1.进一步降低使用和维护守护进程的难度。
    13. # 2.优化脚本执行逻辑。新增服务后无需重启,即可被守护。
    14. # 3.增加对守护脚本存放路径的强校验
    15. #########################################################################
    16. # TODO:定时清理日志(一天一次)
    17. #########################################################################
    18. # 守护进程的文件名(不含后缀)
    19. watchPath=$(pwd)
    20. watchFileName=${0} # 文件名(含后缀)
    21. watchFileName=${watchFileName%.*} # 文件名(不含后缀)
    22. watchFilePath=${watchPath}/${watchFileName}.sh
    23. echo "守护进程的文件名(不含后缀):[[ ${watchFileName} ]]"
    24. # 新服务基础路径、日志文件名称
    25. basePath=$(
    26. cd ..
    27. pwd
    28. )
    29. time=$(date +%Y-%m-%d %H:%M:%S)
    30. # 输出日志信息
    31. # args-1:日志级别(ERROR, WARN, INFO)
    32. # args-2:输出内容
    33. function log_out() {
    34. # 当前执行操作的文件
    35. cur_file=$0
    36. # 日志内容
    37. logContent=$1
    38. # 日志级别
    39. LEVEL_CODE=$2
    40. # 将字符串转成大写,再进行字符串比较
    41. LEVEL_CODE=$(echo ${LEVEL_CODE} | tr [a-z] [A-Z])
    42. logTime=$(date +'%Y-%m-%d %H:%M:%S')
    43. # LEVEL_CODE 为空,则默认日志等级为 INFO
    44. if [[ ! -n "${LEVEL_CODE}" ]]; then
    45. LEVEL="INFO"
    46. elif [[ "${LEVEL_CODE}" == D* ]]; then
    47. LEVEL="DEBUG"
    48. elif [[ "${LEVEL_CODE}" == I* ]]; then
    49. LEVEL="INFO"
    50. elif [[ "${LEVEL_CODE}" == W* ]]; then
    51. LEVEL="WARN"
    52. elif [[ "${LEVEL_CODE}" == E* ]]; then
    53. LEVEL="ERROR"
    54. else
    55. LEVEL="INFO"
    56. fi
    57. echo "${logTime}:[$cur_file][${LEVEL}] ${logContent}"
    58. echo "${logTime}:[$cur_file][${LEVEL}] ${logContent}" >>${LEVEL}.log
    59. }
    60. # 调用示例
    61. # log_out "ip参数:$IP" i
    62. # 校验文件位置是否正确,如果错误,则记录到日志中,并返回错误信息
    63. BASE_PATH=/ICC/dahua/fire
    64. if [[ ! ${basePath} =~ ${BASE_PATH} ]]; then
    65. log_out "守护进程存放位置有误,执行失败!!!" E
    66. exit
    67. fi
    68. ### # 杀死守护进程
    69. ### function killWatch(){
    70. ### numServer=$(ps -ef | grep watch | grep -v "grep" | grep -v "watchdog")
    71. ### if [[ ${numServer} -gt 1 ]];then
    72. ### kill -9 $( ps -ef | grep watch | grep -v "grep" | grep -v "watchdog" | awk -F ' ' '{print $2}' )
    73. ### fi
    74. ###
    75. ### }
    76. # 添加守护进程到开机启动中(服务器重启即会执行)
    77. FIND_S="source /etc/profile"
    78. FIND_STR="nohup sh ${watchFileName}.sh >/dev/null 2>&1 &"
    79. # 开机启动项文件位置
    80. FIND_FILE="/etc/rc.d/rc.local"
    81. # 移除开机启动项中的相关内容
    82. sed -i '/\/etc\/profile/d' $FIND_FILE
    83. sed -i '/watch_server/d' $FIND_FILE
    84. sed -i '/server_keeper/d' $FIND_FILE
    85. sed -i '/server/d' $FIND_FILE
    86. if [ $(grep -c "$FIND_S" $FIND_FILE) -eq '0' ]; then
    87. chmod 777 /etc/rc.d/rc.local
    88. echo "source /etc/profile" >>/etc/rc.d/rc.local
    89. sleep 2
    90. fi
    91. if [ $(grep -c "watch_server" $FIND_FILE) -eq '0' ]; then
    92. chmod 777 /etc/rc.d/rc.local
    93. echo "cd ${watchPath}" >>/etc/rc.d/rc.local
    94. sleep 2
    95. chmod 777 /etc/rc.d/rc.local
    96. echo "nohup sh ${watchFileName}.sh >/dev/null 2>&1 &" >>/etc/rc.d/rc.local
    97. sleep 2
    98. fi
    99. JAVA_OPTS="-Xss512k -XX:MaxMetaspaceSize=1024M -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=75 -XX:ParallelGCThreads=4 -XX:+HeapDumpOnOutOfMemoryError"
    100. # 检验服务是否启动的间隔时间
    101. sleepTime=10
    102. ###########################################################
    103. function start_kafka_zookeeper() {
    104. serverName=zookeeper
    105. path=${basePath}/${serverName}
    106. zookeeper_start_file=${path}/bin/zookeeper-server-start.sh
    107. zookeeper_stop_file=${path}/bin/zookeeper-server-stop.sh
    108. zookeeper_cfg_file=${path}/config/zookeeper.properties
    109. #判断对应 Kafka zookeeper 进程是否已经启动
    110. if $(ps -ef | grep -v "grep" | grep ${path} | grep -q "zookeeper.properties"); then
    111. log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
    112. return
    113. fi
    114. log_out "启动 ${serverName} 开始,... "
    115. cd ${path}
    116. nohup bin/zookeeper-server-start.sh config/zookeeper.properties >/dev/null 2>&1 &
    117. log_out "启动 zookeeper 完成 ... "
    118. cd -
    119. sleep 10
    120. }
    121. function start_kafka() {
    122. serverName=kafka
    123. path=${basePath}/${serverName}
    124. #判断对应 kafka Server 进程是否已经启动
    125. if $(ps -ef | grep ${path} | grep -q "kafka.Kafka"); then
    126. log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
    127. return
    128. fi
    129. cd ${path}
    130. nohup bin/kafka-server-start.sh config/server.properties >/dev/null 2>&1 &
    131. cd -
    132. }
    133. # 启动 zookeeper 和 kafka
    134. function start_zookeeperAndKafka() {
    135. serverName=kafka
    136. path=${basePath}/${serverName}
    137. if [ ! -d "${path}" ]; then
    138. log_out "[[ ${serverName} ]] 不存在(或者 文件夹名称与标准服务名不一致),跳过..."
    139. else
    140. kafka_port=$(cat ${path}/config/server.properties | grep "^listeners" | awk -F ':' '{print $3}')
    141. if [[ ! -n "${kafka_port}" ]]; then
    142. log_out "未找到 [[ ${serverName} ]] 的端口 kafka_port !!!请检查 server.properties 中 是否包含 listeners " E
    143. return
    144. else
    145. # log_out "kafka_port:${kafka_port}"
    146. start_kafka_zookeeper
    147. start_kafka
    148. fi
    149. fi
    150. }
    151. # 启动 redis
    152. function start_redis() {
    153. serverName=redis
    154. path=${basePath}/${serverName}
    155. if [ ! -d "${path}" ]; then
    156. # log_out "没有该服务:[[ ${serverName} ]],无需启动"
    157. log_out "[[ ${serverName} ]] 不存在(或者 文件夹名称与标准服务名不一致),跳过..."
    158. else
    159. redis_file=${path}/redis-server
    160. redis_conf=${path}/redis.conf
    161. #判断对应 redis 进程是否已经启动
    162. if $(ps -ef | grep ${path} | grep -q redis-server); then
    163. log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
    164. return
    165. fi
    166. log_out "[[ ${serverName} ]] 未运行,开始启动... " W
    167. cd ${path}
    168. log_out "${redis_file} ${redis_conf} &"
    169. ${redis_file} ${redis_conf} &
    170. echo "[[ ${serverName} ]] 启动完成... "
    171. cd -
    172. fi
    173. }
    174. #mysql添加守护
    175. function start_mysql() {
    176. serverName=mysql
    177. path=${basePath}/${serverName}
    178. if [ ! -d "${path}" ]; then
    179. log_out "没有该服务:[[ mysql ]],无需启动"
    180. else
    181. #判断对应 mysql 进程是否已经启动
    182. mysqlStatus=$(systemctl status mysqld | grep "Active: active")
    183. if [[ ${mysqlStatus} == *active* ]]; then
    184. # if [ -n ${mysqlStatus} ]; then
    185. log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
    186. return
    187. else
    188. log_out "[[ ${serverName} ]] 未运行,开始启动... " W
    189. setenforce 0
    190. sed -i 's/SELINUX=enforcing SELINUX=disabled/g' /etc/selinux/config
    191. if [ -f "${path}/../../../../firecontroldata/mysql/mysql.sock.lock" ]; then
    192. rm -rf ${path}/../../../../firecontroldata/mysql/mysql.sock.lock
    193. fi
    194. systemctl restart mysqld.service
    195. echo "[[ ${serverName} ]] 启动完成... "
    196. fi
    197. fi
    198. }
    199. # 常用函数(启动 war 包服务)
    200. function startWarServer() {
    201. # 服务名称(new)
    202. serverName=$1
    203. serverPath=${basePath}/${serverName}
    204. numServer=$(ps -aux | grep ${serverPath}/bin | grep -v "grep" | wc -l)
    205. if [[ ${numServer} -lt 1 ]]; then
    206. log_out "[[ ${serverName} ]] 未运行,开始启动... " W
    207. cd ${serverPath}
    208. bin/startup.sh
    209. cd -
    210. else
    211. log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
    212. fi
    213. }
    214. # 常用函数(启动 jar 包服务)
    215. function startJarServer() {
    216. # 服务名称(new)
    217. serverName=$1
    218. # jar 包名称
    219. jarName=$2
    220. # 限制内存大小(含单位:G)
    221. limitXmx=$3
    222. serverPath=${basePath}/${serverName}
    223. jarPath=${serverPath}/${jarName}
    224. # 去除单位(:G)
    225. limitSize=${limitXmx%G*}
    226. if [ ! -n "${limitSize}" ]; then
    227. # 默认限制内存大小:1G
    228. limitXmx=1G
    229. elif [[ ${limitSize} -gt 5 ]]; then
    230. log_out "${limitXmx} 过大,请确认是否正确!!!" E
    231. fi
    232. log_out "serverName=${serverName},jarName=${jarName},limitXmx=${limitXmx},serverPath=${serverPath},jarPath=${jarPath}"
    233. numServer=$(ps -aux | grep ${jarPath} | grep -v "grep" | wc -l)
    234. if [[ ${numServer} -lt 1 ]]; then
    235. log_out "[[ ${serverName} ]] 未运行,开始启动... " W
    236. cd ${serverPath}
    237. nohup java -server -Xms512m -Xmx${limitXmx} ${JAVA_OPTS} -XX:HeapDumpPath=/logs/${serverName}.dump -jar ${jarPath} >/dev/null 2>&1 &
    238. cd -
    239. else
    240. log_out "[[ ${serverName} ]] 正常运行中,无需启动 ... "
    241. fi
    242. }
    243. # 启动服务(war 包和 jar 包服务启动均使用该方法)
    244. function startServer() {
    245. serverName=$1
    246. serverPath=${basePath}/{serverName}
    247. if [ ! -d "${serverPath}" ]; then
    248. log_out "[[ ${serverName} ]] 不存在(或者 文件夹名称与标准服务名不一致),跳过..."
    249. else
    250. FIND_FILE=${basePath}/${serverName}/bin
    251. info="服务名称:[[ ${serverName} ]]"
    252. if [[ -d "${FIND_FILE}" ]]; then
    253. info=${info}",war 包启动"
    254. startWarServer ${serverName}
    255. else
    256. packageName=$2
    257. limitSize=$3
    258. info=${info}",jar 包名称:[[ ${packageName} ]] ,限制内存大小:[[ ${limitSize} ]] "
    259. startJarServer ${serverName} ${packageName} ${limitSize}
    260. echo "${info}"
    261. fi
    262. fi
    263. }
    264. # 查询是否存在 serverList.sh,若不存在则创建,存在则跳过
    265. function mkDir() {
    266. file=$1
    267. if [ -f ${file} ]; then
    268. echo "[[ ${file} ]] 已存在,无需创建"
    269. else
    270. echo "[[ ${file} ]] 文件不存在,开始创建"
    271. # 创建文件
    272. touch ${file}
    273. # 往文件中添加初始化的文件列表
    274. echo "
    275. #! /bin/sh
    276. # 启动守护进程指令:nohup sh ${watchFileName}.sh >/dev/null 2>&1 &
    277. # [注意事项]
    278. # 1.禁止手动启动任何服务,否则可能导致服务启动异常。
    279. # 2.启动守护进程后,务必观察当前文件夹下是否有 ERROR.log 文件产生。如有,务必根据提示修复存在问题。
    280. # 3.新增服务后即被守护,无需重启守护进程。
    281. ################ 示例 (始)################
    282. # 添加 war 包服务格式:
    283. # 服务名称 war包名称(选填)
    284. IFCS IFCS.war
    285. # 添加 jar 包服务格式:
    286. # 服务名称 jar包 限制最大内存(单位:G,选填)
    287. DCPS_TCP DCPS.jar 1G
    288. ################ 示例 (末)################
    289. ftpServer
    290. ftpserver
    291. ftp
    292. httpServer httpServer.jar 1G
    293. httpserver httpServer.jar 1G
    294. http httpServer.jar 1G
    295. HTTP httpServer.jar 1G
    296. MessageServer MessageServer.jar 2G
    297. FireAppServer FireAppServer.jar 2G
    298. CallServer CallServer.jar 2G
    299. DCPS_UDP DCPS_UDP.jar 1G
    300. # IFCSI IFCSI.war
    301. # IFCSI2.0 IFCSI.jar 2G
    302. # DCPS-HTTP_YD1.0 DCPS-HTTP.jar 1G
    303. # ONENET1.0 DCPS-HTTP.jar 1G
    304. # ONENET1 DCPS-HTTP.jar 1G
    305. # ONENET DCPS-HTTP.jar 1G
    306. # DCPS-HTTP_YD1.1 DCPS-HTTP.jar 1G
    307. # ONENET1.1 DCPS-HTTP.jar 1G
    308. # DCPS-HTTP_DX DCPS-HTTP.jar 1G
    309. # DXIOT DCPS-HTTP.jar 1G
    310. " >${file}
    311. log_out "创建 [[ ${file} ]] 文件结束"
    312. fi
    313. }
    314. # 获取文件大小
    315. function getFileSize() {
    316. file=$1
    317. # 获取文件大小(以 M 为单位)
    318. fileSize=$(du -sb ${file} | awk '{print int($1/1024/1024)}')
    319. echo "${fileSize}"
    320. }
    321. ### TODO:清理日志(大小超过某值)
    322. ## 定时清理日志
    323. #function cleanFile() {
    324. #
    325. # file=$1
    326. #
    327. # fielSize=$(getFileSize ${file})
    328. # echo "${file} 大小:${fielSize}(M)"
    329. #
    330. # if [[ ${fielSize} -lt 100 ]]; then
    331. # echo "${file} 小于 100M,无需清理"
    332. # return
    333. # else
    334. # echo "${file} 大于 100M,清理"
    335. # fi
    336. #
    337. #}
    338. # 获取并启动服务(列表)
    339. function readAndRunServerList() {
    340. # 需要读取服务列表的文件名称(带文件类型,eg. serverList.sh)
    341. serverListFile=$1
    342. echo "服务列表文件:${serverListFile}"
    343. # 读取文件(过滤掉 注释行、空行)
    344. egrep -v "^\s*#|^\s*$" ${serverListFile} | while read xxx; do
    345. serverName=$(echo ${xxx} | awk -F ' ' '{print $1}')
    346. packageName=$(echo ${xxx} | awk -F ' ' '{print $2}')
    347. limitSize=$(echo ${xxx} | awk -F ' ' '{print $3}')
    348. startServer ${serverName} ${serverName} ${limitSize}
    349. done
    350. }
    351. # 总的调用服务方法
    352. function main() {
    353. while true; do
    354. # 启动 zookeeper 和 kafka
    355. start_zookeeperAndKafka
    356. # 启动 redis
    357. start_redis
    358. # 启动 mysql
    359. start_mysql
    360. # 调用方法(获取 服务列表)
    361. readAndRunServerList serverList.sh
    362. # cleanFile 文件名
    363. echo "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [[ ${sleepTime} ]] 秒后开始下一轮检查 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "
    364. echo "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [[ ${sleepTime} ]] 秒后开始下一轮检查 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "
    365. echo "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [[ ${sleepTime} ]] 秒后开始下一轮检查 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "
    366. sleep ${sleepTime}
    367. done
    368. }
    369. #####################################################
    370. #####################################################
    371. #####################################################
    372. #####################################################
    373. #####################################################
    374. #####################################################
    375. # 创建文件
    376. mkDir serverList.sh
    377. # 启动所有服务
    378. main
    379. exit 0