Dubbo应用启动与停止脚本,超详细解析

本周刚好研究了一下dubbo的启动脚本,所以在官网的启动脚本和公司内部的启动脚本做了一个整理,弄了一份比较通过的Dubbo应用启动和停止脚本。

         下面的脚本只应用于配置分离的应用,什么叫做配置分离呢?就是使用maven打包时,借助assemble插件,打一个tar.gz的压缩包。里面有三个目录。bin目录,用来存放启动与停止的脚本,lib目录,用来存放相关依赖的jar包,注意,这里每个jar包都是单独的,而不是一个大的jar包。conf目录,用来存放配置文件,包括dubbo.property,applicatiom.xml等文件。

工程解压后如下图:

本文脚本免费下载

1、启动脚本

详细的注释都已写在脚本中,请看具体的注释

#!/bin/bash
cd `dirname $0`

#当前路径
BIN_DIR=`pwd`

#向上一层路径
cd ..
DEPLOY_DIR=`pwd`
echo $DEPLOY_DIR

#配置文件路径
CONF_DIR=$DEPLOY_DIR/conf
#日志输出路径
LOGS_DIR=$DEPLOY_DIR/logs

# 如果JDK环境变量没有写到全局要添加如下几行
# JAVA_HOME=/opt/java/jdk1.6.0_45
# PATH=$JAVA_HOME/bin:$PATH
# export JAVA_HOME
# export PATH

#从dubbo.properties取得应用名、端口号,端口名
SERVER_NAME=`sed ‘/dubbo.application.name/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`
SERVER_PROTOCOL_NAME=`sed ‘/dubbo.protocol.name/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`
SERVER_PROTOCOL_PORT=`sed ‘/dubbo.protocol.port/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`

#应用名为空的话就取当前系统名
if [ -z "$SERVER_NAME" ]; then
    echo "SERVER_NAME is empty"
    SERVER_NAME=`hostname`
fi

#根据配置文件路径去查找当前是否已有dubbo应用启动起来
APP_PID=`ps -ef -ww | grep "java" | grep " -DappName=$SERVER_NAME " | awk ‘{print $2}‘`
echo "SERVER_NAME: $SERVER_NAME"
echo "SERVER_PROTOCOL_NAME: $SERVER_PROTOCOL_NAME"
echo "SERVER_PROTOCOL_PORT: $SERVER_PROTOCOL_PORT"
echo "APP_PID: $APP_PID" 

#APP_PID不为空,说明应用已启动,直接退出
if [ -n "$APP_PID" ]; then
    echo "ERROR: The $SERVER_NAME already started!"
    echo "PID: $APP_PID"
    exit 1
fi

#检查端口是否被占用
if [ -n "$SERVER_PROTOCOL_PORT" ]; then
    SERVER_PORT_COUNT=`netstat -tln | grep $SERVER_PROTOCOL_PORT | wc -l`
    if [ $SERVER_PORT_COUNT -gt 0 ]; then
        echo "ERROR: The $SERVER_NAME port $SERVER_PROTOCOL_PORT already used!"
        exit 1
    fi
fi

#如果logs目录不存在,就创建一个
if [ ! -d $LOGS_DIR ]; then
    mkdir $LOGS_DIR
fi

echo "LOGS_DIR :$LOGS_DIR"

#控制台日志输出收集位置
STDOUT_FILE=$LOGS_DIR/stdout.log

#依赖jar包目录
LIB_DIR=$DEPLOY_DIR/lib

#将上面的jar文件名称,拼接上lib的路径然后输出
LIB_JARS=`ls $LIB_DIR|grep .jar|awk ‘{print "‘$LIB_DIR‘/"$0}‘|tr "\n" ":"`

#-DappName指定应用名
JAVA_OPTS="-DappName=$SERVER_NAME -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Ddubbo.shutdown.hook=true"

#调试模式
JAVA_DEBUG_OPTS=""
if [ "$1" = "debug" ]; then
    JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n "
fi
JAVA_JMX_OPTS=""
if [ "$1" = "jmx" ]; then
    JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false "
fi

#首先将java版本号信息输出到标准输出,然后查找’64-bit’信息,目的就是判断jdk版本是否为64位

JAVA_MEM_OPTS=""
BITS=`java -version 2>&1 | grep -i 64-bit`

#JVM启动基本参数,这里根据应用自行调整
JAVA_MEM_SIZE_OPTS="-Xmx768m -Xms378m -Xmn256m -XX:PermSize=64m -XX:MaxPermSize=256M -Xss256k"

