azkaban-aplcache

Issue #957 - fixes to azkaban-solo start & shunit2 unit tests

3/30/2017 9:05:04 PM

Details

diff --git a/azkaban-common/src/main/bash/util.sh b/azkaban-common/src/main/bash/util.sh
index c817e28..aca53c3 100755
--- a/azkaban-common/src/main/bash/util.sh
+++ b/azkaban-common/src/main/bash/util.sh
@@ -1,53 +1,56 @@
 #!/usr/bin/env bash
 # Common utils
-set -o nounset
+set -o nounset   # exit the script if you try to use an uninitialised variable
+set -o errexit   # exit the script if any statement returns a non-true return value
 
-
-# If process is still running then abort start up
-function abort_if_process_already_running {
-  installdir="$1"
-  pidfile="${installdir}/currentpid"
-  if [ -f ${pidfile} ]; then
-    pid=`cat ${pidfile}`
-    ps -p ${pid} 2>&1 1>nul && echo "Process already running [pid: ${pid}]. Aborting." && exit 1
-  fi
+#---
+# is_process_running: Checks if a process is running
+# args:               Process ID of running proccess
+# returns:            returns 0 if process is running, 1 if not found
+#---
+function is_process_running {
+  local  pid=$1
+  kill -0 $pid > /dev/null 2>&1 #exit code ($?) is 0 if pid is running, 1 if not running
+  local  status=$?              #because we are returning exit code, can use with if & no [ bracket 
+  return $status
 }
 
-# kill the process with retry
-# return 0 if kill succeeds or no process to kill,
-#        1 if kill fails
+#---
+# kill_process_with_retry: Checks and attempts to kill the running process
+# args:                    PID, process name, number of kill attempts
+# returns:                 returns 0 if kill succeds or nothing to kill, 1 if kill fails
+# exception:               If passed a non-existant pid, function will forcefully exit 
+#---
 function kill_process_with_retry {
-   pid="$1"
-   pname="$2"
-   maxattempt="$3"
+   local pid="$1"
+   local pname="$2"
+   local maxattempt="$3"
+   local sleeptime=5
 
-   if [[ -z $pid ]]; then
-     echo "pid doesn't exist, shutdown completed"
-     return 0
+   if ! is_process_running $pid ; then 
+     echo "ERROR: process name ${pname} with pid: ${pid} not found"
+     exit 1
    fi
 
    for try in $(seq 1 $maxattempt); do
-     if [[ ! -z $pid ]]; then
       echo "Killing $pname. [pid: $pid], attempt: $try"
       kill ${pid}
       sleep 5
-      if [[ -n "$(ps -p $pid -o pid=)" ]]; then
+      if is_process_running $pid; then
         echo "$pname is not dead [pid: $pid]"
-        if [[ $try -lt $maxattempt ]]; then
-          echo "sleeping for a few seconds before retry"
-          sleep 10
-        fi
+        echo "sleeping for $sleeptime seconds before retry"
+        sleep $sleeptime
       else
         echo "shutdown succeeded"
         return 0
       fi
-     fi
-    done
+   done
 
    echo "Error: unable to kill process for $maxattempt attempt(s), killing the process with -9"
    kill -9 $pid
-   sleep 5
-   if [[ -n "$(ps -p $pid -o pid=)" ]]; then
+   sleep $sleeptime
+
+   if is_process_running $pid; then
       echo "$pname is not dead even after kill -9 [pid: $pid]"
       return 1
    else
@@ -55,3 +58,4 @@ function kill_process_with_retry {
     return 0
    fi
 }
+
diff --git a/azkaban-common/src/test/bash/test_util.shunit2 b/azkaban-common/src/test/bash/test_util.shunit2
new file mode 100755
index 0000000..4db057c
--- /dev/null
+++ b/azkaban-common/src/test/bash/test_util.shunit2
@@ -0,0 +1,19 @@
+#!/usr/bin/env shunit2
+# Make sure to "brew install shunit2" or use your favorite package manager to install
+# before running tests
+
+function oneTimeSetUp() {
+  source ../../main/bash/util.sh
+}
+
+function test_is_process_running() {
+  is_process_running $PPID
+  assertEquals "$?" "0"
+}
+
+function test_kill_process_with_retry() {
+  sleep 600 &                                          #create test process to kill
+  kill_process_with_retry $! sleep 3  2>&1 >/dev/null  #$! is pid for sleep process, sleep name, 3 times to loop
+  assertEquals "$?" "0"                                #$? is exit code of function kill_process_with_retry
+}
+
diff --git a/azkaban-solo-server/src/main/bash/azkaban-solo-start.sh b/azkaban-solo-server/src/main/bash/azkaban-solo-start.sh
index 895a3bc..6bd5207 100755
--- a/azkaban-solo-server/src/main/bash/azkaban-solo-start.sh
+++ b/azkaban-solo-server/src/main/bash/azkaban-solo-start.sh
@@ -1,45 +1,63 @@
 #!/bin/bash
 # This script starts the solo server
+set -o nounset   # exit the script if you try to use an uninitialised variable
+set -o errexit   # exit the script if any statement returns a non-true return value
+
 source "$(dirname $0)/util.sh"
 
-installdir=$(dirname $0)/..
-abort_if_process_already_running ${installdir}
+installdir="$(dirname $0)/.."
+currentpidfile="${installdir}/currentpid"
+
+if [[ -f "$currentpidfile" ]] ; then
+  if is_process_running $(<$currentpidfile) ; then
+    echo "Process already running [pid: $(<$currentpidfile)]. Aborting"
+    exit 1
+  fi
+fi
 
 # Specifies location of azkaban.properties, log4j.properties files
 # Change if necessary
-conf=${installdir}/conf
+conf="${installdir}/conf"
 
 if [[ -z "${tmpdir:-}" ]]; then
-  tmpdir=/tmp
+  tmpdir="/tmp"
 fi
 
-CLASSPATH=${CLASSPATH:-}:${installdir}/lib/*:${installdir}/extlib/*
+CLASSPATH="${CLASSPATH:-}:${installdir}/lib/*:${installdir}/extlib/*"
+
+HADOOP_HOME=${HADOOP_HOME:""}  # needed for set -o nounset aove
 
 if [ "$HADOOP_HOME" != "" ]; then
   echo "Using Hadoop from $HADOOP_HOME"
-  CLASSPATH=${CLASSPATH}:${HADOOP_HOME}/conf:${HADOOP_HOME}/*
+  CLASSPATH="${CLASSPATH}:${HADOOP_HOME}/conf:${HADOOP_HOME}/*"
   JAVA_LIB_PATH="-Djava.library.path=$HADOOP_HOME/lib/native/Linux-amd64-64"
 else
   echo "Error: HADOOP_HOME is not set. Hadoop job types will not run properly."
 fi
 
+HIVE_HOME=${HIVE_HOME:""}  # Needed for set -o nounset above
 if [ "$HIVE_HOME" != "" ]; then
   echo "Using Hive from $HIVE_HOME"
-  CLASSPATH=${CLASSPATH}:${HIVE_HOME}/conf:${HIVE_HOME}/lib/*
+  CLASSPATH="${CLASSPATH}:${HIVE_HOME}/conf:${HIVE_HOME}/lib/*"
 fi
 
+CLASSPATH=${CLASSPATH:""}  # Needed for set -o nounset above
 echo "CLASSPATH: ${CLASSPATH}";
 
-executorport=`cat ${conf}/azkaban.properties | grep executor.port | cut -d = -f 2`
-serverpath=`pwd`
+executorport=$(grep executor.port "${conf}/azkaban.properties" | cut -d = -f 2)
+serverpath=$(pwd)
+
+AZKABAN_OPTS=" -Xmx512M -server -Djava.io.tmpdir=$tmpdir -Dexecutorport=${executorport} \
+    -Dserverpath=${serverpath} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
 
-# Set the log4j configuration file
-if [ -f ${conf}/log4j.properties ]; then
-  AZKABAN_OPTS="$AZKABAN_OPTS -Dlog4j.configuration=file:$conf/log4j.properties"
+if [[ -f "${conf}/log4j.properties" ]]; then
+  # Set the log4j configuration file
+  AZKABAN_OPTS="${AZKABAN_OPTS:- } -Dlog4j.configuration=file:${conf}/log4j.properties \
+      -Dlog4j.log.dir=${installdir}/logs"
 fi
-AZKABAN_OPTS="$AZKABAN_OPTS -Xmx3G -server -Djava.io.tmpdir=$tmpdir -Dexecutorport=$executorport -Dserverpath=$serverpath -Dlog4j.log.dir=$installdir/logs"
 
 java ${AZKABAN_OPTS} -cp ${CLASSPATH} azkaban.soloserver.AzkabanSingleServer -conf ${conf} $@ &
 
-echo $! > ${installdir}/currentpid
+echo $! > $currentpidfile
+