ActiveMQ 配置启动文件介绍

本文详细介绍了ActiveMQ的配置启动文件,包括配置jdk环境、配置文件如activemq.xml、jetty-realm.properties、jmx访问权限设置等。重点解析了启动脚本activemq的各个部分,如系统服务脚本头、帮助函数、启动、停止、检查运行状态等功能实现,以及如何在运行中的ActiveMQ实例上执行任务。此外,还提到了附录中关于shell脚本执行方式、ps命令的用法等知识点。

1.配置jdk环境(Linux)

一般在普通用户下的 ~/.bash_profile 或者在 /etc/profile 最后添加如下语句:

export JAVA_HOME=/opt/app/jdk1.8.0_162/
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib 
export PATH=${JAVA_HOME}/bin:$PATH

 

2.配置文件

activemq.xml

ActiveMQ的主配置文件,其中有部分配置有所修改以适应我的程序。

<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<!-- START SNIPPET: example -->
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

    <!-- Allows us to use system properties as variables in this configuration file -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <value>file:${activemq.conf}/credentials.properties</value>
        </property>
    </bean>

   <!-- Allows accessing the server log -->
    <bean id="logQuery" class="io.fabric8.insight.log.log4j.Log4jLogQuery"
          lazy-init="false" scope="singleton"
          init-method="start" destroy-method="stop">
    </bean>

    <!--
        The <broker> element is used to configure the ActiveMQ broker.
    -->


    <!-- brokerName 设置broker的名字,默认是localhost,注意在网络上必须是唯一的。
         dataDirectory 设置持久化文件目录,默认为activemq的apache-activemq-5.11.1/data目录。
    -->
    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">

        
        <destinationPolicy>
            <policyMap>
              <policyEntries>
                <!-- 这里使用通配符">",用于递归地匹配从这个名称开始的任何目的地 -->
                <policyEntry topic=">" >
                    <!-- The constantPendingMessageLimitStrategy is used to prevent
                         slow topic consumers to block producers and affect other consumers
                         by limiting the number of messages that are retained
                         For more information, see:

                         http://activemq.apache.org/slow-consumer-handling.html

                    -->
                  <pendingMessageLimitStrategy>
                    <constantPendingMessageLimitStrategy limit="1000"/>
                  </pendingMessageLimitStrategy>
                </policyEntry>
                <!-- 我自己添加的一个policyEntry(DLQ) -->
                <policyEntry queue=">" >
                  <deadLetterStrategy>
                   <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/>
                  </deadLetterStrategy>
                </policyEntry>
              </policyEntries>
            </policyMap>
        </destinationPolicy>


        <!--
            The managementContext is used to configure how ActiveMQ is exposed in
            JMX. By default, ActiveMQ uses the MBean server that is started by
            the JVM. For more information, see:

            http://activemq.apache.org/jmx.html
        -->
        <managementContext>
            <managementContext createConnector="false"/>
        </managementContext>

        <!--
            Configure message persistence for the broker. The default persistence
            mechanism is the KahaDB store (identified by the kahaDB tag).
            For more information, see:

            http://activemq.apache.org/persistence.html
        -->
	<!--
        <persistenceAdapter>
            <kahaDB directory="${activemq.data}/kahadb"/>
        </persistenceAdapter>
	-->
    <!-- 这个persistenceAdapter是我添加的,使用MySQL来持久化存储 -->
	<persistenceAdapter>
  	  <jdbcPersistenceAdapter dataSource="#MySQL-DS"/>
	</persistenceAdapter>

          <!--
            The systemUsage controls the maximum amount of space the broker will
            use before disabling caching and/or slowing down producers. For more information, see:
            http://activemq.apache.org/producer-flow-control.html
          -->
          <systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage percentOfJvmHeap="70" />
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="100 gb"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="50 gb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>

        <!--
            The transport connectors expose ActiveMQ over a given protocol to
            clients and other brokers. For more information, see:

            http://activemq.apache.org/configuring-transports.html
        -->
        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <!-- The transport connectors ActiveMQ will listen to following transportConnector -->  
            <!-- 注释掉其他transportConnector,只配置openwire,允许其他进程来访问本机的所有地址上的61616端口。以及一些链接属性的配置 -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=3000&amp;wireFormat.maxFrameSize=209715200&amp;wireFormat.maxInactivityDuration=600000"/>
            <!--
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=5000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=5000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=5000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=5000&amp;wireFormat.maxFrameSize=104857600"/>
            -->
        </transportConnectors>

        <!-- destroy the spring context on shutdown to stop jetty -->
        <shutdownHooks>
            <bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
        </shutdownHooks>

    </broker>

  <!-- 这个bean("MySQL-DS") 就是前面添加的persistenceAdapter("MySQL-DS")的具体消息持久化方式,如jdbc的参数,属性等-->
  <bean id="MySQL-DS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/activemq?relaxAutoCommit=true&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;socketTimeout=5000"/>
    <property name="username" value="mquser"/>
    <property name="password" value="Inteplay007"/>
    <!--property name="maxActive" value="350"/-->
    <property name="poolPreparedStatements" value="true"/>
  </bean>

    <!--
        Enable web consoles, REST and Ajax APIs and demos
        The web consoles requires by default login, you can disable this in the jetty.xml file

        Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details
    -->
    
    <!-- 代表从 jetty.xml文件中导入其他配置。 -->
    <import resource="jetty.xml"/>

</beans>
<!-- END SNIPPET: example -->

通配符

  • . 用于在路径中分隔名称
  • * 用于匹配路径中的任何名称
  • > 用于递归地匹配从这个名称开始的任何目的地

关于通配符详细参见:http://activemq.apache.org/wildcards.html

 

jetty-realm.properties

定义可以访问web(console,demo等)的用户密码[角色]。

一般要修改默认的密码,或者防火墙关闭8161端口禁止访问。

# Defines users that can access the web (console, demo, etc.)
# username: password [,rolename ...]
admin: admin, admin
user: user, user

 

jmx.access 和 jmx.password

配置jmx访问的账户密码

 

3.启动脚本 activemq

位于:apache-activemq-5.11.1/bin/

 

3.1 INIT INFO 系统服务脚本头

activemq通过命令 activemq start 启动之后,以系统服务的方式在后台运行。

以下是脚本的开头,这个是系统服务系统的方式

#!/bin/sh

### BEGIN INIT INFO
# Provides:          activemq
# Required-Start:    $remote_fs $network $syslog
# Required-Stop:     $remote_fs $network $syslog
# Default-Start:     3 5
# Default-Stop:      0 1 6
# Short-Description: Starts ActiveMQ
# Description:       Starts ActiveMQ Message Broker Server
### END INIT INFO

定义两个变量,分别记录命令行的所有参数和执行选项。

# ------------------------------------------------------------------------
# IMPROVED DEBUGGING (execute with bash -x)
# export PS4=' ${BASH_SOURCE}:${LINENO}(${FUNCNAME[0]}) '
#
# Backup invocation parameters
COMMANDLINE_ARGS="$@"
EXEC_OPTION=""

 

3.2 几个帮助函数

setCurrentUser()用于将当前用户赋值给CUSER变量,以便脚本里使用。

# ------------------------------------------------------------------------
# HELPERS

# a simple helper to get the current user
setCurrentUser(){
   CUSER="`whoami 2>/dev/null`"
   # Solaris hack
   if [ ! $? -eq 0 ]; then
      CUSER="`/usr/ucb/whoami 2>/dev/null`"
   fi
}

pathCanonical()用于获得规范的路径,摒除系统的差异。

# get a canonical path, macosx and slowlaris does not support radlink -f :-)
pathCanonical() {
    local dst="${1}"
    while [ -h "${dst}" ] ; do
        ls=`ls -ld "${dst}"`
        link=`expr "$ls" : '.*-> \(.*\)$'`
        if expr "$link" : '/.*' > /dev/null; then
            dst="$link"
        else
            dst="`dirname "${dst}"`/$link"
        fi
    done
    local bas="`basename "${dst}"`"
    local dir="`dirname "${dst}"`"
    if [ "$bas" != "$dir" ]; then
      dst="`pathCanonical "$dir"`/$bas"
    fi
    echo "${dst}" | sed -e 's#//#/#g' -e 's#/\./#/#g' -e 's#/[^/]*/\.\./#/#g'
}

getActiveMQHome() 用于获取ActiveMQ的安装路径。先通过pathCanonical()获取到启动脚本的bin路径,再获取到上一级的home目录。pwd的选项-P,是为了避免所有的符号链接。

# a simple helper to get the activemq installation dir
getActiveMQHome(){
  # get the real path to the binary
  local REAL_BIN="`pathCanonical $0`"
  local REAL_DIR="`dirname $REAL_BIN`/../"
  REAL_DIR="`cd $REAL_DIR && pwd -P`"
  if [ -z "$REAL_DIR" ];then
      echo 'ERROR: unable to find real installtion path fo activemq, you have to define ACTIVEMQ_HOME manually in the config' >&2
      exit 1
  fi
  echo "$REAL_DIR/"

}

 