#根据32位和64位配置不同的启动java垃圾回收参数,根据应用自行调整
if [ -n "$BITS" ]; then
    JAVA_MEM_OPTS=" -server $JAVA_MEM_SIZE_OPTS -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
else
    JAVA_MEM_OPTS=" -server $JAVA_MEM_SIZE_OPTS -XX:SurvivorRatio=2 -XX:+UseParallelGC "
fi

echo -e "Starting the $SERVER_NAME ...\c"
echo "启动参数:java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS $JAVA_PROPERTIES_OPTS -classpath $CONF_DIR:$LIB_JARS com.alibaba.dubbo.container.Main"

#通过java命令启动服务,同时将其作为后台任务执行。
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -classpath $CONF_DIR:$LIB_JARS com.alibaba.dubbo.container.Main > $STDOUT_FILE 2>&1 &

#睡眠一下再检查应用是否启动,下面这里注释打开的话,就把最下面的那一段注释掉
#sleep 1
#APP_PID=`ps -f | grep java | grep "$CONF_DIR" |awk ‘{print $2}‘`

#if [ -z "$APP_PID" ]; then
    #echo "START APP FAIL!"
    #echo "STDOUT: $STDOUT_FILE"
    #exit 1
#fi

#echo "START  SUCCESSED APP_PID: $APP_PID"
#echo "STDOUT: $STDOUT_FILE"

#grep -c 阻止正常的结果输出,转而输出匹配的结果数量,这里就是输出OK的个数。
COUNT=0
while [ $COUNT -lt 1 ]; do
    echo -e ".\c"
    sleep 1
    if [ -n "$SERVER_PROTOCOL_PORT" ]; then
        if [ "$SERVER_PROTOCOL_NAME" == "dubbo" ]; then
            COUNT=`echo status | nc -i 1 127.0.0.1 $SERVER_PROTOCOL_PORT | grep -c OK`
        else
            COUNT=`netstat -an | grep $SERVER_PROTOCOL_PORT | wc -l`
        fi
    else
        COUNT=`ps -f | grep java | grep "$DEPLOY_DIR" | awk ‘{print $2}‘ | wc -l`
    fi
    if [ $COUNT -gt 0 ]; then
        break
    fi
done
echo "OK!"
APP_PID=`ps -ef -ww | grep "java" | grep " -DappName=$SERVER_NAME " | awk ‘{print $2}‘`
echo "START  SUCCESSED APP_PID: $APP_PID"
echo "STDOUT: $STDOUT_FILE"

直接执行上面脚本sh start.sh,输出内容如下:

到logs/stdout.log可查看详细启动过程以及失败信息等

还可以使用命令ps -ef|grep java确定应用是否起来:

或者看Dubbo的监控页面也可查看服务是否注册上去:

2、停止

停止就更加简单了,就是根据应用名找到pid,然后kill。

#!/bin/bash
cd `dirname $0`

#当前路径
BIN_DIR=`pwd`

#向上一层路径
cd ..
DEPLOY_DIR=`pwd`
echo $DEPLOY_DIR

#配置文件路径
CONF_DIR=$DEPLOY_DIR/conf
#日志输出路径
LOGS_DIR=$DEPLOY_DIR/logs

# 如果JDK环境变量没有写到全局要添加如下几行
# JAVA_HOME=/opt/java/jdk1.6.0_45
# PATH=$JAVA_HOME/bin:$PATH
# export JAVA_HOME
# export PATH

#从dubbo.properties取得应用名、端口号,端口名
SERVER_NAME=`sed ‘/dubbo.application.name/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`
SERVER_PROTOCOL_NAME=`sed ‘/dubbo.protocol.name/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`
SERVER_PROTOCOL_PORT=`sed ‘/dubbo.protocol.port/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`

#应用名为空的话就取当前系统名
if [ -z "$SERVER_NAME" ]; then
    echo "SERVER_NAME is empty"
    SERVER_NAME=`hostname`
fi

#根据配置文件路径去查找当前是否已有dubbo应用启动起来
APP_PID=`ps -ef -ww | grep "java" | grep " -DappName=$SERVER_NAME " | awk ‘{print $2}‘`
echo "SERVER_NAME: $SERVER_NAME"
echo "SERVER_PROTOCOL_NAME: $SERVER_PROTOCOL_NAME"
echo "SERVER_PROTOCOL_PORT: $SERVER_PROTOCOL_PORT"
echo "APP_PID: $APP_PID" 

