分析啟動指令碼zkServer.sh
阿新 • • 發佈:2019-01-07
# use POSIX interface, symlink is followed automatically ZOOBIN="${BASH_SOURCE-$0}" ZOOBIN="$(dirname "${ZOOBIN}")" ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)" # 這裡會先配置一些必要的環境變數 if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then . "$ZOOBINDIR"/../libexec/zkEnv.sh else . "$ZOOBINDIR"/zkEnv.sh fi #此處配置JMX,預設是開啟的,支援本地連線,如果遠端連線,需要單獨配置 # See the following page for extensive details on setting # up the JVM to accept JMX remote management: # http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html # by default we allow local JMX connections if [ "x$JMXLOCALONLY" = "x" ] then JMXLOCALONLY=false fi if [ "x$JMXDISABLE" = "x" ] || [ "$JMXDISABLE" = 'false' ] then #執行這裡 echo "ZooKeeper JMX enabled by default" >&2 if [ "x$JMXPORT" = "x" ] then # for some reason these two options are necessary on jdk6 on Ubuntu # accord to the docs they are not necessary, but otw jconsole cannot # do a local attach #配置遠端連線,修改ZOOMAIN變數 ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMain" else if [ "x$JMXAUTH" = "x" ] then JMXAUTH=false fi if [ "x$JMXSSL" = "x" ] then JMXSSL=false fi if [ "x$JMXLOG4J" = "x" ] then JMXLOG4J=true fi echo "ZooKeeper remote JMX Port set to $JMXPORT" >&2 echo "ZooKeeper remote JMX authenticate set to $JMXAUTH" >&2 echo "ZooKeeper remote JMX ssl set to $JMXSSL" >&2 echo "ZooKeeper remote JMX log4j set to $JMXLOG4J" >&2 ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=$JMXPORT -Dcom.sun.management.jmxremote.authenticate=$JMXAUTH -Dcom.sun.management.jmxremote.ssl=$JMXSSL -Dzookeeper.jmx.log4j.disable=$JMXLOG4J org.apache.zookeeper.server.quorum.QuorumPeerMain" fi else echo "JMX disabled by user request" >&2 ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain" fi if [ "x$SERVER_JVMFLAGS" != "x" ] then JVMFLAGS="$SERVER_JVMFLAGS $JVMFLAGS" fi if [ "x$2" != "x" ] then ZOOCFG="$ZOOCFGDIR/$2" fi # if we give a more complicated path to the config, don't screw around in $ZOOCFGDIR if [ "x$(dirname "$ZOOCFG")" != "x$ZOOCFGDIR" ] then ZOOCFG="$2" fi if $cygwin then ZOOCFG=`cygpath -wp "$ZOOCFG"` # cygwin has a "kill" in the shell itself, gets confused KILL=/bin/kill else KILL=kill fi echo "Using config: $ZOOCFG" >&2 case "$OSTYPE" in *solaris*) GREP=/usr/xpg4/bin/grep ;; *) GREP=grep ;; esac ZOO_DATADIR="$($GREP "^[[:space:]]*dataDir" "$ZOOCFG" | sed -e 's/.*=//')" ZOO_DATADIR="$(echo -e "${ZOO_DATADIR}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" ZOO_DATALOGDIR="$($GREP "^[[:space:]]*dataLogDir" "$ZOOCFG" | sed -e 's/.*=//')" # iff autocreate is turned off and the datadirs don't exist fail # immediately as we can't create the PID file, etc..., anyway. if [ -n "$ZOO_DATADIR_AUTOCREATE_DISABLE" ]; then if [ ! -d "$ZOO_DATADIR/version-2" ]; then echo "ZooKeeper data directory is missing at $ZOO_DATADIR fix the path or run initialize" exit 1 fi if [ -n "$ZOO_DATALOGDIR" ] && [ ! -d "$ZOO_DATALOGDIR/version-2" ]; then echo "ZooKeeper txnlog directory is missing at $ZOO_DATALOGDIR fix the path or run initialize" exit 1 fi ZOO_DATADIR_AUTOCREATE="-Dzookeeper.datadir.autocreate=false" fi # 在類linux系統上,當zookeeper啟動時,會建立一個用於儲存程序id的zookeeper_server.pid檔案(在資料目錄下),每次執行start、stop、restart命令時都會檢查這個命令來判斷zookeeper的啟動狀態,而前臺啟動命令start-foreground不會檢查這個檔案,所以 start-foreground 和其他命令不是一個系列,最好不混用。 # windows的zkServer.cmd 沒有這個 程序檔案 的操作 if [ -z "$ZOOPIDFILE" ]; then if [ ! -d "$ZOO_DATADIR" ]; then mkdir -p "$ZOO_DATADIR" fi ZOOPIDFILE="$ZOO_DATADIR/zookeeper_server.pid" else # ensure it exists, otw stop will fail mkdir -p "$(dirname "$ZOOPIDFILE")" fi if [ ! -w "$ZOO_LOG_DIR" ] ; then mkdir -p "$ZOO_LOG_DIR" fi ZOO_LOG_FILE=zookeeper-$USER-server-$HOSTNAME.log _ZOO_DAEMON_OUT="$ZOO_LOG_DIR/zookeeper-$USER-server-$HOSTNAME.out" case $1 in start) echo -n "Starting zookeeper ... " if [ -f "$ZOOPIDFILE" ]; then if kill -0 `cat "$ZOOPIDFILE"` > /dev/null 2>&1; then # 如果zookeeper_server.pid中儲存的程序id代表的程序存在(kill -0 pid),說明zookeeper已經啟動了,無需再次啟動,指令碼退出執行 echo $command already running as process `cat "$ZOOPIDFILE"`. exit 1 fi fi nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \ "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \ -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null & if [ $? -eq 0 ] # 如果上面的啟動命令返回 0,說明執行成功,zookeeper啟動了,就要把 程序id 寫到zookeeper_server.pid檔案中 then case "$OSTYPE" in *solaris*) /bin/echo "${!}\\c" > "$ZOOPIDFILE" ;; *) /bin/echo -n $! > "$ZOOPIDFILE" ;; esac if [ $? -eq 0 ]; then sleep 1 pid=$(cat "${ZOOPIDFILE}") if ps -p "${pid}" > /dev/null 2>&1; then echo STARTED else echo FAILED TO START exit 1 fi else echo FAILED TO WRITE PID exit 1 fi else echo SERVER DID NOT START exit 1 fi ;; # 前臺啟動命令 start-foreground) ZOO_CMD=(exec "$JAVA") if [ "${ZOO_NOEXEC}" != "" ]; then ZOO_CMD=("$JAVA") fi "${ZOO_CMD[@]}" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \ "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \ -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" ;; # 列印啟動命令 print-cmd) echo "\"$JAVA\" $ZOO_DATADIR_AUTOCREATE -Dzookeeper.log.dir=\"${ZOO_LOG_DIR}\" \ -Dzookeeper.log.file=\"${ZOO_LOG_FILE}\" -Dzookeeper.root.logger=\"${ZOO_LOG4J_PROP}\" \ -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \ -cp \"$CLASSPATH\" $JVMFLAGS $ZOOMAIN \"$ZOOCFG\" > \"$_ZOO_DAEMON_OUT\" 2>&1 < /dev/null" ;; # 停止服務:會判斷zookeeper_server.pid檔案是否存在,如果不存在說明zookeeper沒有執行 stop) echo -n "Stopping zookeeper ... " if [ ! -f "$ZOOPIDFILE" ] then echo "no zookeeper to stop (could not find file $ZOOPIDFILE)" else # 停止服務就是執行兩條命令: # 第一條kill pid,注意沒帶訊號變數,他會讓程序清理善後工作,而不是直接殺死程序; # 第二條rm zookeeper_server.pid,刪除程序檔案,也就是說zookeeper 訪問沒有啟動的時候,是沒有這個檔案的 $KILL $(cat "$ZOOPIDFILE") rm "$ZOOPIDFILE" echo STOPPED fi exit 0 ;; # 重啟服務:執行stop,等三秒,執行start restart) shift "$0" stop ${@} sleep 3 "$0" start ${@} ;; # 查詢狀態 status) # -q is necessary on some versions of linux where nc returns too quickly, and no stat result is output clientPortAddress=`$GREP "^[[:space:]]*clientPortAddress[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'` if ! [ $clientPortAddress ] then clientPortAddress="localhost" fi clientPort=`$GREP "^[[:space:]]*clientPort[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'` if ! [[ "$clientPort" =~ ^[0-9]+$ ]] then dataDir=`$GREP "^[[:space:]]*dataDir" "$ZOOCFG" | sed -e 's/.*=//'` myid=`cat "$dataDir/myid"` if ! [[ "$myid" =~ ^[0-9]+$ ]] ; then echo "clientPort not found and myid could not be determined. Terminating." exit 1 fi clientPortAndAddress=`$GREP "^[[:space:]]*server.$myid=.*;.*" "$ZOOCFG" | sed -e 's/.*=//' | sed -e 's/.*;//'` if [ ! "$clientPortAndAddress" ] ; then echo "Client port not found in static config file. Looking in dynamic config file." dynamicConfigFile=`$GREP "^[[:space:]]*dynamicConfigFile" "$ZOOCFG" | sed -e 's/.*=//'` clientPortAndAddress=`$GREP "^[[:space:]]*server.$myid=.*;.*" "$dynamicConfigFile" | sed -e 's/.*=//' | sed -e 's/.*;//'` fi if [ ! "$clientPortAndAddress" ] ; then echo "Client port not found. Terminating." exit 1 fi if [[ "$clientPortAndAddress" =~ ^.*:[0-9]+ ]] ; then clientPortAddress=`echo "$clientPortAndAddress" | sed -e 's/:.*//'` fi clientPort=`echo "$clientPortAndAddress" | sed -e 's/.*://'` if [ ! "$clientPort" ] ; then echo "Client port not found. Terminating." exit 1 fi fi echo "Client port found: $clientPort. Client address: $clientPortAddress." # 這裡會向 FourLetterWordMain 傳送 srvr命令,從返回結果中 找到包含Mode的行,最終顯示 該節點是leader還是follower STAT=`"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.log.file=${ZOO_LOG_FILE}" \ -cp "$CLASSPATH" $JVMFLAGS org.apache.zookeeper.client.FourLetterWordMain \ $clientPortAddress $clientPort srvr 2> /dev/null \ | $GREP Mode` if [ "x$STAT" = "x" ] then echo "Error contacting service. It is probably not running." exit 1 else echo $STAT exit 0 fi ;; # 對於不認識的命令,列印幫助資訊 *) echo "Usage: $0 [--config <conf-dir>] {start|start-foreground|stop|restart|status|print-cmd}" >&2 esac