3.3 几个帮助判断

配置MQ的安装目录,如果脚本启动之前的环境里没有定义ACTIVEMQ_HOME变量,则将getActiveMQHome函数获取到的路径赋值给它。

base目录,如果环境历里设置了ACTIVEMQ_BASE变量则用之,否则将ACTIVEMQ_HOME赋值给她。

# Active MQ installation dir
if [ -z "$ACTIVEMQ_HOME" ] ; then
  ACTIVEMQ_HOME="`getActiveMQHome`"
fi

# Active MQ base dir
if [ -z "$ACTIVEMQ_BASE" ] ; then
  ACTIVEMQ_BASE="$ACTIVEMQ_HOME"
fi

先配置用户级的classpath,脚本这里使用或者脚本外部调用。

再配置MQ的classpath,将外部lib添加到ACTIVEMQ_USER_CLASSPATH之前,合起来作为ACTIVEMQ_CLASSPATH。

# Configure user specified classpath here or externally using this variable
if [ -z "$ACTIVEMQ_USER_CLASSPATH" ] ; then
    ACTIVEMQ_USER_CLASSPATH=""
fi

# ActiveMQ Classpath configuration
ACTIVEMQ_CLASSPATH="$ACTIVEMQ_BASE/../lib/:$ACTIVEMQ_USER_CLASSPATH"

MQ配置文件目录,如果变量ACTIVEMQ_CONF未配置,且老的写法ACTIVEMQ_CONFIG_DIR也未配置,则将$ACTIVEMQ_BASE/conf赋值给它。

# Active MQ configuration directory
if [ -z "$ACTIVEMQ_CONF" ] ; then

    # For backwards compat with old variables we let ACTIVEMQ_CONFIG_DIR set ACTIVEMQ_CONF
    if [ -z "$ACTIVEMQ_CONFIG_DIR" ] ; then
        ACTIVEMQ_CONF="$ACTIVEMQ_BASE/conf"
    else
        ACTIVEMQ_CONF="$ACTIVEMQ_CONFIG_DIR"
    fi
fi

MQ可以配置一个非root权限的用户,如果ACTIVEMQ_USER变量没有指定,则不改变,默认为当前用户。

# Configure a user with non root privileges, if no user is specified do not change user
if [ -z "$ACTIVEMQ_USER" ] ; then
    ACTIVEMQ_USER=""
fi

MQ的数据目录,持久化目录,也存储了log。

如果ACTIVEMQ_DATA变量未指定,且老写法ACTIVEMQ_DATA_DIR也未指定,则将$ACTIVEMQ_BASE/data赋值给ACTIVEMQ_DATA。

# Active MQ data directory
if [ -z "$ACTIVEMQ_DATA" ] ; then

    # For backwards compat with old variables we let ACTIVEMQ_DATA_DIR set ACTIVEMQ_DATA
    if [ -z "$ACTIVEMQ_DATA_DIR" ] ; then
        ACTIVEMQ_DATA="$ACTIVEMQ_BASE/data"
    else
        ACTIVEMQ_DATA="$ACTIVEMQ_DATA_DIR"
    fi
fi

MQ的tmp目录

if [ -z "$ACTIVEMQ_TMP" ] ; then
  ACTIVEMQ_TMP="$ACTIVEMQ_BASE/tmp"
fi

如果$ACTIVEMQ_DATA目录不存在,则将当前用户保存到CUSER变量。

     如果$ACTIVEMQ_USER不为空或者$ACTIVEMQ_USER与$CUSER相同,则直接创建该目录;

     或者如果当前用户id等于0(即root的id),则需要使用指定用户$ACTIVEMQ_USER的权限来创建该目录。

if [ ! -d "$ACTIVEMQ_DATA" ]; then
   setCurrentUser
   if ( [ -z "$ACTIVEMQ_USER" ] || [ "$ACTIVEMQ_USER" = "$CUSER" ] );then
        mkdir $ACTIVEMQ_DATA
   elif [ "`id -u`" = "0" ];then
      su -c "mkdir $ACTIVEMQ_DATA" - $ACTIVEMQ_USER;
   fi
fi

MQ的PID文件路径

# Location of the pidfile
if [ -z "$ACTIVEMQ_PIDFILE" ]; then
  ACTIVEMQ_PIDFILE="$ACTIVEMQ_DATA/activemq.pid"
fi

上面的是一些基础环境的获取,下面介绍配置的加载。

 

3.4 加载配置

对于使用实例时的加载,一般没用到。我就说没有实例时,配置文件的路径ACTIVEMQ_CONFIGS有多个,分别是"/etc/default/activemq","$HOME/.activemqrc","$ACTIVEMQ_HOME/bin/env"。

# ------------------------------------------------------------------------
# LOAD CONFIGURATION

# CONFIGURATION
# For using instances
if ( basename $0 | grep "activemq-instance-" > /dev/null);then
  INST="`basename $0|sed 's/^activemq-instance-//;s/\.sh$//'`"
  ACTIVEMQ_CONFIGS="/etc/default/activemq-instance-${INST} $HOME/.activemqrc-instance-${INST}"
  echo "INFO: Using alternative activemq configuration files: $ACTIVEMQ_CONFIGS"
else
  ACTIVEMQ_CONFIGS="/etc/default/activemq $HOME/.activemqrc $ACTIVEMQ_HOME/bin/env"
fi

加载activemq配置,先将标志CONFIG_LOAD设置为no。

遍历$ACTIVEMQ_CONFIGS里面的配置,一般只有env是存在的,env是个shell脚本,可在里面修改一些配置,里面的配置将会覆盖启动脚本里获取到的配置。

( . $ACTIVEMQ_CONFIG >/dev/null 2>&1 )  执行之后,判断状态码,为0则再次执行  .  $ACTIVEMQ_CONFIG ,并将标志CONFIG_LOAD设置为yes 。关于使用点加脚本的方式执行的说明,参见附录1。

# load activemq configuration
CONFIG_LOAD="no"
for ACTIVEMQ_CONFIG in $ACTIVEMQ_CONFIGS;do
   if [ -f "$ACTIVEMQ_CONFIG" ] ; then
     ( . $ACTIVEMQ_CONFIG >/dev/null 2>&1 )
     if [ "$?" != "0" ];then
      echo "ERROR: There are syntax errors in '$ACTIVEMQ_CONFIG'"
      exit 1
     else
       echo "INFO: Loading '$ACTIVEMQ_CONFIG'"
       . $ACTIVEMQ_CONFIG
      CONFIG_LOAD="yes"
      break
     fi
   fi
done

执行上面这个程序后,在启动脚本的环境下的变量里多了如下一些变量(可通过set命令查看)

ACTIVEMQ_CONFIG=/opt/app/apache-activemq-5.11.1/bin/env
ACTIVEMQ_KILL_MAXSECONDS=30
ACTIVEMQ_OPTS='-Xms1G -Xmx1G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/login.config'
ACTIVEMQ_OPTS_MEMORY='-Xms1G -Xmx1G'
ACTIVEMQ_QUEUEMANAGERURL='--amqurl tcp://localhost:61616'
ACTIVEMQ_SSL_OPTS=
ACTIVEMQ_SUNJMX_CONTROL=
ACTIVEMQ_SUNJMX_START=' -Dcom.sun.management.jmxremote'
ACTIVEMQ_USER=
JAVACMD=/opt/app/jdk1.8.0_162/bin/java

通过标志变量CONFIG_LOAD值为yes来通知加载了默认配置。

# inform user that default configuration is loaded, no suitable configfile found
if [ "$CONFIG_LOAD" != "yes" ];then
      echo "INFO: Using default configuration";
      echo "      Configurations are loaded in the following order: $ACTIVEMQ_CONFIGS"
      echo
fi

设置变量ACTIVEMQ_OPTS

(ACTIVEMQ_OPTS和ACTIVEMQ_OPTS_MEMORY都可以在env脚本里设置)

if [ -z "$ACTIVEMQ_OPTS" ] ; then
    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS_MEMORY -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=$ACTIVEMQ_CONF/login.config"
fi

 

3.5 针对不同操作系统的适配

其他也写java项目,如tomcat的启动脚本里面也有类似的内容。

我的环境是linux系统,所以这些内容都不会执行到。

# ------------------------------------------------------------------------
# OS SPECIFIC SUPPORT

OSTYPE="unknown"

case "`uname`" in
  CYGWIN*) OSTYPE="cygwin" ;;
  Darwin*)
           OSTYPE="darwin"
           if [ -z "$JAVA_HOME" ] && [ "$JAVACMD" = "auto" ];then
             JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
           fi
           ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched
