How to Write Linux Init Scripts Based on LSB Init Standard

by Lakshmanan Ganapathy on March 16, 2012

LSB stands for Linux Standard Base.

LSB was started by Linux Foundation to reduce the difference between several Linux distributions, and thereby reducing the cost involved in porting between different distributions. Init scripts are one among them to be standardized.

In this article, we will see how to write an Init script that conforms to LSBInit Standard.

Init scripts are used to start|stop a software|service. For example, if you are using postgresql software, we will have a Init script named ‘/etc/init.d/postgresql’ which can be used to ‘start|stop|restart|reload|force-reload|status’.

LSB-compliant init scripts need to:

  • Provide at-least ‘start, stop, restart, force-reload, and status’
  • Return Proper exit code
  • Document run-time dependencies

Optionally, they can use init.d functions like “log_success_msg”, “log_failure_msg” etc.. to log the messages.

LSB provides default set of functions which is in /lib/lsb/init-functions. We can make use of those functions in our Init scripts. All the Init process by default will log the pid of the process in a file under /var/run/ directory. This is useful for the Init scripts to find the status of the process.

Now let’s start writing a Init script. First we need to add a header to the Init script, which looks like,

### BEGIN INIT INFO
# Provides:          my_daemon
# Required-Start:    postgresql networking
# Required-Stop:     postgresql networking
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: This is a test daemon
# Description:       This is a test daemon
#                    This provides example about how to
#                    write a Init script.
### END INIT INFO

Provides specifies what is the facility provided by this Init script. The name should be unique.

Required-start specifies the set of facilities that should be started before starting this service. In our case, postgresql and networking has to be started before starting my_daemon. Remember, here ‘postgresql’ will have a separate Init script which says ‘Provides: postgresql’. This ensures dependency based booting. Based on this dependency, the ‘inserv’ command or ‘update-rc.d’ will put the entries in run-level directories with appropriate sequence number. For example, the entries can be like follows

/etc/rc2.d/S12postgresql
/etc/rc2.d/S03networking
/etc/rc2.d/S13my_daemon

Which indicates, networking will be started first, then postgresql and then my_daemon.

To know more about run-levels, refer to stage#6 (which is runlevel) of Linux boot process.

Required-Stop specifies the list of facilities that has to be stopped only after stopping this facility. Here only after my_daemon is stopped, the postgresql and networking facilities will be stopped.

Default-Start Default-Stop defines the run-levels in which the service has to be started or stopped.

Short-Description and Description are used to give some description with regard the to the facility provided. Description can span across multiple lines, Short-Description is limited to single line.

Let’s look at an actual Init script.

### BEGIN INIT INFO
# Provides:          my_daemon
# Required-Start:    postgresql networking
# Required-Stop:     postgresql networking
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: This is a test daemon
# Description:       This is a test daemon
#                    This provides example about how to
#                    write a Init script.
### END INIT INFO

# Using the lsb functions to perform the operations.
. /lib/lsb/init-functions
# Process name ( For display )
NAME=my-daemon
# Daemon name, where is the actual executable
DAEMON=/home/user1/my_daemon
# pid file for the daemon
PIDFILE=/var/run/my_daemon.pid

# If the daemon is not there, then exit.
test -x $DAEMON || exit 5

