#!/bin/bash #title :flushjava #description :The purpose of this cron job is to flush java running on the server by killing what currently exists and then starting up a new set #description : of java processes. #author :Joe #date :20120327 #version :1.0 #usage :/etc/cron.weekly #notes :This script is intended to be run by the system by dropping into cron.weekly (or cron.hourly, cron.daily, cron.monthly). #notes : Alternatively you can place into /etc/cron.d and run via SSH with run-parts /etc/cron.d for immediate running/testing/modification. #notes : [OTHER] Get bash_version via "echo $BASH_VERSION" and bash_full via "bash --version" #bash_version :4.1.5(1)-release #bash_full :GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu) # Define a few global variables userAcct="skippy" # User account where Hazelcast start.sh is located, and the user account to run the processes under cronSchedule="cron.weekly" # Type of system cron schedule (displayed in /var/log/flushjava.log) showInteractive=0 # Useful if you are running this yourself such as with root@server:~# run-parts /etc/cron.d. 0 = show no messages # to screen, 1 = show messages to screen. logProgress=1 # Useful if you want to log the steps this cron job completed to /var/log/flushjava.log. detectRunningJavaServer=-1 detectRunningJavaHazel=-1 cDate=`date` exCode=0 currentMsg="" progressMsgs="" # Discover Java Hazelcast process running on server currentMsg="Detecting process /usr/bin/java -cp." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$currentMsg; fi output1=`ps -C java f | grep "/usr/bin/java -cp"` set -- $output1 # Grab the process ID: output should be PID($1) TTY($2) STAT($3) TIME($4) COMMAND($5) pid1=$1 # Only flush if Java Hazelcast is running on server if [ "$pid1" != "" ]; then currentMsg="Process found with PID("$pid1"), will attempt friendly termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi # Kill the process (-SIGTERM) kill -15 $pid1 # Wait for a bit sleep 15 # See if it is still present; should not be if the application was listening for a termination signal currentMsg="Detecting if process is still active." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi look1=`ps -C java f | grep "/usr/bin/java -cp"` set -- $look1 pidHere1=$1 if [ "$pidHere1" = "$pid1" ]; then currentMsg="Process with PID("$pidHere1") still active, will attempt forced termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi # Kill the process (-SIGKILL) that is still present (send output to oblivion) kill -9 $pidHere1 >/dev/null 2>&1 # Wait for a bit sleep 15 # See if it is still present (-f to get the PPID) but a zombie process to flush from system RAM currentMsg="Detecting if zombie/artifact remains." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi zombie1=`ps -C java -f | grep "<defunct>"` set -- $zombie1 # Grab the parent process ID: output should be UID($1) PID($2) PPID($3) C($4) STIME($5) TTY($6) TIME($7) COMMAND($8) parentPid1=$3 # Kill the parent process if [ "$2" = "$pid1" ]; then currentMsg="Zombie/artifact remains PPID("$parentPid1"), will force termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi kill -9 $parentPid1 >/dev/null 2>&1 # Wait for a bit sleep 15 fi else # Make sure a artifact/zombie process was not left behind currentMsg="Detecting if zombie/artifact remains." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi artifact1=`ps -C java -f | grep "<defunct>"` set -- $artifact1 # Grab the parent process ID artifactPid1=$3 # Kill the parent process if [ "$2" = "$pid1" ]; then currentMsg="Zombie/artifact remains PPID("$artifactPid1"), will force termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi kill -9 $artifactPid1 >/dev/null 2>&1 # Wait for a bit sleep 15 fi fi fi # Discover the Java server process running on the server currentMsg="Detecting process java -server." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi output2=`ps -C java f | grep "java -server"` set -- $output2 # Grab the process ID pid2=$1 # Only flush if Java is running on server if [ "$pid2" != "" ]; then currentMsg="Process found with PID("$pid2"), will attempt friendly termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi # Kill the process kill -15 $pid2 # Wait for a bit sleep 15 # See if it is still present currentMsg="Detecting if process is still active." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi look2=`ps -C java f | grep "java -server"` set -- $look2 pidHere2=$1 if [ "$pidHere2" = "$pid2" ]; then currentMsg="Process with PID("$pidHere2") still active, will attempt forced termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi # Kill the process that is still present kill -9 $pidHere2 >/dev/null 2>&1 # Wait for a bit sleep 15 # See if it is still present but a zombie process to flush from system RAM currentMsg="Detecting if zombie/artifact remains." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi zombie2=`ps -C java -f | grep "<defunct>"` set -- $zombie2 # Grab the parent process ID parentPid2=$3 # Kill the parent process if [ "$2" = "$pid2" ]; then currentMsg="Zombie/artifact remains PPID("$parentPid2"), will force termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi kill -9 $parentPid2 >/dev/null 2>&1 # Wait for a bit sleep 15 fi else # Make sure a artifact/zombie process was not left behind currentMsg="Detecting if zombie/artifact remains." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi artifact2=`ps -C java -f | grep "<defunct>"` set -- $artifact2 # Grab the parent process ID artifactPid2=$3 # Kill the parent process if [ "$2" = "$pid2" ]; then currentMsg="Zombie/artifact remains PPID("$artifactPid2"), will force termination." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi kill -9 $artifactPid2 >/dev/null 2>&1 # Wait for a bit sleep 15 fi fi fi # Start up the "java -server" under the userAcct account # NOTE 1: server.sh spends a lot of time scanning and setting up connections. In order to allow this cron script to continue processing # (since server.sh does not exit) need to wait for a while and then send a keyboard interrupt signal (2) to return control to this cron script. # NOTE 2: Interrupts include: # SIGHUP 1 - Hangup - allows process to continue running but will exit out of this cron script # SIGINT 2 - Keyboard Interrupt - allows process to continue running as well as this cron script # SIGTERM 15 - Termination Signal - request that the process terminate itself # SIGSTOP 17, 19, 23 - stop but don't terminate the process; akin to pause # SIGKILL 9 - have the kernel terminate the process which could result in data loss and so on but guarantees it goes away # NOTE 3: Only works if running in the background (&) currentMsg="Starting process java -server." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi cd "/home/"$userAcct"/hazelcast/hazelcast-2.3.1/bin" su "$userAcct" ./server.sh& sleep 30;kill -2 $! # Make sure the "java -server" process is running currentMsg="Detecting process java -server." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi output3=`ps -C java f | grep "java -server"` set -- $output3 pid3=$1 if [ "$pid3" = "" ]; then currentMsg="Process java -server failed to start." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi detectRunningJavaServer=0 else currentMsg="Process java -server with PID("$pid3") successfully started." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi detectRunningJavaServer=1 fi # Start up the "/usr/bin/java -cp" under the userAcct account only if the "java -server" process is running # NOTE 1: Also run in the background (&) to ensure this script does not get called before the prior one has started running # NOTE 2: While this script does not "hang" like the prior one, we still need to return control to this cron script after this script runs if [ $detectRunningJavaServer = 1 ]; then currentMsg="Starting process /usr/bin/java -cp." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi cd "/home/"$userAcct su "$userAcct" ./start.sh& sleep 5; # Make sure the "/usr/bin/java -cp" process is running currentMsg="Detecting process /usr/bin/java -cp." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi output4=`ps -C java f | grep "/usr/bin/java -cp"` set -- $output4 pid4=$1 if [ "$pid4" = "" ]; then currentMsg="Process /usr/bin/java -cp failed to start." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi detectRunningJavaHazel=0 else currentMsg="Process /usr/bin/java -cp with PID("$pid4") successfully started." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi detectRunningJavaHazel=1 fi fi # If the processes are not running, log the problem, email, etcetera if [ $detectRunningJavaServer != 1 ] || [ $detectRunningJavaHazel != 1 ]; then currentMsg="A process did not start, logging failure." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi exCode=1 # NOTE 1: Common operators like . + not allowed when joining string fragments together strCompile=$cDate" ::: One or more processes could not be started by the cron job /etc/"$cronSchedule"/flushjava: " if [ $detectRunningJavaServer != 1 ]; then strCompile=$strCompile"java -server could not be started ("$detectRunningJavaServer"). " fi if [ $detectRunningJavaHazel != 1 ]; then strCompile=$strCompile"/usr/bin/java -cp could not be started ("$detectRunningJavaHazel")." fi # Save to log file currentMsg="Saving failure to log." if [ $showInteractive = 1 ]; then echo $currentMsg; fi if [ $logProgress = 1 ]; then progressMsgs=$progressMsgs" "$currentMsg; fi logFile="/var/log/flushjava.log" if [ -f $logFile ]; then # Append data to file echo $strCompile >> $logFile else # Create new file touch $logFile # Assign root as owner chown root $logFile # Assign 0644 permissions to the file chmod u+rw,g+r,o+r $logFile # Dump content into file echo $strCompile > $logFile fi fi # Save cron progress if specified if [ $logProgress = 1 ]; then progressMsgs=$cDate" [CRON PROGRESS DUMP] "$progressMsgs logFile="/var/log/flushjava.log" if [ -f $logFile ]; then # Append data to file echo $progressMsgs >> $logFile else # Create new file touch $logFile # Assign root as owner chown root $logFile # Assign 0644 permissions to the file chmod u+rw,g+r,o+r $logFile # Dump content into file echo $progressMsgs > $logFile fi fi # Exit exit $exCode