if [ "$OSTYPE" = "cygwin" ]; then
  [ -n "$ACTIVEMQ_HOME" ] &&
    ACTIVEMQ_HOME="`cygpath --unix "$ACTIVEMQ_HOME"`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`cygpath --unix "$JAVA_HOME"`"
  [ -n "$ACTIVEMQ_CLASSPATH" ] &&
    ACTIVEMQ_CLASSPATH="`cygpath --path --unix "$ACTIVEMQ_CLASSPATH"`"
fi

 

3.6 寻找java命令的路径

JAVACMD从env脚本继承而来值为"auto"。

如果JAVACMD为空或者等于"auto",则

        如果JAVA_HOME非空(我们一般在配置jdk环境的时候就指定了JAVA_HOME),则

                如果 "$JAVA_HOME/jre/sh/java" 可执行,则将其赋值给JAVACMD;否则将"$JAVA_HOME/bin/java"赋值给他。

                一般jdk里jre/bin下没有sh目录,所以一般找到的就是$JAVA_HOME/bin/java。

# Detect the location of the java binary
if [ -z "$JAVACMD" ] || [ "$JAVACMD" = "auto" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  fi
fi

如果还是没有找到java的位置,则使用which命令来查找java。如果找到了,则代表环境变量里找得到java,JAVACMD就直接使用java。

# Hm, we still do not know the location of the java binary
if [ -z "$JAVACMD" ] || [ "$JAVACMD" = "auto" ] || [ ! -x "$JAVACMD" ] ; then
    JAVACMD=`which java 2> /dev/null `
    if [ -z "$JAVACMD" ] ; then
        JAVACMD=java
    fi
fi

如果$JAVACMD 还不存在或不可执行,就报错,退出进程。

# Stop here if no java installation is defined/found
if [ ! -x "$JAVACMD" ] ; then
  echo "ERROR: Configuration variable JAVA_HOME or JAVACMD is not defined correctly."
  echo "       (JAVA_HOME='$JAVA_HOME', JAVACMD='$JAVACMD')"
  exit 1
fi

如果$JAVACMD可执行,就跳过上一个判断,向终端的标准输出打印使用的$JAVACMD。

echo "INFO: Using java '$JAVACMD'"

如果经过前面的配置,$ACTIVEMQ_BASE还是为空,则把$ACTIVEMQ_HOME赋值给它。

if [ -z "$ACTIVEMQ_BASE" ] ; then
  ACTIVEMQ_BASE="$ACTIVEMQ_HOME"
fi

如果是在windows下的cygwin环境中启动的本脚本,则在相应的变量前添加"cygpath --windows"前缀。

# For Cygwin, switch paths to Windows format before running java if [ "$OSTYPE" = "cygwin" ]; then
if [ "$OSTYPE" = "cygwin" ];then
  ACTIVEMQ_HOME="`cygpath --windows "$ACTIVEMQ_HOME"`"
  ACTIVEMQ_BASE="`cygpath --windows "$ACTIVEMQ_BASE"`"
  ACTIVEMQ_CONF="`cygpath --windows "$ACTIVEMQ_CONF"`"
  ACTIVEMQ_DATA="`cygpath --windows "$ACTIVEMQ_DATA"`"
  ACTIVEMQ_CLASSPATH=`cygpath --path --windows "$ACTIVEMQ_CLASSPATH"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`cygpath --windows "$JAVA_HOME"`"
  CYGHOME="`cygpath --windows "$HOME"`"
  ACTIVEMQ_TMP="`cygpath --windows "$ACTIVEMQ_TMP"`"
  if [ -n "$CYGHOME" ]; then
      ACTIVEMQ_CYGWIN="-Dcygwin.user.home=\"$CYGHOME\""
  fi
fi

 

3.7 设置默认cpasspath

在AMQ的安装配置目录前添加实例配置目录,以便先获取实例的相关配置。

# Set default classpath
# Add instance conf dir before AMQ install conf dir to pick up instance-specific classpath entries first
ACTIVEMQ_CLASSPATH="${ACTIVEMQ_CONF}:${ACTIVEMQ_CLASSPATH}"

如果系统是cygwin,则删除反斜杠以防止引用问题。

if [ "$OSTYPE" = "cygwin" ];then
  # remove training backslashes to prevent quoting problems
  ACTIVEMQ_CLASSPATH="`echo ${ACTIVEMQ_CLASSPATH}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_HOME="`echo ${ACTIVEMQ_HOME}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_BASE="`echo ${ACTIVEMQ_BASE}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_CONF="`echo ${ACTIVEMQ_CONF}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_DATA="`echo ${ACTIVEMQ_DATA}|sed '~s,[\\]*$,,g'`"
fi

 

3.8 功能:启动AMQ的jar文件

@ARG1 :pid文件名,如果本参数指定了,函数invokeJar()启动的java进程将在后台以服务的方式运行,并且这个文件存储着新建的进程pid。

              标准输出和错误输出都将被抑制。

@RET :出现错误则为0

注意:本函数使用了许多全局定义的变量。

-  如果$ACTIVEMQ_USER设置了,本函数就尝试使用指定的用户启动进程。

3.8.1 函数:invokeJar()

如果${ACTIVEMQ_HOME}/bin/activemq.jar 不存在则报错,存在则继续。

然后调用函数setCurrentUser设置当前用户给变量$CUSER。

如果$ACTIVEMQ_USER为空或者等于当前用户$CUSER,则添加前缀"sh -c "和后缀";";

再如果id为0,即root,就要使用指定用户的前缀"su -s /bin/sh -c "和后缀" - $ACTIVEMQ_USER",然后向终端输出提示信息,告知更改了执行用户。

然后才是执行java程序。

【条件一】

如果$TASK_TODO(本函数的第二个参数)非空并且不等于stop,则

       如果$ACTIVEMQ_OUT(继承自env脚本)为空,则赋值为"/dev/null"。(其实env里面就已经这样判断并赋值了,为什么这里还要来一遍??)

       还记得最开始的EXEC_OPTION变量吗,为空。这里以它为开头,从$DOIT_PREFIX到$DOIT_POSTFIX这一句才是真正的执行启动AMQ的jar的语句。

       然后用RET变量来保存执行结束状态。

【条件二】

再如果$TASK_TODO非空且等于stop,则

       用SPID变量来保存本函数的第一个参数${PIDFILE}的值。

       然后也是真正的意义上的启动语句。

       并用RET来保存结束状态。

【条件三】

否则

       执行并保存结束状态。

函数的最后是返回变量$RET。

我们需要注意区分上面红色字体的三个条件下的启动参数间的差异。

# Start the ActiveMQ JAR
#
#
# @ARG1 : the name of the PID-file
#         If specified, this function starts the java process in background as a daemon
#         and stores the pid of the created process in the file.
#         Output on stdout/stderr will be supressed if this parameter is specified
# @RET  : If unless 0 something went wrong
#
# Note: This function uses a lot of globally defined variables
# - if $ACTIVEMQ_USER is set, the function tries starts the java process whith the specified user
invokeJar(){
   PIDFILE="$1"
   TASK_TODO="$2"
   RET="1"

   if [ ! -f "${ACTIVEMQ_HOME}/bin/activemq.jar" ];then
    echo "ERROR: '${ACTIVEMQ_HOME}/bin/activemq.jar' does not exist, define ACTIVEMQ_HOME in the config"
    exit 1
   fi

   setCurrentUser

   if ( [ -z "$ACTIVEMQ_USER" ] || [ "$ACTIVEMQ_USER" = "$CUSER" ] );then
      DOIT_PREFIX="sh -c "
      DOIT_POSTFIX=";"
   elif [ "`id -u`" = "0" ];then
      DOIT_PREFIX="su -s /bin/sh -c "
      DOIT_POSTFIX=" - $ACTIVEMQ_USER"
      echo "INFO: changing to user '$ACTIVEMQ_USER' to invoke java"
   fi

   # Execute java binary
   if [ -n "$TASK_TODO" ] && [ "$TASK_TODO" != "stop" ];then
      if [ -z "$ACTIVEMQ_OUT" ]; then
         ACTIVEMQ_OUT="/dev/null"
      fi
      $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \
              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \
              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \
              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \
              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \
              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \
              $ACTIVEMQ_CYGWIN \
              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS >> $ACTIVEMQ_OUT 2>&1 &
              RET=\"\$?\"; APID=\"\$!\";
              echo \$APID > "${PIDFILE}";
              echo \"INFO: pidfile created : '${PIDFILE}' (pid '\$APID')\";exit \$RET" $DOIT_POSTFIX
      RET="$?"
   elif [ -n "$TASK_TODO" ] && [ "$TASK_TODO" = "stop" ];then
          SPID="`cat "${PIDFILE}"`"
          $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \
              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \
              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \
              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \
              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \
              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \
              $ACTIVEMQ_CYGWIN \
              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS --pid $SPID &
              RET=\"\$?\"; APID=\"\$!\";
              echo \$APID > "${PIDFILE}.stop"; exit \$RET" $DOIT_POSTFIX
      RET="$?"
   else
      $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \
              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \
              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \
              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \
              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \
              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \
              $ACTIVEMQ_CYGWIN \
              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS" $DOIT_POSTFIX
      RET="$?"
   fi
   return $RET
}

 

3.9 功能:检查ActiveMQ是否在运行

@RET : 0 => activemq 进程正在运行中

              1 => $ACTIVEMQ_PIDFILE中进程ID不存在了

              2 => PID文件相关错误

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE : PID文件名称(全路径)

3.9.1 函数:checkRunning()

如果$ACTIVEMQ_PIDFILE文件存在,则

        如果$ACTIVEMQ_PIDFILE文件的值为空,则报错“PID文件存在但是不包含PID”。

        将$ACTIVEMQ_PIDFILE文件的值赋值给ACTIVEMQ_PID。

        ps -p 来探测该PID的进程是否存在,并用RET来保存,$RET不为0,则本函数return 0;$RET为0,则本函数return 1。

否则

        本函数return 1 。

# Check if ActiveMQ is running
#
# @RET  : 0 => the activemq process is running
#         1 => process id in $ACTIVEMQ_PIDFILE does not exist anymore
#         2 => something is wrong with the pid file
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE : the name of the pid file


checkRunning(){
    if [ -f "$ACTIVEMQ_PIDFILE" ]; then
       if  [ -z "`cat $ACTIVEMQ_PIDFILE`" ];then
        echo "ERROR: Pidfile '$ACTIVEMQ_PIDFILE' exists but contains no pid"
        return 2
       fi
       ACTIVEMQ_PID="`cat ${ACTIVEMQ_PIDFILE}`"
       RET="`ps -p "${ACTIVEMQ_PID}"|grep java`"   #ps -p 的用法见附录2
       if [ -n "$RET" ];then
         return 0;
       else
         return 1;
       fi
    else
         return 1;
    fi
}

3.9.2 函数:checkStopRunning()

AMQ在停止的时候,会启动一个进程来停止服务,本函数就是检测这个stop进程的状态。

stop进程产生的PID文件以".stop"结尾。相关逻辑判断与checkRunning函数类似。

checkStopRunning(){
    PID_STOP="${ACTIVEMQ_PIDFILE}.stop"
    if [ -f "$PID_STOP" ]; then
       if  [ -z "`cat $PID_STOP`" ];then
        echo "ERROR: Pidfile os stop process '$PID_STOP' exists but contains no pid"
        return 2
       fi
       THEPID=`cat ${PID_STOP}`
       RET=`ps -p $THEPID|grep java`
       if [ -n "$RET" ];then
         return 0;
       else
         return 1;
       fi
    else
         return 1;
    fi
}

 

3.10 功能:检查ActiveMQ是否运行

@RET : 0 => activemq进程运行

              1 => activemq进程没有运行

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE : PID文件名称()全路径

调用checkRunning函数,判断函数结束状态,如果为0,则进程在运行,于是将文件$ACTIVEMQ_PIDFILE里保存值赋值给PID变量,并且以return 0 结束本函数。

3.10.1 函数 : invoke_status()

# Check if ActiveMQ is running
#
# @RET  : 0 => the activemq process is running
#         1 => the activemq process is not running
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE : the name of the pid file


invoke_status(){
    if ( checkRunning );then
         PID="`cat $ACTIVEMQ_PIDFILE`"
         echo "ActiveMQ is running (pid '$PID')"
         exit 0
    fi
    echo "ActiveMQ not running"
    exit 1
}

3.11 功能 : ActiveMQ如果没有运行则启动

@RET : 0 => 进程正在启动或者已经启动

              !0 => 出错

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE                : PID文件名称()全路径

- $ACTIVEMQ_OPTS                    : 附加选项

- $ACTIVEMQ_SUNJMX_START  : JMX设定的选项

- $ACTIVEMQ_SSL_OPTS            : SSL加密相关的选项

调用checkRunning函数,判断函数结束状态,如果为0,则进程在运行,并打印信息到终端。

然后使用ACTIVEMQ_OPTS添加一些选项,

调用invokeJar函数,pid文件,start参数 启动AMQ进程。

这里的start是invokeJar函数的第二个参数,也就是前面说的该函数内部的TASK_TODO,且是执行jar文件的第一个条件情况(见前面红色字体部分)

3.11.1 函数 : invoke_start()

# Start ActiveMQ if not already running
#
# @RET  : 0 => is now started, is already started
#         !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE      : the name of the pid file
# - $ACTIVEMQ_OPTS         : Additional options
# - $ACTIVEMQ_SUNJMX_START : options for JMX settings
# - $ACTIVEMQ_SSL_OPTS     : options for SSL encryption

invoke_start(){
    if ( checkRunning );then
      PID="`cat $ACTIVEMQ_PIDFILE`"
      echo "INFO: Process with pid '$PID' is already running"
      exit 0
    fi

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\""

    echo "INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details"
    invokeJar "$ACTIVEMQ_PIDFILE" start
    exit "$?"
}

3.12 功能 : 后台启动ActiveMQ(debug模式)

本函数以调试模式启动consle,方便观察输出。

@RET  :  0 => 启动

                1 => 已经启动

                !0 => 报错

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE                : PID文件名称()全路径

- $ACTIVEMQ_OPTS                    : 附加选项

- $ACTIVEMQ_SUNJMX_START  : JMX设定的选项

- $ACTIVEMQ_SSL_OPTS            : SSL加密相关的选项

调用checkRunning函数检查进程状态,没有运行才继续下去。

同样要添加一些选项到ACTIVEMQ_OPTS。

COMMANDLINE_ARGS是传递给启动脚本的,

3.12.1 函数 : invoke_console()

在前台运行AMQ,通常用于调试。

@RET  :   0 =>  was started

                 1 =>  was already started    (我去,"was started"和"was already started "怎么区分开,英语不好)

                 !0 => 出错     (我想问,上面1不也是非0吗,不属于这一类?)

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE                : PID文件名称()全路径

- $ACTIVEMQ_OPTS                    : 附加选项

- $ACTIVEMQ_SUNJMX_START  : JMX设定的选项

- $ACTIVEMQ_SSL_OPTS            : SSL加密相关的选项

在函数invoke_console中

如果 checkRunning 为真,则打印错误,告诉AMQ已经在运行,并退出函数。

ACTIVEMQ_OPTS追加一些内容。

COMMANDLINE_ARGS  删除以console开头的字段。

EXEC_OPTION赋值为"exec"。

打印一些 INFO 。

保存当前shell进程的PID到文件 $ACTIVEMQ_PIDFILE 。

以文件$ACTIVEMQ_PIDFILE作为参数执行函数invokeJar,也就是使用启动脚本的PID来最为新启动的jar进程的PID。在前面该函数的开头有说明。

使用变量 RET 记录invokeJar函数退出状态。

打印  INFO : 移除PID文件 $ACTIVEMQ_PIDFILE。

最后再以前面invokeJar函数退出状态最为本函数的退出状态。

# Start ActiveMQ in foreground (for debugging)
#
# @RET  : 0 => was started
#         1 => was already started
#         !0 => somthing went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE      : the name of the pid file
# - $ACTIVEMQ_OPTS         : Additional options
# - $ACTIVEMQ_SUNJMX_START : options for JMX settings
# - $ACTIVEMQ_SSL_OPTS     : options for SSL encryption

invoke_console(){
    if ( checkRunning );then
      echo "ERROR: ActiveMQ is already running"
      exit 1
    fi

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\""

    COMMANDLINE_ARGS="start `echo $COMMANDLINE_ARGS|sed 's,^console,,'`"
    EXEC_OPTION="exec"
    echo "INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)"
    echo "INFO: Creating pidfile $ACTIVEMQ_PIDFILE"
    echo "$$" > "$ACTIVEMQ_PIDFILE"
    invokeJar "$ACTIVEMQ_PIDFILE"
    RET="$?"
    echo "INFO: removing pidfile $ACTIVEMQ_PIDFILE"
    exit "$RET"
}

 

3.13 功能 : Kill ActiveMQ

杀死 ActiveMQ

3.13.1 函数 : invoke_kill()

kill ActiveMQ 进程。

@RET  :  0 => 成功停止

                !0 => 停止失败

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE                : PID文件名称()全路径

在函数invoke_kill中

如果 checkRunning 为真,则

        将文件${ACTIVEMQ_PIDFILE}中的PID号赋值给变量ACTIVEMQ_PID

        打印提示信息,已经发送SIGKILL信号到该PID进程。

        真正执行kill命令。"kill -KILL"与"kill -9"等价。强制杀死进程。

        记录kill命令退出状态。

        强制删除文件 ${ACTIVEMQ_PIDFILE} 。

        以kill的退出状态最为本函数的退出状态。

否则

        打印 INFO,没有运行,什么也不做。

        以0退出本函数。

# Kill ActiveMQ
# @RET    : 0 => stop was successful
#          !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE         : the name of the pid file


invoke_kill(){
    if ( checkRunning ); then
       ACTIVEMQ_PID="`cat ${ACTIVEMQ_PIDFILE}`"
       echo "INFO: sending SIGKILL to pid '$ACTIVEMQ_PID'"
       kill -KILL $ACTIVEMQ_PID
       RET="$?"
       rm -f "${ACTIVEMQ_PIDFILE}"
       return $RET
    fi
    echo "INFO: not running, nothing to do"
    return 0
}

 

3.14 功能 : Stop ActiveMQ

停止 ActiveMQ

3.14.1 函数 : invoke_stop()

停止 ActiveMQ 进程。(这个stop和前面的kill,不都是停止么?)

@RET     :   0 => 停止成功

                    !0 => 停止失败

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_PIDFILE                      : PID文件名称()全路径

- $ACTIVEMQ_KILL_MAXSECONDS : 一个秒为单位的数字,是在jmx接口发送shutdonw信号后,broker停止所耗费的时间。

在函数invoke_stop中

首先把RET置为1。

如果 checkRunning 为真,则

        opts后面追加ssl的opts。

        COMMANDLINE_ARGS后面追加ACTIVEMQ_SUNJMX_CONTROL。

        文件$ACTIVEMQ_PIDFILE里的PID号赋值给变量ACTIVEMQ_PID。

        以两个参数"$ACTIVEMQ_PIDFILE" "stop" 来执行函数 invokeJar。

        保存invokeJar执行退出状态。

        把FOUND置为0,i置为0.

        打印 INFO, 等待至少 $ACTIVEMQ_KILL_MAXSECONDS秒的常规进程停止操作。

        当  $i 小于或等于 $ACTIVEMQ_KILL_MAXSECONDS 时,则

               如果 checkStopRunning 不为真,则

                        如果 checkRunning 不为真,则

                                打印完成 并把 FOUND置为1。

                        否则

                                break退出循环。

       

               如果 checkRunning 为真,则

                        休眠1秒,并打印一个"."号。

               否则

                       打印TERMINATED,并把FOUND置为1。

 

               变量i加1。

        <while循环结束>

        如果 FOUND不为1,则

               打印 INFO,常规停止不成功,发送SIGKILL信号到jar进程。

                执行函数invoke_kill。 (这里我们可以看出,invoke_stop函数是完整的停止操作,而invoke_kill函数是常规停止操作失败而强制杀死进程的擦做)

               保存invoke_kill函数的退出状态。

再如果 "$ACTIVEMQ_PIDFILE" 文件存在,则

        打印错误,没有或者过期PID号在文件 "$ACTIVEMQ_PIDFILE"里。

        打印INFO,移除文件"$ACTIVEMQ_PIDFILE"。

否则,

        打印 ActiveMQ没有运行。

        以0退出本函数。

 

删除文件"$ACTIVEMQ_PIDFILE"和"$ACTIVEMQ_DATA/stop.pid"。

最后用前面的RET来退出本函数。

# Stop ActiveMQ
# @RET    : 0 => stop was successful
#          !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE         : the name of the pid file
# - $ACTIVEMQ_KILL_MAXSECONDS : the number of seconds to wait for termination of broker after sending
#                              shutdown signal by jmx interface

invoke_stop(){
    RET="1"
    if ( checkRunning );then
       ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"
       COMMANDLINE_ARGS="$COMMANDLINE_ARGS $ACTIVEMQ_SUNJMX_CONTROL"

       ACTIVEMQ_PID="`cat $ACTIVEMQ_PIDFILE`"

       invokeJar "$ACTIVEMQ_PIDFILE" "stop"
       RET="$?"

       FOUND="0"
       i=0
       echo "INFO: Waiting at least $ACTIVEMQ_KILL_MAXSECONDS seconds for regular process termination of pid '$ACTIVEMQ_PID' : "
       while [ "$i" -le "$ACTIVEMQ_KILL_MAXSECONDS" ]; do
         if [ ! checkStopRunning ];then
            if [ ! checkRunning ]; then
               echo " FINISHED"
               FOUND="1"
            fi
            break
         fi

         if (checkRunning);then
            sleep 1
            printf  "."
         else
            echo " TERMINATED"
            FOUND="1"
            break
         fi
         i="`expr $i + 1`"
       done
       if [ "$FOUND" -ne "1" ];then
         echo
         echo "INFO: Regular shutdown not successful,  sending SIGKILL to process"
         invoke_kill
         RET="$?"
       fi
    elif [ -f "$ACTIVEMQ_PIDFILE" ];then
       echo "ERROR: No or outdated process id in '$ACTIVEMQ_PIDFILE'"
       echo
       echo "INFO: Removing $ACTIVEMQ_PIDFILE"
    else
       echo "ActiveMQ not running"
       exit 0
    fi
    rm -f "$ACTIVEMQ_PIDFILE" >/dev/null 2>&1
    rm -f "$ACTIVEMQ_DATA/stop.pid" >/dev/null 2>&1
    exit $RET
}

 

3.15 功能 : 在一个运行中的ActiveMQ实例上调用一个任务

 

3.15.1 函数 : invoke_task()

在一个运行的AMQ实例上调用一个任务

$1    :   "checkforrunning",如果activemq没有运行则不调用任务,否则要调用任务。

@RET   :  0 => 成功

                 !1 => 错误

注意 : 本函数使用了全局定义的变量

- $ACTIVEMQ_QUEUEMANAGERURL      : 队列管理器的url

- $ACTIVEMQ_OPTS                                  : 附加选项

- $ACTIVEMQ_SUNJMX_START                : JMX设定的选项

- $ACTIVEMQ_SSL_OPTS                          : SSL加密相关的选项

在函数invoke_task里

定义一个局部变量CHECKRUNNING来保存传递给本函数的第一个参数。

在opts后追加ssl的opts。

如果CHECKRUNNING等于"checkforrunning",则

        如果 checkRunning不为真,则

                打印  “AMQ没有运行”并退出函数。

再如果 CHECKRUNNING 等于 "checkfornotrunning" ,则

        如果 checkRunning 为真,则

                打印 “AMQ 正在运行” 并 退出函数。

调用所有java二进制程序中的任务。

如果参数 $1 等于 "browse" 或  $ACTIVEMQ_QUEUEMANAGERURL 不为空,则

        将 $COMMANDLINE_ARGS 里以browse开头的字段删除,同变量$ACTIVEMQ_QUEUEMANAGERURL 一起赋值给变量 COMMANDLINE_ARGS ;

再如果 $1 等于 "query" 或 $ACTIVEMQ_QUEUEMANAGERURL 不为空,则

        将 $COMMANDLINE_ARGS 里以query开头的字段删除,同变量 $ACTIVEMQ_SUNJMX_CONTROL一起赋值给变量 COMMANDLINE_ARGS  ;

否则

        $ACTIVEMQ_SUNJMX_CONTROL 直接追加到  $COMMANDLINE_ARGS。

执行函数invokeJar,并用"$ACTIVEMQ_PIDFILE"作为参数。

实用变量RET记录上面函数的退出状态,并最为本函数的退出状态。

# Invoke a task on a running ActiveMQ instance
#
# $1    : "checkforrunning", do not invoke the task if activemq is not
#         active
#         <other>, invoke task always
# @RET  : 0 => successful
#         !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_QUEUEMANAGERURL : The url of the queuemanager
# - $ACTIVEMQ_OPTS            : Additional options
# - $ACTIVEMQ_SUNJMX_START    : options for JMX settings
# - $ACTIVEMQ_SSL_OPTS        : options for SSL encryption
invoke_task(){

    local CHECKRUNNING="$1"
    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"

    if [ "$CHECKRUNNING" = "checkforrunning" ];then
       if ( ! checkRunning );then
         echo "Activemq is not running."
         exit 1
       fi
    elif [ "$CHECKRUNNING" = "checkfornotrunning" ];then
      if ( checkRunning );then
         echo "Activemq is running."
         exit 1
       fi
    fi

    # call task in java binary
    if [ "$1" = "browse" ] && [ -n "$ACTIVEMQ_QUEUEMANAGERURL" ];then
       COMMANDLINE_ARGS="$ACTIVEMQ_QUEUEMANAGERURL `echo $COMMANDLINE_ARGS|sed 's,^browse,,'`"
    elif [ "$1" = "query" ]  && [ -n "$ACTIVEMQ_QUEUEMANAGERURL" ];then
       COMMANDLINE_ARGS="$ACTIVEMQ_SUNJMX_CONTROL `echo $COMMANDLINE_ARGS|sed 's,^query,,'`"
    else
       COMMANDLINE_ARGS="$COMMANDLINE_ARGS $ACTIVEMQ_SUNJMX_CONTROL"
    fi
    invokeJar "$ACTIVEMQ_PIDFILE"
    RET="$?"
    exit $RET
}

 

3.16 函数 : show_help()

脚本的帮助函数

show_help() {
  invokeJar "$ACTIVEMQ_PIDFILE"|sed "s,Usage: Main,Usage: $0,"
  cat << EOF
Tasks provided by the sysv init script:
    kill            - terminate instance in a drastic way by sending SIGKILL
    restart         - stop running instance (if there is one), start new instance
    console         - start broker in foreground, useful for debugging purposes
    status          - check if activemq process is running

Configuration of this script:
    The configuration of this script is read from the following files:
    $ACTIVEMQ_CONFIGS
    This script searches for the files in the listed order and reads the first available file.
    Modify $ACTIVEMQ_BASE/bin/env or create a copy of that file on a suitable location.
    To use additional configurations for running multiple instances on the same operating system
    rename or symlink script to a name matching to activemq-instance-<INSTANCENAME>.
    This changes the configuration location to /etc/default/activemq-instance-<INSTANCENAME> and
    \$HOME/.activemqrc-instance-<INSTANCENAME>.
EOF
  exit 1
}

 

3.17 主逻辑

主逻辑部分,主要是根据输入的脚本参数,调用相应的前面的函数,以完成相关的功能。

# ------------------------------------------------------------------------
# MAIN

# show help
if [ -z "$1" ];then
 show_help
fi

case "$1" in
  status)
    invoke_status
    ;;
  restart)
    if ( checkRunning );then
      $0 stop
      echo
    fi
    $0 start
    $0 status
    ;;
  start)
    invoke_start
    ;;
  console)
    invoke_console
    exit $?
    ;;
  stop)
    invoke_stop
    exit $?
    ;;
  kill)
    invoke_kill
    exit $?
    ;;
  *)
    invoke_task
    exit $?