#APP_PID不为空,说明应用已启动,直接退出
if [ -n "$APP_PID" ]; then
    echo "ERROR: The $SERVER_NAME already started!"
    echo "PID: $APP_PID"
    exit 1
fi

#检查端口是否被占用
if [ -n "$SERVER_PROTOCOL_PORT" ]; then
    SERVER_PORT_COUNT=`netstat -tln | grep $SERVER_PROTOCOL_PORT | wc -l`
    if [ $SERVER_PORT_COUNT -gt 0 ]; then
        echo "ERROR: The $SERVER_NAME port $SERVER_PROTOCOL_PORT already used!"
        exit 1
    fi
fi

#如果logs目录不存在,就创建一个
if [ ! -d $LOGS_DIR ]; then
    mkdir $LOGS_DIR
fi

echo "LOGS_DIR :$LOGS_DIR"

#控制台日志输出收集位置
STDOUT_FILE=$LOGS_DIR/stdout.log

#依赖jar包目录
LIB_DIR=$DEPLOY_DIR/lib

#将上面的jar文件名称,拼接上lib的路径然后输出
LIB_JARS=`ls $LIB_DIR|grep .jar|awk ‘{print "‘$LIB_DIR‘/"$0}‘|tr "\n" ":"`

#-DappName指定应用名
JAVA_OPTS="-DappName=$SERVER_NAME -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Ddubbo.shutdown.hook=true"

#调试模式
JAVA_DEBUG_OPTS=""
if [ "$1" = "debug" ]; then
    JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n "
fi
JAVA_JMX_OPTS=""
if [ "$1" = "jmx" ]; then
    JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false "
fi

#首先将java版本号信息输出到标准输出,然后查找’64-bit’信息,目的就是判断jdk版本是否为64位

JAVA_MEM_OPTS=""
BITS=`java -version 2>&1 | grep -i 64-bit`

#JVM启动基本参数,这里根据应用自行调整
JAVA_MEM_SIZE_OPTS="-Xmx768m -Xms378m -Xmn256m -XX:PermSize=64m -XX:MaxPermSize=256M -Xss256k"

#根据32位和64位配置不同的启动java垃圾回收参数,根据应用自行调整
if [ -n "$BITS" ]; then
    JAVA_MEM_OPTS=" -server $JAVA_MEM_SIZE_OPTS -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
else
    JAVA_MEM_OPTS=" -server $JAVA_MEM_SIZE_OPTS -XX:SurvivorRatio=2 -XX:+UseParallelGC "
fi

echo -e "Starting the $SERVER_NAME ...\c"
echo "启动参数:java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS $JAVA_PROPERTIES_OPTS -classpath $CONF_DIR:$LIB_JARS com.alibaba.dubbo.container.Main"

#通过java命令启动服务,同时将其作为后台任务执行。
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -classpath $CONF_DIR:$LIB_JARS com.alibaba.dubbo.container.Main > $STDOUT_FILE 2>&1 &

#睡眠一下再检查应用是否启动,下面这里注释打开的话,就把最下面的那一段注释掉
#sleep 1
#APP_PID=`ps -f | grep java | grep "$CONF_DIR" |awk ‘{print $2}‘`

#if [ -z "$APP_PID" ]; then
    #echo "START APP FAIL!"
    #echo "STDOUT: $STDOUT_FILE"
    #exit 1
#fi

#echo "START  SUCCESSED APP_PID: $APP_PID"
#echo "STDOUT: $STDOUT_FILE"

#grep -c 阻止正常的结果输出,转而输出匹配的结果数量,这里就是输出OK的个数。
COUNT=0
while [ $COUNT -lt 1 ]; do
    echo -e ".\c"
    sleep 1
    if [ -n "$SERVER_PROTOCOL_PORT" ]; then
        if [ "$SERVER_PROTOCOL_NAME" == "dubbo" ]; then
            COUNT=`echo status | nc -i 1 127.0.0.1 $SERVER_PROTOCOL_PORT | grep -c OK`
        else
            COUNT=`netstat -an | grep $SERVER_PROTOCOL_PORT | wc -l`
        fi
    else
        COUNT=`ps -f | grep java | grep "$DEPLOY_DIR" | awk ‘{print $2}‘ | wc -l`
    fi
    if [ $COUNT -gt 0 ]; then
        break
    fi
done
echo "OK!"
APP_PID=`ps -ef -ww | grep "java" | grep " -DappName=$SERVER_NAME " | awk ‘{print $2}‘`
echo "START  SUCCESSED APP_PID: $APP_PID"
echo "STDOUT: $STDOUT_FILE"

