tags:

views:

718

answers:

1

I have a shutdown script for Oracle in /etc/init.d dir on "stop" command it does:

su oracle -c "lsnrctl stop >/dev/null"
su oracle -c "sqlplus sys/passwd as sysdba @/usr/local/PLATEX/scripts/orastop.sql >/dev/null"

.. The problem is when lsnrctl or sqlplus are unresponsive - in this case this "stop" script just never ends and server cant shutdown. The only way - is to "kill - 9 " that.

I'd like to rewrite script so that after 5min (for example) if command is not finished - it should be terminated. How I can achieve this? Could you give me an example? I'm under Linux RHEL 5.1 + bash.

Thanks in advance!

+6  A: 

If able to use 3rd-party tools, I'd leverage one of the 3rd-party, pre-written helpers you can call from your script (doalarm and timeout are both mentioned by the BashFAQ entry on the subject).

If writing such a thing myself without using such tools, I'd probably do something like the following:

function try_proper_shutdown() {
  su oracle -c "lsnrctl stop >/dev/null"
  su oracle -c "sqlplus sys/passwd as sysdba @/usr/local/PLATEX/scripts/orastop.sql >/dev/null"
}

function resort_to_harsh_shutdown() {
  for progname in ora_this ora_that ; do
    killall -9 $progname
  done
  # also need to do a bunch of cleanup with ipcs/ipcrm here
}

# here's where we start the proper shutdown approach in the background
try_proper_shutdown &
child_pid=$!

# rather than keeping a counter, we check against the actual clock each cycle
# this prevents the script from running too long if it gets delayed somewhere
# other than sleep (or if the sleep commands don't actually sleep only the
# requested time -- they don't guarantee that they will).
end_time=$(( $(date '+%s') + (60 * 5) ))
while (( $(date '+%s') < end_time )); do
  if kill -0 $child_pid 2>/dev/null; then
    exit 0
  fi
  sleep 1
done

# okay, we timed out; stop the background process that's trying to shut down nicely
# (note that alone, this won't necessarily kill its children, just the subshell we
# forked off) and then make things happen.    
kill $child_pid
resort_to_harsh_shutdown
Charles Duffy
AFAIR we could use WAITPID in bash? And what about waitpid + WHOHANG option in while-loop that measure time that past since exec and terminates then? (I think instead of "if [[ ! -e /proc/$child_pid ]] ; then" construction?)
zmische
You recall incorrectly; bash's wait construct accepts a pid as an argument, but nothing else (no timeout, so you lose much of the power of the actual waitpid syscall).
Charles Duffy
...but yes, if we could do that, it would be *much* less evil. :)
Charles Duffy
Updated to remove the /proc/$child_pid reference.
Charles Duffy
I looked through my past projects and found, that I'd used waitpid in PERL when forking childs for multithreading of the script. So you were right - no waitpid with params in bash!
zmische