esac

 

附录

附录1 : source script | . scritpt |  script 三种方式执行shell脚本的区别

前两种方式 :source script 和 . scritpt 执行脚本效果一样,在当前shell里执行后,script里面的变量在当前shell生效,而不会产生子shell,不会只有在子shell中script的变量才有效。

第三种方式:直接运行脚本,则脚本中的变量只在子shell中有效,在当前shell中无效。

详细说明,请参见文章《在Linux中用source,dot(.)和直接用脚本文件名执行shell脚本的区别》。

附录2 : ps -p 的用法

[inteplay@localhost data]$ ps -p 1174
  PID TTY          TIME CMD
[inteplay@localhost data]$ ps -p 11749
  PID TTY          TIME CMD
11749 ?        2-17:37:04 java

-p 用来指定进程pid,如果没有该进程则只显示列头,且通过java运行的进程,CMD似乎都显示的是java。

 

附录3 : activemq启动脚本完整内容

#!/bin/sh

### BEGIN INIT INFO
# Provides:          activemq
# Required-Start:    $remote_fs $network $syslog
# Required-Stop:     $remote_fs $network $syslog
# Default-Start:     3 5
# Default-Stop:      0 1 6
# Short-Description: Starts ActiveMQ
# Description:       Starts ActiveMQ Message Broker Server
### END INIT INFO

