Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using perl in /etc/init.d ?

Status
Not open for further replies.

forrie

MIS
Mar 6, 2009
91
US
I'm not able to get a native perl script to run under RHEL 5.x in the /etc/init.d section.

Specifically, we're trying to get certain information logged when the system shuts down.

(yes, it's checked in with chkconfig)

What I suspect I must do is wrap the init.d script in /bin/sh then have it call the bash script during shutdown.

I'm just trying to confirm this limitation... can someone comment?


Thanks.
 
I'm not aware of such a limitation under RHEL. Under some other Unix flavours the init scripts are run explicitly using sh, but not usually under Linux.

Is the shebang line (the first line of the script prefixed with #!) correct for the location of perl on your system?

Is it executable?

Has chkconfig created all the expected symlinks? Try ls -l /etc/rc?.d/*scriptname.

Does the logging depend on another service (such as syslog) that may have already been shut down when it runs?

Annihilannic.
 
The shebang is correct and the file is executable.

I can get the script to run when the system starts up, but I want it to be executed when the system shuts down, too.

I added chkconfig --levels 2345 to it, do I need more for the shutdown to work?


Thank you.
 
I just wrote a simple dummy script with stop and start functions and (as far as I know) put it in chkconfig correctly, and it runs only when the system starts.

It's set to:

# chkconfig: 2345 12 88
# description:

the links seem correct (chkconfig does this).

I have a "restart" function in there, too, which works correctly when I do a /sbin/service restart, it will stop (log a string) and start (log a string).

Just not at system shutdown. And this is with no perl, just basic shell scripting.

 
I tried a different version of this script, where I increased (or lowered?) the priority to 1 and included a dummy /var/log/subsys creation (and removal) in the script. No go.

The links to the script are present and in the correct rc.* directories.

I'm stumped.


 
I believe it's because of this:

Code:
...

# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K* ; do
        check_runlevel "$i" || continue

        [red]# Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/K??}
        [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] \
                || continue[/red]

        # Bring the subsystem down.
        if LC_ALL=C egrep -q "^..*init.d/functions" $i ; then
                $i stop
        else
                action $"Stopping $subsys: " $i stop
        fi
done

...

So you just need to add some code to create the lock files, this test worked for me:

Code:
#!/bin/bash
#
# chkconfig: 2345 13 87 
# description: a test

logger -p daemon.notice "testscript invoked with parameters: $@"

case "$1" in
        start)
                touch /var/lock/subsys/testscript
                ;;
        stop)
                rm -f /var/lock/subsys/testscript
                ;;
        status)
                if [[ -f /var/lock/subsys/testscript ]]
                then
                        echo "testscript service is 'running'"
                else
                        echo "testscript service is 'stopped'"
                fi
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|condrestart|status}"
                exit 1
esac

Annihilannic.
 
Let me post snippet from my script, as I believe I did this:

For sake of simplicity I fell back to /bin/sh scripting to test this.


binary="/path/to/script.sh"

start() {
echo -n "Starting mytest: "
$binary
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/mytest
}

stop() {
echo -n "Shutting down mytest: "
$binary
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
rm -f /var/lock/subsys/mytest
fi
}




I assume the shell will expand $binary for the full path of the script and execute it. The sheband and permissions are correct.

So I want the script to be RUN at shutdown, too.... as it collects and logs data (or it will).

Eventually that simple script which I'm trying to get work will be a perl script that will collect and log other data.

However, our version of perl lives in /usr/local/bin (not /usr/bin) -- but i doubt the system is unmounting at this point ?



Thanks!

 
Can you please post all of your script rather than just snippets... it could be elsewhere that we're missing something. Please use [ignore]
Code:
 ...
[/ignore] tags around any code you post to make it look pretty and readable.

Also can you post the output of the ls -l command I mentioned earlier, just to double-check?

You shouldn't need to echo starting or shutting down messages, because /etc/rc dose that for you - unless you're going to follow Red Hat's semantics and import the /etc/init.d/functions and so-on. If so, use one of the existing system scripts as a template.

Have you checked whether the lock file is being correctly created and/or removed when you start and stop the service manually?

Annihilannic.
 
Forgot some things... yes, $binary should be expanded and run. And /usr/local/bin should be fine, filesystems aren't unmounted until just before the system is halted.

Annihilannic.
 
I wonder if there is an issue because there is no *.pid file being created (doesn't apply here). From the documentation, it should just run whatever commands you request in there when the system shuts down.

Here is the simple script (sorry for not using the code brackets):

Code:
#!/bin/bash
#
# mytest 
#
# chkconfig: 012345 12 02
# description: some script

# Source function library.
. /etc/init.d/functions

binary="/tmp/mytest"

[ -x $binary ] || exit 0

RETVAL=0

start() {
    echo -n "Starting mytest: "
    /usr/local/bin/perl /tmp/mytest
    RETVAL=$?
    PID=$!
    echo
    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/mytest

    # echo $PID > /var/run/mytest.pid
}

stop() {
    echo -n "Shutting down mytest: "
    /usr/local/bin/perl /tmp/mytest
    RETVAL=$?
    echo
    if [ $RETVAL -eq 0 ]; then
        rm -f /var/lock/subsys/mytest
    fi
}

restart() {
    echo -n "Restarting mytest: "
    stop
    sleep 2
    start
}

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

exit 0


Obviously the restart isn't necessary, but I put it in there to test. I get the results I want (script executed, data written) if I restart it when the system is live. But when it shuts down, the script is not executed.

This is very puzzling!

I just used one of the standard scripts as a template, so the echo and whatever is just there for no reason.


thanks...
 
I think this may be your problem:

Code:
# chkconfig: [red]0[/red]12345 12 02

That 0 means you have your "mytest" service configured to be running in runlevel 0. It would already have been started during the boot into runlevel 5 (or 3 if your system is configured that way), so when the system enters run level 0 to shut down, it decides that it does not need to start that service again since it's already running.

You should find that if you reboot instead of shutting down, it will actually run your script during the shutdown because it is entering run level 6, not 0.

Try removing the "0" in question, then delete and add your service, and see how it goes during shutdown.

Annihilannic.
 
I will do this, tho the previous levels were 2345 and it didn't work then, either.

Will let you know.

Thanks!
 
Unfortunately, it didn't work. The chkconfig levels are now:

Code:
# chkconfig: 12345 12 02
# description: some script


 
Well... there's something funny going on then, because I have your script set up exactly as above on a CentOS 5.4 system (a clone of RHEL 5.4) and it's working fine.

Is chkconfig --list mytest returning the correct runlevels?

Annihilannic.
 
Here is what chkconfig shows for it:

Code:
mytest         0:off   1:on    2:on    3:on    4:on    5:on    6:off

Thing is, this is a recent install, and there's really not been a lot of work done on it, at least as it applies to system scripts.

So on your system, you can get the script to run when it shuts down and when it reboots?

CentOS and RHEL should be practically the same.

 
Looks fine... yes, it runs both at startup and shutdown, either for reboot or halt.

Annihilannic.
 
I went to another system, CentOS 5.4 (final) and it does the same thing (doesn't work).

Granted, this CentOS is under VMware, that should make no difference.

Cripes! :)
 
Mine's under VirtualBox, but like you say, it should be irrelevant.

Consider backing up /etc/rc.d/rc and adding a set -x to it before the loop which should be handling your script during shutdown. If you can keep a close eye on the console output, maybe you can figure out why it's deciding not to run your script.

If it all happens too fast, try updating it as follows to log the output:

Code:
[red]set -x
exec 3>&1 4>&2
exec 1>>/tmp/rc.log 2>&1
date[/red]
# First, run the KILL scripts. 
for i in /etc/rc$runlevel.d/K* ; do
        check_runlevel "$i" || continue

        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/K??}
        [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] \
                || continue

        # Bring the subsystem down.
        if LC_ALL=C egrep -q "^..*init.d/functions" $i ; then
                $i stop
        else
                action $"Stopping $subsys: " $i stop
        fi
done
[red]date 
exec 1>&3 2>&4 3>&- 4>&-
set +x[/red]

(Note that after these modifications you'll see no output on the actual console while this part is running.)

Annihilannic.
 
A minor update here.

On a hunch, I decided to take an existing script that works with a daemon process and insert some simple shell level commands. In this case, I chose "crond" -- and it worked. I was able to see the script executed at START and STOP.

What I dread is having to read through and follow every single shell command and call() definition to figure out why this is the case.

My first suspicion is being the functions called in /etc/init.d/functions, such as daemon() and killproc() are written with the assumption that whatever it's working with will start and start a running process. That theory seems to make sense at this point.

I'm not much of a programmer, but I wonder about writing a simple perl script (or whatever) that will run as a real daemon, in the background, have it's own PID, etc., that I can use to augment more script testing. Anyone know of some dummy C code out there I could use? :)

I've run through /etc/rc0.d/S00killall, /etc/rc, /etc/init.d/functions and I'm still trying to make some sense of it.


Thanks!
 
oops, I forgot to add: I was asked if somehow the scripting process was dependent upon the process name and the script name being the same -- I doubt this. Anyone know whether this is true?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top