sh stop.sh

执行后输出结果:

详细的输出日志可用/logs/shell.log文件查看

如果想输出dump文件,执行

sh stop.sh dump

其中dump.sh内容如下:

#!/bin/bash
cd `dirname $0`
BIN_DIR=`pwd`
cd ..
DEPLOY_DIR=`pwd`
CONF_DIR=$DEPLOY_DIR/conf

# 如果JDK环境变量没有写到全局要添加如下几行
# JAVA_HOME=/opt/java/jdk1.6.0_45
# PATH=$JAVA_HOME/bin:$PATH
# export JAVA_HOME
# export PATH

SERVER_NAME=`sed ‘/^app.process.name/!d;s/.*=//‘ conf/dubbo.properties | tr -d ‘\r‘`

if [ -z "$SERVER_NAME" ]; then
    SERVER_NAME=`hostname`
fi

PIDS=`ps -ef -ww | grep "java" | grep " -DappName=$SERVER_NAME " | awk ‘{print $2}‘`
if [ -z "$PIDS" ]; then
    echo "ERROR: The $SERVER_NAME does not started!"
    exit 1
fi

LOGS_DIR=$DEPLOY_DIR/logs
if [ ! -d "$LOGS_DIR" ]; then
	mkdir -p "$LOGS_DIR"
fi
DUMP_DIR=$LOGS_DIR/dump
if [ ! -d $DUMP_DIR ]; then
	mkdir $DUMP_DIR
fi
DUMP_DATE=`date +%Y%m%d%H%M%S`
DATE_DIR=$DUMP_DIR/$DUMP_DATE
if [ ! -d $DATE_DIR ]; then
	mkdir $DATE_DIR
fi

echo -e "Dumping the $SERVER_NAME ...\c"
for PID in $PIDS ; do
	jstack $PID > $DATE_DIR/jstack-$PID.dump 2>&1
	echo -e ".\c"
	jinfo $PID > $DATE_DIR/jinfo-$PID.dump 2>&1
	echo -e ".\c"
	jstat -gcutil $PID > $DATE_DIR/jstat-gcutil-$PID.dump 2>&1
	echo -e ".\c"
	jstat -gccapacity $PID > $DATE_DIR/jstat-gccapacity-$PID.dump 2>&1
	echo -e ".\c"
	jmap $PID > $DATE_DIR/jmap-$PID.dump 2>&1
	echo -e ".\c"
	jmap -heap $PID > $DATE_DIR/jmap-heap-$PID.dump 2>&1
	echo -e ".\c"
	jmap -histo $PID > $DATE_DIR/jmap-histo-$PID.dump 2>&1
	echo -e ".\c"
	if [ -r /usr/sbin/lsof ]; then
	/usr/sbin/lsof -p $PID > $DATE_DIR/lsof-$PID.dump
	echo -e ".\c"
	fi
done

if [ -r /bin/netstat ]; then
/bin/netstat -an > $DATE_DIR/netstat.dump 2>&1
echo -e ".\c"
fi
if [ -r /usr/bin/iostat ]; then
/usr/bin/iostat > $DATE_DIR/iostat.dump 2>&1
echo -e ".\c"
fi
if [ -r /usr/bin/mpstat ]; then
/usr/bin/mpstat > $DATE_DIR/mpstat.dump 2>&1
echo -e ".\c"
fi
if [ -r /usr/bin/vmstat ]; then
/usr/bin/vmstat > $DATE_DIR/vmstat.dump 2>&1
echo -e ".\c"
fi
if [ -r /usr/bin/free ]; then
/usr/bin/free -t > $DATE_DIR/free.dump 2>&1
echo -e ".\c"
fi
if [ -r /usr/bin/sar ]; then
/usr/bin/sar > $DATE_DIR/sar.dump 2>&1
echo -e ".\c"
fi
if [ -r /usr/bin/uptime ]; then
/usr/bin/uptime > $DATE_DIR/uptime.dump 2>&1
echo -e ".\c"
fi

echo "OK!"
echo "DUMP: $DATE_DIR"

这是dump文件

本文脚本免费下载

时间: 2024-10-10 02:19:04

Dubbo应用启动与停止脚本,超详细解析的相关文章

JFinal 源码超详细解析之DB+ActiveRecord

