Technology Inside Out!

Index ¦ Archives ¦ Atom ¦ RSS

Runlevels and rc.d scripts

Many operating systems use the concept of runlevels. This is particularly the case for System V Unix based systems. As you might have read in our earlier post how Linux boots it uses runlevels to determine what to do. Let's study runlevels and rc scripts in detail.

Runlevels

Runlevels are the state to which a computer intends to go, or it intends to reach. There are total 7 runlevels.

Runlevel 0: Halt or Shutdown

Runlevel 1: Single-user mode

Runlevel 2: Basic Multi-user mode but without networking

Runlevel 3: Full text-based Multi-user mode (includes networking)

Runlevel 4: X11 with session managers (Generally not used by most of the operating systems and is customizable)

Runlevel 5: Full GUI based Multi-user mode

Runlevel 6: Reboot

These are the basic definitions what each runlevel is responsible for. For example, if an operating system is required to shut down, then it'd go to runlevel 0. You can even switch between these runlevels using the init command. Just type init \<runlevel> and it'd change the current runlevel to the one specified. For example:

init 0

will shut down the system.

Each system has a default runlevel to which it boots. Like Fedora has runlevel as default. To see which runlevel you are in type:

runlevel

To check the default runlevel of your system, type:

systemctl get-default

You can even change the default, keeping in mind what runlevel provided, like you want it to be multiuser or the graphical one. Using it you can set the default like:

systemctl set-default multi-user.target 
rm '/etc/systemd/system/default.target  # To remove current default
ln -s '/usr/lib/systemd/system/multi-user.target' '/etc/systemd/system/default.target'

Runlevel and target file have the following relation:

runlevel 0: poweroff.target

runlevel 1: rescue.target

runlevel 2: multi-user.target

runlevel 3: multi-user.target

runlevel 4: multi-user.target

runlevel 5: graphical.target

runlevel 6: reboot.target

You should never mess with the default runlevel unless you are absolutely sure with what you're doing. Like, if you manage to set runlevel 0 or 6 as default you will end up in a loop kind of condition. Your PC will shut down( or reboot depending on what runlevel you set) as soon as it has booted.

rc Scripts

When a computer has entered into a specific runlevel, it runs scripts according to the runlevel it's in. The rc here comes from use in the older computers which had rc files to contain commands that run at startup. These files were called runcom files. Where runcom files meant files used to RunCommand.

Your script must contain the line before any command executes:

. /etc/init.d/functions

This is because, your script might be executed at a time when nothing is loaded, not even file system( though it can be specified in boot facilities in Required-Start in LSB styled stanzas discussed below) so we can not say that each command we write will already be present( Remeber that each command is executed from a script present in PATH variable of your system). Hence in order for those commands to work, we need the functions file to be loaded as the first step. This function file contains the functions that a shell script might use.

Fedora and most of the distros have folders that contain scripts that are to be run at a specific runlevel. They are located in the /etc folder. The folders containing these scripts are:

/etc/init.d
/etc/rc.d/rc0.d
/etc/rc.d/rc1.d
/etc/rc.d/rc2.d
/etc/rc.d/rc3.d
/etc/rc.d/rc4.d
/etc/rc.d/rc5.d
/etc/rc.d/rc6.d

And, folders with the same name also exist in /etc but they are actually symbolic links of there corresponding folders in /etc/rc.d For example:

/etc/rc0.d (Symbolic link of /etc/rc.d/rc0.d)

Each of these folders contain symbolic links of scripts that are actually stored in init.d for the runlevel they have in their name. Like /etc/rc.d/rc0.d contains a symbolic link for scripts in /etc/init.d that are required to be run at shutdown.

Now if you open any of these folders you'd find out weird names with the structure like

S|K[01-99]filename where filename is the name of the script in /etc/int.d

Like K50netconsole. Now let's see what these names mean.

Demystifying the symlink names

The terms have their meanings as follows:

S: start the service, if it's not already started.

K: Kill the service, if it's running.

01-99 is the priority for that start or kill task

filename is the exact same name of the file in /etc/init.d folder.

(Remember that it's actually /etc/init.d that actually houses those scripts. Rest of the folders just have symlinks to these.)

So, If a file named shutdown-script is to be run at shutdown all times with a priority of 90 then the file shutdown-script should be present in init.d folder. And a symlink to it must be created in /etc/rc.d/rc0.d with the name S90shutdown-script, rest of the folders rc[1-6] can have K90shutdown-script. If 90 is the priority required to shut down.

Priority Of these scripts

Essentially, it can be better thought of as a position, and think of them being executed downwards from 01 to 99. For example, if you have a script that requires the network to be switched on then the network script should be at a higher position or priority than your script. Like the network, a script can have a priority of 01 and your script can have any number greater than it. So that it's executed after the network script.

The chkconfig

the chkconfig command here deserves the 'The' in the heading for how easy it makes to manage these scripts and runlevels! Yes, this command just needs your source script file and manages creation deletion, the setting of S or D and also the priority level!

chkconfig has an amazing man page and here are the basic commands that will get you going.

chkconfig --list

This prints the System V services, and that will do for us.

chkconfig --add

Is used to add your file for management by chkconfig. BUT wait. This command won't run unless you have some things set with your script.

First and foremost, your script should exist in the home of all scripts, and that is:

/etc/init.d

Paste your script here.

Secondly, your file must have certain comment lines so that it can be managed by chkconfig.

It must have these comment lines, though the description is not absolutely necessary and the script would work without it, it's recommended. So that anyone who intends to clean up the unnecessary services knows if this script is essential or not:

# chkconfig: 235 29 88
# description: The description of the script like what it does

The first line here has some numbers ahead chkconfig: like 235, 29 and 88.

here the First number is the runlevels it's required to run on combined into a string. Like 235 here means it's supposed to run in runlevel 2,3 and 5.

The next two numbers are the priority for start and stop respectively. So in this example, start priority is 29 and stop priority is 88.

you can use backslash for a multiline comment though you still require a #, in the beginning, to identify it as a comment.

This is how it creates the symlinks with required priorities.

Another way you can do this is enter LSB(Linux Standard Base) style init stanzas instead of these two comments. For it you can do it like:

 ### BEGIN INIT INFO
 # Provides: scriptA
 # Required-Start: scriptB
 # Default-Start: 2 3 5
 # Default-Stop: 0 1 6
 # Description: Description of what the script does
 ### END INIT INFO

This one gives you more ease though it just looks a bit more complicated.

In this, Required-Start is the script that is required to start this script. That is, it should be running before the current script gets up. Provides: It tells about the boot facilities that this script provides so that those will be counted as already present when another script requires it. Hence priorities will be set accordingly to what is required to be already present and what it'll provide. Default-Start or Stop tells which runlevel should this start on and stopped(if running) respectively.

And don't forget a shebang at the beginning of the file.

Now we are all set to go with these things done. Let's execute this command to add it to the management of chkconfig:

chkconfig --add filename

like for a file named bootpref in init.d it would be:

chkconfig --add bootpref

Now most probably your file will be visible with a status of on under the respective runlevels when you run

chkconfig --list

And if it's not or you want to change runlevels you can go like:

chkconfig bootpref --level 0 on

Will make it run on runlevel 0 that is at shutdown.

Similarly off argument will kill it if present in that level. If no level is specified then these act on level 2,3,4 and 5. You can also specify multiple levels like --level 26 for level 2 and 6.

chkconfig --del bootpref

will delete its symlinks from all rc folders but not from the init.d folder. That is required to be done manually. Ad chkconfig generally doesn't modify the content of init.d but rc folders.

Hope this will help you play with your scripts in a better and safe manner.

Thank you for reading!

© The Geeky Way. Built using Pelican. Theme by Giulio Fidente on github.

Disclaimer Privacy policy