# ------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------------------------------------------------------------
#
# This script controls standalone Apache ActiveMQ service processes.
# To ensure compatibility to macosx and cygwin we do not utilize
# lsb standard infrastructure for controlling daemons like
# "start-stop-daemon".
#
# See also http://activemq.apache.org/activemq-command-line-tools-reference.html
# for additional commandline arguments
#
# System variables for this script, like ACTIVEMQ_OPTS and ACTIVEMQ_OPTS_MEMORY,
# can be configured in 'env' script located in this directory.
#
# For more information on configuring the script, see http://activemq.apache.org/unix-shell-script.html
#
#
# Authors:
# Marc Schoechlin <ms@256bit.org>

# ------------------------------------------------------------------------
# IMPROVED DEBUGGING (execute with bash -x)
# export PS4=' ${BASH_SOURCE}:${LINENO}(${FUNCNAME[0]}) '
#
# Backup invocation parameters
COMMANDLINE_ARGS="$@"
EXEC_OPTION=""

# ------------------------------------------------------------------------
# HELPERS

# a simple helper to get the current user
setCurrentUser(){
   CUSER="`whoami 2>/dev/null`"
   # Solaris hack
   if [ ! $? -eq 0 ]; then
      CUSER="`/usr/ucb/whoami 2>/dev/null`"
   fi
}