case $1 in
 start)
  # Checked the PID file exists and check the actual status of process
  if [ -e $PIDFILE ]; then
   status_of_proc -p $PIDFILE $DAEMON "$NAME process" && status="0" || status="$?"
   # If the status is SUCCESS then don't need to start again.
   if [ $status = "0" ]; then
    exit # Exit
   fi
  fi
  # Start the daemon.
  log_daemon_msg "Starting the process" "$NAME"
  # Start the daemon with the help of start-stop-daemon
  # Log the message appropriately
  if start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON ; then
   log_end_msg 0
  else
   log_end_msg 1
  fi
  ;;
 stop)
  # Stop the daemon.
  if [ -e $PIDFILE ]; then
   status_of_proc -p $PIDFILE $DAEMON "Stoppping the $NAME process" && status="0" || status="$?"
   if [ "$status" = 0 ]; then
    start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
    /bin/rm -rf $PIDFILE
   fi
  else
   log_daemon_msg "$NAME process is not running"
   log_end_msg 0
  fi
  ;;
 restart)
  # Restart the daemon.
  $0 stop && sleep 2 && $0 start
  ;;
 status)
  # Check the status of the process.
  if [ -e $PIDFILE ]; then
   status_of_proc -p $PIDFILE $DAEMON "$NAME process" && exit 0 || exit $?
  else
   log_daemon_msg "$NAME Process is not running"
   log_end_msg 0
  fi
  ;;
 reload)
  # Reload the process. Basically sending some signal to a daemon to reload
  # it configurations.
  if [ -e $PIDFILE ]; then
   start-stop-daemon --stop --signal USR1 --quiet --pidfile $PIDFILE --name $NAME
   log_success_msg "$NAME process reloaded successfully"
  else
   log_failure_msg "$PIDFILE does not exists"
  fi
  ;;
 *)
  # For invalid arguments, print the usage message.
  echo "Usage: $0 {start|stop|restart|reload|status}"
  exit 2
  ;;
esac

The above script basically provides a template for writing LSBInit scripts. You can change the DAEMON,PIDFILE,NAME variables, and the header to make this script, fit to your own programs.

To know more about the functions provided by the LSB, please refer to InitScript Functions

Once the Init script is done, in order to make the script to start or stop automatically, execute the following command. This will add appropriate ‘S’ and ‘K’ entries in the given run-levels. This will also add appropriate sequence number by considering the dependencies.

update-rc.d filename defaults

Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 14 comments… read them below or add one }

1 Pierre B. March 16, 2012 at 2:31 am

Thx,

It’s been some time that i wanted to have a more detailed look at LSB scripts writing, it is now easier thanx to you!

2 Suresh Danda March 16, 2012 at 2:32 am

Excellent Bro……!

Thanks for being like Geek and making Geeks.

3 Jalal Hajigholamali March 16, 2012 at 3:02 am

Hi,

Thanks a lot, very nice article

4 tasos March 16, 2012 at 4:21 am

Great article

5 Lakshmanan Ganapathy March 16, 2012 at 8:09 am

Thank u all guys…

6 Mustapha Oldache March 17, 2012 at 12:03 pm

Genius article about things we dont mind.

7 Julien March 21, 2012 at 9:57 am

Great explaination ! wanted to learn that one day. Checked

8 Shantanu May 19, 2012 at 2:30 pm

Good article to get started with init script..!
Can you mention distro name, distro version and LSB release for which this example script is written? I can’t seem to find some of the functions you have used, e.g. ‘log_daemon_msg’ and ‘status_of_proc’ either in ‘/lib/lsb/init-functions’ on CentOS 6.2 or refspec for LSB 3.1.0.

9 Mike Rogers July 1, 2012 at 2:01 pm

Thanks for the article – I notice in the status) option you dont return an exit status of 3 if the process is not running. This article suggest that in an init script that is lsb compliant, process not running should return ‘ 3 program is not running’ rather than 0. This article is specific to my current learning.

10 Venadan August 29, 2012 at 10:00 am

Excelelnt article. Was looking for some thing like this explains in detail..

11 Lakshmanan Ganapathy October 12, 2012 at 10:07 am

@Mike Rogers

Thanks for pointing it out Mike.

12 Victory January 19, 2013 at 7:08 am

Great post, i put the script template to good use.

One little gotcha i found is that line

start-stop-daemon –start –quiet –oknodo –pidfile $PIDFILE –exec $DAEMON

Expects the DAEMON to create a pid file, which mine was just a shell script and did not, i also had to force it to the background

I used the -b and –make-pidfile options to fix this.

start-stop-daemon –start -b –make-pidfile –quiet –oknodo –pidfile $PIDFILE –exec $DAEMON

13 pavan October 2, 2013 at 12:37 am

thanks for the nice and neat article

14 Senthil February 11, 2014 at 10:23 pm

Thanks. As usual, well explained!

Leave a Comment

Previous post:

Next post: