Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I've got a script that gets run during boot on a Debian server. It's getting run too early, but I can't control when it's fired off. I can force the script to delay its own run with:

sleep 60

...or, alternately, I could just try the action a few times, like this:

TESTRUN=0
ACTIONWORKED=0
while [ $ACTIONWORKED -eq 0 ] && [ $TESTRUN -le 5 ]; do
      # run the action i want
      # quick test if it worked
      # if yes, set ACTIONWORKED=1
      # if no, sleep 10
      # increment TESTRUN
done

What's a better way to test that the system is ready? The script will be run at other times during system operation, so the test is needed to differentiate between "booting-can't-do-this-yet" and "not-booting-run-now" states. I don't want it to wait every time the script runs.


Edit: Thanks for the ideas so far. Keep 'em coming if you have alternatives to what's already been posted.

To those who've asked for specifics, I've left them out of the question specifically to gather answers that work with the general Linux boot process.

Assume a "fully booted" system has presented a login prompt (via console, X, or whatever).

share|improve this question
add comment

9 Answers

up vote 1 down vote accepted

Really the best way to do what you want is to insert a call to the script in the proper place in SysV init. I'd recommend that you write a script that calls your script, and cajole your sysadmin until he or she installs it in the proper place.

EDIT: Okay, I just read your other question, and I see that you are talking about a script that is fired asynchronously, when someone plugs in a device. What you want to do is check the runlevel to see if it's 2 (or whatever your default runlevel is if you've changed it, and also 1 if you want this to run in single-user mode.) If I'm reading the Debian FAQ correctly, the runlevel does not change to the default until the boot is complete.

share|improve this answer
    
can't do it. i am the sysadmin. i need a good test. –  quack quixote Nov 5 '09 at 21:10
    
ah, now that's useful. another answer suggested checking the runlevel but i didn't know when that would change. –  quack quixote Nov 5 '09 at 21:27
2  
My understanding is that all the /etc/rcS.d scripts are run first, and then it switches to runlevel 2 (or whatever is the default) and runs all the scripts in /etc/rc2.d –  Brent Nov 5 '09 at 22:41
    
@brent: that's my understanding as well. my script is running during the early /etc/rcS.d scripts (S03, i think). so checking against the runlevel is probably the right test. –  quack quixote Nov 5 '09 at 23:02
add comment

I would watch the init levels.

This should get you started..

 [[ `/sbin/runlevel | cut -d " " -f 2` == 5 ]] && echo "Ready"

HTH

share|improve this answer
1  
it's debian, so testing against runlevel 2 would be more approproate. hmm. it wouldn't work if i ever needed single mode, but i'm not sure that's a concern. –  quack quixote Nov 5 '09 at 21:29
add comment

On a debian system, you can specify the order something is run during boot by the number at the start of the script in /etc/rc?.d. So that the first script to be run at that runlevel would be /etc/rc?.d/S01scriptname - and the last would be /etc/rc?.d/S99scriptname. By ensuring your script is the only one that is prefixed with S99, it will ensure it is run last.

Alternatively, one of the last things to be done is to call /etc/rc.local. By calling your script from there, you could ensure it is called at the end of the boot process.

Another option would be to test for the file /etc/nologin - which is created at the start of boot, and removed at the end.

That being said - I don't think your idea of testing whether or not the script worked is a bad one. It ensures that nothing else gets in the way of the script running correctly.

share|improve this answer
    
the script is being run (forked, not exec'd) by an earlier script in the init chain, and i don't want to change that one. –  quack quixote Nov 5 '09 at 21:15
    
actually on Debian lenny it'll be /var/lib/initscripts/nologin, and you need to set DELAYLOGIN=yes in /etc/defaults/rcS ... some versions may create /etc/nologin as a symlink to the one under /var but i haven't seen where yet. –  quack quixote Nov 5 '09 at 21:52
    
and it's done in /etc/init.d/bootscripts.sh, which runs too late for this purpose. :( –  quack quixote Nov 5 '09 at 22:07
add comment

You could add a script under rc3.d. Call it S99local and it will run after all the other scripts.

Scripts are executed in order S01xx to S99xx.

share|improve this answer
    
can't do it. the script is called from elsewhere. i could write another script (eg S99local) to call it again, but this is not an optimal solution. –  quack quixote Nov 5 '09 at 21:12
add comment

You could also run it as a cronjob using @reboot as the time.

share|improve this answer
add comment

You're assuming that you need to see if the system is "ready", but what does that mean? What functionality to you require in order for this script to be running? Does the network need to be up and running? Does X11 have to have a logged in user? Check for those conditions directly, or find a better place to install the script that will execute when those particular steps are complete (i.e. postup stanza in /etc/network/interfaces or similiar).

share|improve this answer
    
I totally agree with your point. –  Anonymous Nov 6 '09 at 16:54
add comment

Two pieces of information would greatly assist in finding an answer:

  1. Why can't you adjust when the script is fired off?
  2. What specific services/capabilities have to be ready/working for your task to succeed? X? networking? low system load? File shared mounted? Each of those things could be checked for; "system is booted" is too general and could encompass any or all of those.
share|improve this answer
add comment

The last file that is called in the boot process is a file called /etc/rc.local. Anything that you will place into that file will be run at the end of the boot process.

One example for a manual for this is http://www.netbsd.org/docs/guide/en/chap-rc.html

share|improve this answer
add comment

Here's a (truly ugly) solution:

  1. use this test in the script:

    while [ ! -e "/etc/yes-we-up" ]; do
        sleep 10
    done
    
  2. add this to the end of /etc/rc.local:

    touch /etc/yes-we-up && chmod 644 /etc/yes-we-up
    
  3. create /etc/init.d/is-we-up,
    symlink it to /etc/rc0.d/K02is-we-up and /etc/rc6.d/K02is-we-up,
    and put this in it:

    #!/bin/sh -e
    # no we ain't
    rm /etc/yes-we-up
    
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.