# get a canonical path, macosx and slowlaris does not support radlink -f :-)
pathCanonical() {
    local dst="${1}"
    while [ -h "${dst}" ] ; do
        ls=`ls -ld "${dst}"`
        link=`expr "$ls" : '.*-> \(.*\)$'`
        if expr "$link" : '/.*' > /dev/null; then
            dst="$link"
        else
            dst="`dirname "${dst}"`/$link"
        fi
    done
    local bas="`basename "${dst}"`"
    local dir="`dirname "${dst}"`"
    if [ "$bas" != "$dir" ]; then
      dst="`pathCanonical "$dir"`/$bas"
    fi
    echo "${dst}" | sed -e 's#//#/#g' -e 's#/\./#/#g' -e 's#/[^/]*/\.\./#/#g'
}


# a simple helper to get the activemq installation dir
getActiveMQHome(){
  # get the real path to the binary
  local REAL_BIN="`pathCanonical $0`"
  local REAL_DIR="`dirname $REAL_BIN`/../"
  REAL_DIR="`cd $REAL_DIR && pwd -P`"
  if [ -z "$REAL_DIR" ];then
      echo 'ERROR: unable to find real installtion path fo activemq, you have to define ACTIVEMQ_HOME manually in the config' >&2
      exit 1
  fi
  echo "$REAL_DIR/"

}

# Active MQ installation dir
if [ -z "$ACTIVEMQ_HOME" ] ; then
  ACTIVEMQ_HOME="`getActiveMQHome`"
fi

# Active MQ base dir
if [ -z "$ACTIVEMQ_BASE" ] ; then
  ACTIVEMQ_BASE="$ACTIVEMQ_HOME"
fi

# Configure user specified classpath here or externally using this variable
if [ -z "$ACTIVEMQ_USER_CLASSPATH" ] ; then
    ACTIVEMQ_USER_CLASSPATH=""
fi

# ActiveMQ Classpath configuration
ACTIVEMQ_CLASSPATH="$ACTIVEMQ_BASE/../lib/:$ACTIVEMQ_USER_CLASSPATH"

# Active MQ configuration directory
if [ -z "$ACTIVEMQ_CONF" ] ; then

    # For backwards compat with old variables we let ACTIVEMQ_CONFIG_DIR set ACTIVEMQ_CONF
    if [ -z "$ACTIVEMQ_CONFIG_DIR" ] ; then
        ACTIVEMQ_CONF="$ACTIVEMQ_BASE/conf"
    else
        ACTIVEMQ_CONF="$ACTIVEMQ_CONFIG_DIR"
    fi
fi

# Configure a user with non root privileges, if no user is specified do not change user
if [ -z "$ACTIVEMQ_USER" ] ; then
    ACTIVEMQ_USER=""
fi

# Active MQ data directory
if [ -z "$ACTIVEMQ_DATA" ] ; then

    # For backwards compat with old variables we let ACTIVEMQ_DATA_DIR set ACTIVEMQ_DATA
    if [ -z "$ACTIVEMQ_DATA_DIR" ] ; then
        ACTIVEMQ_DATA="$ACTIVEMQ_BASE/data"
    else
        ACTIVEMQ_DATA="$ACTIVEMQ_DATA_DIR"
    fi
fi

if [ -z "$ACTIVEMQ_TMP" ] ; then
  ACTIVEMQ_TMP="$ACTIVEMQ_BASE/tmp"
fi

if [ ! -d "$ACTIVEMQ_DATA" ]; then
   setCurrentUser
   if ( [ -z "$ACTIVEMQ_USER" ] || [ "$ACTIVEMQ_USER" = "$CUSER" ] );then
        mkdir $ACTIVEMQ_DATA
   elif [ "`id -u`" = "0" ];then
      su -c "mkdir $ACTIVEMQ_DATA" - $ACTIVEMQ_USER;
   fi
fi

# Location of the pidfile
if [ -z "$ACTIVEMQ_PIDFILE" ]; then
  ACTIVEMQ_PIDFILE="$ACTIVEMQ_DATA/activemq.pid"
fi


# ------------------------------------------------------------------------
# LOAD CONFIGURATION

