I fully agree with eSelix's analysis.
There are two methods I've used in service scripts, to solve the problem (of stopping a service reliably).
First looks up the PIDs using
ps -C 3proxy -o pid= , and kills only those:
Code:
CMDNAME=3proxy
DELAY=50
pids=`ps -C $CMDNAME -o pid=`
[ -n "$pids" ] && kill -TERM $pids
while [ $DELAY -gt 0 ] && [ -n "`ps -C $CMDNAME -o pid=`" ]; do
sleep .1
DELAY=$((DELAY - 1))
done
pids=`ps -C $CMDNAME -o pid=`
[ -n "$pids" ] && kill -KILL $pids
This works quite well for services that do not create worker processes. The above will first send a TERM signal, then wait up to five seconds (50 deciseconds), and if the processes still exist, it will send a KILL signal. For slow-terminating services I recommend a much longer limit. Half a minute is okay, if the service may have to save a lot of files before exiting.
This procedure lets the service catch the TERM signal, do whatever cleanup it sees necessary, and then exit, by its own volition. The KILL signal will forcibly terminate the process immediately (unless it is blocked in some kernel call).
The other method is the more typical one. The service processes save the main PID in a pid file, usually
/var/run/name.pid . (I do not know if 3proxy creates a pid file or not, and I'm too lazy to find out. Sorry.)
The service script should check if that file exists. If not, the service is not running. If the file specifies a PID that is no longer running (or runs a different binary), then the service has crashed. Only if the PID is still running (and has the proper name, since PIDs can be reused after a while), the service is still up. For example, to stop the service, you might use
Code:
CMDNAME=3proxy
PIDFILE=/var/run/$CMDNAME.pid
DELAY=50
pid=`cat "$PIDFILE" 2>/dev/null`
if [ -n "$pid" ]; then
if [ "`ps -o comm= $pid`" = "$CMDNAME" ]; then
# Ask process to terminate
kill -TERM $pid
while [ $DELAY -gt 0 ] && [ "`ps -o comm= $pid`" = "$CMDNAME" ]; do
sleep .1
DELAY=$((DELAY - 1))
done
if [ "`ps -o comm= $pid`" = "$CMDNAME" ]; then
# Forcibly terminate process
kill -KILL $pid
else
# Process terminated peacefully
fi
else
# Process has already crashed or died
fi
else
# Not running
fi
While it is possible for the service script to
guess the PID of the main process it started, it is not reliable. For example, if the service daemonizes itself, it will acquire a new PID. Thus, I do not recommend trying to create a PID file for services that do not create one themselves; for those, I just use the first method.
I hope this helps,