我记得以前有人跟我说,"面试的时候要看spring的源码,要看ioc.aop的源码"那为什么要看这些开源框架的源码呢,其实很多人都是"应急式"的去读,就像读一篇文章一下,用最快的速度把文章从头到尾读一遍,那结果就是当你读完它,你也不清楚它讲了一个什么故事,想表达什么. 一个优秀的架构的源码我认为就好像一本名著一样,你的"文学"水平越高,你就越能读出作者设计的精妙之处.一篇源码在你不同水平的时候,能读出不同的东西,因此,我觉得优秀的框架的源码是经久

算法核心——空间复杂度和时间复杂度超详细解析

算法核心——空间复杂度和时间复杂度超详细解析 一.什么是算法 算法: 一个有限指令集 接受一些输入(有些情况下不需要收入) 产生输出 一定在有限步骤之后终止 每一条指令必须: 有充分明确的目标,不可以有歧义 计算机能处理的范围之内 描述应不依赖于任何一种计算机语言以及具体的实现手段 其实说白了,算法就是一个计算过程解决问题的方法.我们现在已经知道数据结构表示数据是怎么存储的,而“程序=数据结构+算法”,数据结构是静态的,算法是动态的,它们加起来就是程序. 对算法来说有输入,有输出,相当于函数有参

shell 启动和停止脚本

启动脚本 start_kmeans_v3.sh #!/bin/bash #用于kmeans_data_v3_hadle启动 ps -ef | grep kmeans_data_v3_hadle.py > stop.txt a2=$(awk 'END{print NR}' stop.txt) rm -rf stop.txt if [ ${a2} -gt 1 ]; then echo "已启动服务,请不要重复启动!" else nohup python -u kmeans_data_

Elasticsearch启动、停止脚本

注:本文出自博主:chloneda Elasticsearch官网 构建Elasticsearch启动脚本 start_es.sh. #!/bin/bash export ES_HOME=xxx su elastic -c "sh ${ES_HOME}/bin/elasticsearch -d -p ${ES_HOME}/pid" 参数说明: su:登录用户. elastic:部署Elasticsearch用户,避免root用户而无法启动. c:c参数后跟具体命令. d:Elastic

【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由Eberhart 博士和kennedy 博士提出,源于对鸟群捕食的行为研究 .该算法最初是受到飞鸟集群活动的规律性启发,进而利用群体智能建立的一个简化模型.粒子群算法在对动物集群活动行为观察基础上,利用群体中的个体对信息的共享使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得最优解.

双 MySQL 启动、停止脚本

5.5 启动 #!/bin/bash # author: Wang Xiaoqiang # func: Start MySQL 5.5 pid=`netstat -lnpt | awk -F '[ /]+' '/3306/ {print $7}'` [ ! -z $pid ] && echo -e "\e[1;31mMySQL 5.5 Is Running...\e[0m" && exit 0 /usr/local/mysql5/bin/mysqld_s

TransMac Win系统下制作 OS X启动盘图文教程超详细小白版

1软件安装好后把准备好的8G或者8G以上U盘插到电脑上:右键以管理员身份运行如                     <ignore_js_op> 2打开软件后右键先格式化U盘操作如下图跟着步骤走: <ignore_js_op> <ignore_js_op> 直接点OK格式化U盘如下图: <ignore_js_op> 3格式化成功后提示如下图: <ignore_js_op> 4再选中U盘右键加载镜像文件如下图: <ignore_js_op

jdk动态代理和cglib动态代理底层实现原理超详细解析(jdk动态代理篇)

代理模式是一种很常见的模式,关于底层原理网上看到很多的有关的讲解,但看了一些都觉得比较粗略,很多时候把底层代码copy下来也不大讲解,感觉不如自己详细的写上一篇.本文将以非常详细的说明来分析jdk动态代理底层的实现原理,篇幅较长,但是每个核心方法代码中每步都有说明.还请耐心阅读 1.举例 public class ProxyFactory implements InvocationHandler { private Class target; public <T>T getProxy(Clas

【优化算法】Greedy Randomized Adaptive Search算法 超详细解析,附代码实现TSP问题求解

01 概述 Greedy Randomized Adaptive Search,贪婪随机自适应搜索(GRAS),是组合优化问题中的多起点元启发式算法,在算法的每次迭代中,主要由两个阶段组成:构造(construction)和局部搜索( local search). 构造(construction)阶段主要用于生成一个可行解,而后该初始可行解会被放进局部搜索进行邻域搜索,直到找到一个局部最优解为止. 02 整体框架 如上面所说,其实整一个算法的框架相对于其他算法来说还算比较简单明了,大家可以先看以