# CONFIGURATION
# For using instances
if ( basename $0 | grep "activemq-instance-" > /dev/null);then
  INST="`basename $0|sed 's/^activemq-instance-//;s/\.sh$//'`"
  ACTIVEMQ_CONFIGS="/etc/default/activemq-instance-${INST} $HOME/.activemqrc-instance-${INST}"
  echo "INFO: Using alternative activemq configuration files: $ACTIVEMQ_CONFIGS"
else
  ACTIVEMQ_CONFIGS="/etc/default/activemq $HOME/.activemqrc $ACTIVEMQ_HOME/bin/env"
fi

# load activemq configuration
CONFIG_LOAD="no"
for ACTIVEMQ_CONFIG in $ACTIVEMQ_CONFIGS;do
   if [ -f "$ACTIVEMQ_CONFIG" ] ; then
     ( . $ACTIVEMQ_CONFIG >/dev/null 2>&1 )
     if [ "$?" != "0" ];then
      echo "ERROR: There are syntax errors in '$ACTIVEMQ_CONFIG'"
      exit 1
     else
       echo "INFO: Loading '$ACTIVEMQ_CONFIG'"
       . $ACTIVEMQ_CONFIG
      CONFIG_LOAD="yes"
      break
     fi
   fi
done

# inform user that default configuration is loaded, no suitable configfile found
if [ "$CONFIG_LOAD" != "yes" ];then
      echo "INFO: Using default configuration";
      echo "      Configurations are loaded in the following order: $ACTIVEMQ_CONFIGS"
      echo
fi

if [ -z "$ACTIVEMQ_OPTS" ] ; then
    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS_MEMORY -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=$ACTIVEMQ_CONF/login.config"
fi




# ------------------------------------------------------------------------
# OS SPECIFIC SUPPORT

OSTYPE="unknown"

case "`uname`" in
  CYGWIN*) OSTYPE="cygwin" ;;
  Darwin*)
           OSTYPE="darwin"
           if [ -z "$JAVA_HOME" ] && [ "$JAVACMD" = "auto" ];then
             JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
           fi
           ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched
if [ "$OSTYPE" = "cygwin" ]; then
  [ -n "$ACTIVEMQ_HOME" ] &&
    ACTIVEMQ_HOME="`cygpath --unix "$ACTIVEMQ_HOME"`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`cygpath --unix "$JAVA_HOME"`"
  [ -n "$ACTIVEMQ_CLASSPATH" ] &&
    ACTIVEMQ_CLASSPATH="`cygpath --path --unix "$ACTIVEMQ_CLASSPATH"`"
fi

