init-script failing because of /etc/rc.d/init.d/functions

I encountered a problem on one of our database servers.

OS: CentOS 5.5 final
Kernel: 2.6.18-238.5.1.el5.028stab085.2 (OpenVZ kernel)

We wrote some DB-Start/Stop-scripts ("/db2/admin/scripts_dba/start_services.ksh" and ".../stop_services.ksh") to start the database instances. (Database instances are started with their own user, "dbwlpiopr" in this case.)

The scripts worked fine and i wrote an init-script to automate the process and used "chkconfig" to create the service:

#!/bin/sh
#
# chkconfig: - 95 02
# description: Starts and stops Oracle Services for dbwlpiopr
#

declare  PROG=oradb_dbwlpiopr
declare  RUNAS=dbwlpiopr
declare  STOP_SCRIPT=/db2/admin/scripts_dba/stop_services.ksh
declare  START_SCRIPT=/db2/admin/scripts_dba/start_services.ksh

if [ $UID -ne 0 ] ; then
     exit 127
fi

. /etc/rc.d/init.d/functions



start()
{
local -i RETVAL=0

action "Starting Oracle services for $RUNAS: " \
       "/bin/su -c $START_SCRIPT &> /dev/null - $RUNAS"
RETVAL=$?

if [ "$RETVAL" = 0 ] ; then 
     touch /var/lock/subsys/$PROG
fi

return $RETVAL
}



stop()
{
local -i RETVAL=0

action "Stopping Oracle services for $RUNAS: " \
       "/bin/su -c '$STOP_SCRIPT &> /dev/null' - $RUNAS"
RETVAL=$?

if [ "$RETVAL" = 0 ] ; then
     rm -f /var/lock/subsys/$PROG
fi

return $RETVAL
}




# main()

case "$1" in
     start)
          start
          ;;

     stop)
          stop
          ;;

     restart)
          stop
          start
          ;;

     *)
          echo $"Usage: $0 {start|stop|restart}"
          exit 1
          ;;

esac

exit 0

I tried the command

/bin/su -c '/db2/admin/scripts_dba/stop_services.ksh &> /dev/null' - dbwlpiopr

from command line and this worked fine too. Still, the command came back with an error:

# service oradb_dbwlpiopr start
Starting Oracle services for dbwlpiopr:  /etc/rc.d/init.d/functions: line 500: su -c '/db2/admin/scripts_dba/start_services.ksh &> /dev/null' dbwlpiopr: No such file or directory

After some debugging i found the following:

The culprit is the function "action()" in the sourced-in file "/etc/rc.d/init.d/functions", which starts around line 500. The relevant line looks like this:

action() {
[....]
"$@" && success $"$STRING" || failure $"$STRING"
[....]

There the line from the first script marked as "START_SCRIPT" (or "STOP_SCRIPT") should get executed - and in principle, it is. The problem is that the string which should be executed is quoted too much - the system doesn't try to execute "/bin/su" with some parameters, but the command completely - of course there is no file named "/bin/su -c ....".

I eliminated the problem changing the line in action() by preceding it with "eval":

action() {
[....]
eval "$@" && success $"$STRING" || failure $"$STRING"
[....]

but i feel a bit uneasy about the cure maybe being worse than the curse. I do not light-heartedly change the system itself and obviously people have written init-scripts successfully before my "invention" too.

Any suggestions?

bakunin

Just an idea: since the shell doesn't differentiate between a command and a function, move the whole line to a function, and let action() execute that.