I am building a process to kill a list of services. Sometimes, there's a service that hangs therefore I need to add an additionla peice of code to kill all instances of a service if it exists.
Signals are a way of communicating with processes. And Signal 9 is a kind of non-communicating with which the processes get stopped immediately.
Most Software implement a proper cleanup when beeing told to terminate. All that cleanup can not take place here, because SIGKILL means the processes are stopped immediately by the operating system. That can cause a lot of trouble in your application, because Junk is not cleaned up(temporary files, temporary tables, proper setting some values in database done at a clean shutdown,...). Maybe your application will not start after you killed it that way once or some more times. Maybe your applications data will be corrupted badly over time.
A better way of doing what you want is send a signal 15 ( = SIGTERM), then give the task enought time time (10-60 Seconds depending on how much your application usually needs, to avoid trouble I would suggest you rather choose the 60 seconds). If the process is still alive afterwards send a signal 2 ( = SIGINT) and wait for another 10-60 seconds. If the process is still alive afterwards, finally kill it with signal 9 (SIGKILL).
Here's one of my scripts(could be improved though), doing this:
#!/bin/bash
function trim {
arg="$*"
shopt -s extglob
arg="${arg#*( )}"
arg="${arg%*( )}"
echo "$arg"
}
function kill_soft_then_hard {
PIDS="$*"
PID_REGEX_PATTERN="^\s*("
for pid in $PIDS;do
PID_REGEX_PATTERN="$PID_REGEX_PATTERN|$pid"
done
PID_REGEX_PATTERN="$PID_REGEX_PATTERN)"
# Here's the chain of signals being sent, when the processes refuse to terminate
for SIGNAL in 15 1 3 7 9 ;do
kill -$SIGNAL $PIDS &>/dev/null
for((w=1;$w<=30;w++)) ; do
if ps ax | grep -qE $PID_REGEX_PATTERN ; then
continue
else
break 2
fi
sleep 1
done
done
}
function kill_by_pattern {
pattern="$1"
PIDS="$(ps ax | grep "$pattern" | grep -v grep | awk '{print $1}')"
PIDS="$(trim $PIDS)"
[ -n "$PIDS" ] && kill_soft_then_hard $PIDS
}
kill_by_pattern ESSSVR
The programs pgrep and pkill may be useful too.
Have a look at the manpage signal(7) for a detailed explanation of the standard signals.
No. I'm grepping the process list for multiple PIDs that may match the given pattern.
For normal use, you may just change the very last line of the script:
kill_by_pattern ESSSVR
If you like to tweak the script, the most liked improvement will be to do not wait the full 30 second period if the process is already terminated.
I recommend you to test the script in a testing environment before using it in production, since you do not know anything about my environment and vice versa for me.