# Detect the location of the java binary
if [ -z "$JAVACMD" ] || [ "$JAVACMD" = "auto" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  fi
fi

# Hm, we still do not know the location of the java binary
if [ -z "$JAVACMD" ] || [ "$JAVACMD" = "auto" ] || [ ! -x "$JAVACMD" ] ; then
    JAVACMD=`which java 2> /dev/null `
    if [ -z "$JAVACMD" ] ; then
        JAVACMD=java
    fi
fi
# Stop here if no java installation is defined/found
if [ ! -x "$JAVACMD" ] ; then
  echo "ERROR: Configuration variable JAVA_HOME or JAVACMD is not defined correctly."
  echo "       (JAVA_HOME='$JAVA_HOME', JAVACMD='$JAVACMD')"
  exit 1
fi

echo "INFO: Using java '$JAVACMD'"

if [ -z "$ACTIVEMQ_BASE" ] ; then
  ACTIVEMQ_BASE="$ACTIVEMQ_HOME"
fi

# For Cygwin, switch paths to Windows format before running java if [ "$OSTYPE" = "cygwin" ]; then
if [ "$OSTYPE" = "cygwin" ];then
  ACTIVEMQ_HOME="`cygpath --windows "$ACTIVEMQ_HOME"`"
  ACTIVEMQ_BASE="`cygpath --windows "$ACTIVEMQ_BASE"`"
  ACTIVEMQ_CONF="`cygpath --windows "$ACTIVEMQ_CONF"`"
  ACTIVEMQ_DATA="`cygpath --windows "$ACTIVEMQ_DATA"`"
  ACTIVEMQ_CLASSPATH=`cygpath --path --windows "$ACTIVEMQ_CLASSPATH"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`cygpath --windows "$JAVA_HOME"`"
  CYGHOME="`cygpath --windows "$HOME"`"
  ACTIVEMQ_TMP="`cygpath --windows "$ACTIVEMQ_TMP"`"
  if [ -n "$CYGHOME" ]; then
      ACTIVEMQ_CYGWIN="-Dcygwin.user.home=\"$CYGHOME\""
  fi
fi

# Set default classpath
# Add instance conf dir before AMQ install conf dir to pick up instance-specific classpath entries first
ACTIVEMQ_CLASSPATH="${ACTIVEMQ_CONF}:${ACTIVEMQ_CLASSPATH}"

if [ "$OSTYPE" = "cygwin" ];then
  # remove training backslashes to prevent quoting problems
  ACTIVEMQ_CLASSPATH="`echo ${ACTIVEMQ_CLASSPATH}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_HOME="`echo ${ACTIVEMQ_HOME}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_BASE="`echo ${ACTIVEMQ_BASE}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_CONF="`echo ${ACTIVEMQ_CONF}|sed '~s,[\\]*$,,g'`"
  ACTIVEMQ_DATA="`echo ${ACTIVEMQ_DATA}|sed '~s,[\\]*$,,g'`"
fi

# Start the ActiveMQ JAR
#
#
# @ARG1 : the name of the PID-file
#         If specified, this function starts the java process in background as a daemon
#         and stores the pid of the created process in the file.
#         Output on stdout/stderr will be supressed if this parameter is specified
# @RET  : If unless 0 something went wrong
#
# Note: This function uses a lot of globally defined variables
# - if $ACTIVEMQ_USER is set, the function tries starts the java process whith the specified
#   user
invokeJar(){
   PIDFILE="$1"
   TASK_TODO="$2"
   RET="1"

   if [ ! -f "${ACTIVEMQ_HOME}/bin/activemq.jar" ];then
    echo "ERROR: '${ACTIVEMQ_HOME}/bin/activemq.jar' does not exist, define ACTIVEMQ_HOME in the config"
    exit 1
   fi

   setCurrentUser

   if ( [ -z "$ACTIVEMQ_USER" ] || [ "$ACTIVEMQ_USER" = "$CUSER" ] );then
      DOIT_PREFIX="sh -c "
      DOIT_POSTFIX=";"
   elif [ "`id -u`" = "0" ];then
      DOIT_PREFIX="su -s /bin/sh -c "
      DOIT_POSTFIX=" - $ACTIVEMQ_USER"
      echo "INFO: changing to user '$ACTIVEMQ_USER' to invoke java"
   fi

   # Execute java binary
   if [ -n "$TASK_TODO" ] && [ "$TASK_TODO" != "stop" ];then
      if [ -z "$ACTIVEMQ_OUT" ]; then
         ACTIVEMQ_OUT="/dev/null"
      fi
      $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \
              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \
              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \
              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \
              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \
              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \
              $ACTIVEMQ_CYGWIN \
              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS >> $ACTIVEMQ_OUT 2>&1 &
              RET=\"\$?\"; APID=\"\$!\";
              echo \$APID > "${PIDFILE}";
              echo \"INFO: pidfile created : '${PIDFILE}' (pid '\$APID')\";exit \$RET" $DOIT_POSTFIX
      RET="$?"
   elif [ -n "$TASK_TODO" ] && [ "$TASK_TODO" = "stop" ];then
          SPID="`cat "${PIDFILE}"`"
          $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \
              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \
              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \
              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \
              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \
              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \
              $ACTIVEMQ_CYGWIN \
              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS --pid $SPID &
              RET=\"\$?\"; APID=\"\$!\";
              echo \$APID > "${PIDFILE}.stop"; exit \$RET" $DOIT_POSTFIX
      RET="$?"
   else
      $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \
              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \
              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \
              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \
              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \
              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \
              $ACTIVEMQ_CYGWIN \
              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS" $DOIT_POSTFIX
      RET="$?"
   fi
   return $RET
}

# Check if ActiveMQ is running
#
# @RET  : 0 => the activemq process is running
#         1 => process id in $ACTIVEMQ_PIDFILE does not exist anymore
#         2 => something is wrong with the pid file
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE : the name of the pid file


checkRunning(){
    if [ -f "$ACTIVEMQ_PIDFILE" ]; then
       if  [ -z "`cat $ACTIVEMQ_PIDFILE`" ];then
        echo "ERROR: Pidfile '$ACTIVEMQ_PIDFILE' exists but contains no pid"
        return 2
       fi
       ACTIVEMQ_PID="`cat ${ACTIVEMQ_PIDFILE}`"
       RET="`ps -p "${ACTIVEMQ_PID}"|grep java`"
       if [ -n "$RET" ];then
         return 0;
       else
         return 1;
       fi
    else
         return 1;
    fi
}

checkStopRunning(){
    PID_STOP="${ACTIVEMQ_PIDFILE}.stop"
    if [ -f "$PID_STOP" ]; then
       if  [ -z "`cat $PID_STOP`" ];then
        echo "ERROR: Pidfile os stop process '$PID_STOP' exists but contains no pid"
        return 2
       fi
       THEPID=`cat ${PID_STOP}`
       RET=`ps -p $THEPID|grep java`
       if [ -n "$RET" ];then
         return 0;
       else
         return 1;
       fi
    else
         return 1;
    fi
}

# Check if ActiveMQ is running
#
# @RET  : 0 => the activemq process is running
#         1 => the activemq process is not running
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE : the name of the pid file


invoke_status(){
    if ( checkRunning );then
         PID="`cat $ACTIVEMQ_PIDFILE`"
         echo "ActiveMQ is running (pid '$PID')"
         exit 0
    fi
    echo "ActiveMQ not running"
    exit 1
}

# Start ActiveMQ if not already running
#
# @RET  : 0 => is now started, is already started
#         !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE      : the name of the pid file
# - $ACTIVEMQ_OPTS         : Additional options
# - $ACTIVEMQ_SUNJMX_START : options for JMX settings
# - $ACTIVEMQ_SSL_OPTS     : options for SSL encryption

invoke_start(){
    if ( checkRunning );then
      PID="`cat $ACTIVEMQ_PIDFILE`"
      echo "INFO: Process with pid '$PID' is already running"
      exit 0
    fi

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\""

    echo "INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details"
    invokeJar "$ACTIVEMQ_PIDFILE" start
    exit "$?"
}

# Start ActiveMQ in foreground (for debugging)
#
# @RET  : 0 => was started
#         1 => was already started
#         !0 => somthing went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE      : the name of the pid file
# - $ACTIVEMQ_OPTS         : Additional options
# - $ACTIVEMQ_SUNJMX_START : options for JMX settings
# - $ACTIVEMQ_SSL_OPTS     : options for SSL encryption

invoke_console(){
    if ( checkRunning );then
      echo "ERROR: ActiveMQ is already running"
      exit 1
    fi

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\""

    COMMANDLINE_ARGS="start `echo $COMMANDLINE_ARGS|sed 's,^console,,'`"
    EXEC_OPTION="exec"
    echo "INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)"
    echo "INFO: Creating pidfile $ACTIVEMQ_PIDFILE"
    echo "$$" > "$ACTIVEMQ_PIDFILE"
    invokeJar "$ACTIVEMQ_PIDFILE"
    RET="$?"
    echo "INFO: removing pidfile $ACTIVEMQ_PIDFILE"
    exit "$RET"
}


# Kill ActiveMQ
# @RET    : 0 => stop was successful
#          !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE         : the name of the pid file


invoke_kill(){
    if ( checkRunning ); then
       ACTIVEMQ_PID="`cat ${ACTIVEMQ_PIDFILE}`"
       echo "INFO: sending SIGKILL to pid '$ACTIVEMQ_PID'"
       kill -KILL $ACTIVEMQ_PID
       RET="$?"
       rm -f "${ACTIVEMQ_PIDFILE}"
       return $RET
    fi
    echo "INFO: not running, nothing to do"
    return 0
}


# Stop ActiveMQ
# @RET    : 0 => stop was successful
#          !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_PIDFILE         : the name of the pid file
# - $ACTIVEMQ_KILL_MAXSECONDS : the number of seconds to wait for termination of broker after sending
#                              shutdown signal by jmx interface

invoke_stop(){
    RET="1"
    if ( checkRunning );then
       ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"
       COMMANDLINE_ARGS="$COMMANDLINE_ARGS $ACTIVEMQ_SUNJMX_CONTROL"

       ACTIVEMQ_PID="`cat $ACTIVEMQ_PIDFILE`"

       invokeJar "$ACTIVEMQ_PIDFILE" "stop"
       RET="$?"

       FOUND="0"
       i=0
       echo "INFO: Waiting at least $ACTIVEMQ_KILL_MAXSECONDS seconds for regular process termination of pid '$ACTIVEMQ_PID' : "
       while [ "$i" -le "$ACTIVEMQ_KILL_MAXSECONDS" ]; do
         if [ ! checkStopRunning ];then
            if [ ! checkRunning ]; then
               echo " FINISHED"
               FOUND="1"
            fi
            break
         fi

         if (checkRunning);then
            sleep 1
            printf  "."
         else
            echo " TERMINATED"
            FOUND="1"
            break
         fi
         i="`expr $i + 1`"
       done
       if [ "$FOUND" -ne "1" ];then
         echo
         echo "INFO: Regular shutdown not successful,  sending SIGKILL to process"
         invoke_kill
         RET="$?"
       fi
    elif [ -f "$ACTIVEMQ_PIDFILE" ];then
       echo "ERROR: No or outdated process id in '$ACTIVEMQ_PIDFILE'"
       echo
       echo "INFO: Removing $ACTIVEMQ_PIDFILE"
    else
       echo "ActiveMQ not running"
       exit 0
    fi
    rm -f "$ACTIVEMQ_PIDFILE" >/dev/null 2>&1
    rm -f "$ACTIVEMQ_DATA/stop.pid" >/dev/null 2>&1
    exit $RET
}

# Invoke a task on a running ActiveMQ instance
#
# $1    : "checkforrunning", do not invoke the task if activemq is not
#         active
#         <other>, invoke task always
# @RET  : 0 => successful
#         !0 => something went wrong
#
# Note: This function uses globally defined variables
# - $ACTIVEMQ_QUEUEMANAGERURL : The url of the queuemanager
# - $ACTIVEMQ_OPTS            : Additional options
# - $ACTIVEMQ_SUNJMX_START    : options for JMX settings
# - $ACTIVEMQ_SSL_OPTS        : options for SSL encryption
invoke_task(){

    local CHECKRUNNING="$1"
    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"

    if [ "$CHECKRUNNING" = "checkforrunning" ];then
       if ( ! checkRunning );then
         echo "Activemq is not running."
         exit 1
       fi
    elif [ "$CHECKRUNNING" = "checkfornotrunning" ];then
      if ( checkRunning );then
         echo "Activemq is running."
         exit 1
       fi
    fi

    # call task in java binary
    if [ "$1" = "browse" ] && [ -n "$ACTIVEMQ_QUEUEMANAGERURL" ];then
       COMMANDLINE_ARGS="$ACTIVEMQ_QUEUEMANAGERURL `echo $COMMANDLINE_ARGS|sed 's,^browse,,'`"
    elif [ "$1" = "query" ]  && [ -n "$ACTIVEMQ_QUEUEMANAGERURL" ];then
       COMMANDLINE_ARGS="$ACTIVEMQ_SUNJMX_CONTROL `echo $COMMANDLINE_ARGS|sed 's,^query,,'`"
    else
       COMMANDLINE_ARGS="$COMMANDLINE_ARGS $ACTIVEMQ_SUNJMX_CONTROL"
    fi
    invokeJar "$ACTIVEMQ_PIDFILE"
    RET="$?"
    exit $RET
}

show_help() {
  invokeJar "$ACTIVEMQ_PIDFILE"|sed "s,Usage: Main,Usage: $0,"
  cat << EOF
Tasks provided by the sysv init script:
    kill            - terminate instance in a drastic way by sending SIGKILL
    restart         - stop running instance (if there is one), start new instance
    console         - start broker in foreground, useful for debugging purposes
    status          - check if activemq process is running

Configuration of this script:
    The configuration of this script is read from the following files:
    $ACTIVEMQ_CONFIGS
    This script searches for the files in the listed order and reads the first available file.
    Modify $ACTIVEMQ_BASE/bin/env or create a copy of that file on a suitable location.
    To use additional configurations for running multiple instances on the same operating system
    rename or symlink script to a name matching to activemq-instance-<INSTANCENAME>.
    This changes the configuration location to /etc/default/activemq-instance-<INSTANCENAME> and
    \$HOME/.activemqrc-instance-<INSTANCENAME>.
EOF
  exit 1
}

# ------------------------------------------------------------------------
# MAIN

# show help
if [ -z "$1" ];then
 show_help
fi

case "$1" in
  status)
    invoke_status
    ;;
  restart)
    if ( checkRunning );then
      $0 stop
      echo
    fi
    $0 start
    $0 status
    ;;
  start)
    invoke_start
    ;;
  console)
    invoke_console
    exit $?
    ;;
  stop)
    invoke_stop
    exit $?
    ;;
  kill)
    invoke_kill
    exit $?
    ;;
  *)
    invoke_task
    exit $?
esac

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值