本周刚好研究了一下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