#!/bin/bash #链接文件 source /etc/profile #java虚拟机启动参数 #通过http://xxfox.perfma.com/jvm/check来检查参数的合理性 #各参数详解:http://calvin1978.blogcn.com/?p=1602 JAVA_OPTS="-server @run.memory@" #使用CMS GC算法 JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal" #启动时预申请内存 JAVA_OPTS="$JAVA_OPTS -XX:+AlwaysPreTouch" #Eden区与2个Survivor区总和的大小比值,8:1:1 JAVA_OPTS="$JAVA_OPTS -XX:SurvivorRatio=8" #老年代内存占用达到70%触发CMS,这个比例有计算公式 JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70" #在CMS初始标记阶段、重新标记阶段启用并发标记 JAVA_OPTS="$JAVA_OPTS -XX:+ParallelRefProcEnabled -XX:+CMSParallelInitialMarkEnabled -XX:-CMSParallelRemarkEnabled" #在CMS重新标记阶段之前执行一次Young GC,减少GC Root扫描开销 JAVA_OPTS="$JAVA_OPTS -XX:+CMSScavengeBeforeRemark" #减少对象在新生代停留时间,加快YGC速度 JAVA_OPTS="$JAVA_OPTS -XX:MaxTenuringThreshold=5" #在FULL GC的时候执行堆压缩 JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0" # System.gc() 使用CMS算法 JAVA_OPTS="$JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent" #在OOM时转储堆内存 JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/@project.build.finalName@/" #应用崩溃时生成一个error文件 JAVA_OPTS="$JAVA_OPTS -XX:ErrorFile==/data/logs/@project.build.finalName@/hs_err_%p.error" #打印详细GC数据 JAVA_OPTS="$JAVA_OPTS -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -XX:+PrintPromotionFailure -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -Xloggc:/data/logs/@project.build.finalName@/gc.gclog" JAVA_OPTS="$JAVA_OPTS -XX:-OmitStackTraceInFastThrow" #JAR包路径 APP_NAME=@project.build.finalName@.jar #服务暂停后等待时间,默认为120秒 PAUSE_WAIT=120 #进程停止需等待多少秒 SHUTDOWN_WAIT=30 workdir=$(cd $(dirname $0); pwd) #使用说明,用来提示输入参数 usage() { echo "Usage: sh 执行脚本.sh [start|stop|restart|status]" exit 1 } #检查程序是否在运行 checkpid(){ pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' ` if [ ! -z "${pid}" ]; then return 0 # 0=true fi return 1 # 1=false } #检查程序端口是否已启动 checkport() { if checkpid; then port=$(netstat -ntlp | grep $pid | awk '{printf $4}' | cut -d':' -f4) if [ ! -z "${port}" ]; then return 0 # 0=true else return 1 # 1=false fi else echo "${APP_NAME} is not running!" return 1 fi } checktcp() { echo "start check connections, $SECONDS." if checkport; then local count=0; until [ `netstat -ntp | grep ESTABLISHED | awk -v port=":$port" '$4~port{print}' | wc -l` = '0' ] || [ ${count} -gt ${PAUSE_WAIT} ] do if [ `expr ${count} % 5` -eq 0 ]; then echo "waiting for connections disconnect!" fi sleep 1 let count=$count+1; done if [ ${count} -gt ${PAUSE_WAIT} ]; then echo "wait for ${PAUSE_WAIT} seconds, still have connetion" #打印所有的连接 netstat -ntp | grep ESTABLISHED | awk -v port=":$port" '$4~port{print}' fi fi echo "end check connections, $SECONDS." } #启动方法 start(){ echo "starting ..." if checkpid; then echo "${APP_NAME} is already running. pid=${pid} ." else nohup java $JAVA_OPTS -jar $workdir/$APP_NAME > /dev/null 2>&1 & fi } pause() { if checkport; then url="http://localhost:$port/actuator/pause" echo $url local curlRtn=$(curl -s -XPOST $url | cat) echo "service pause $curlRtn" fi } #停止方法 stop(){ echo "stopping ..." if checkpid; then #停止分为3个步骤:暂停、检测tcp连接、停止进程 pause checktcp kill $pid local kwait=$SHUTDOWN_WAIT local count=0; until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ] do echo "waiting for processes to exit"; sleep 1 let count=$count+1; done if [ $count -gt $kwait ]; then echo "killing processes didn't stop after $SHUTDOWN_WAIT seconds" kill -9 $pid fi echo "${APP_NAME} stopped." else echo "${APP_NAME} is not running" fi } #输出运行状态 status(){ if checkpid; then echo "${APP_NAME} is running. pid is ${pid}" else echo "${APP_NAME} is NOT running." fi } #重启 restart(){ stop start } #根据输入参数,选择执行对应方法,不输入则执行使用说明 case "$1" in "start") start ;; "stop") stop ;; "status") status ;; "restart") restart ;; "check") checktcp ;; *) usage ;; esac