##Create a linux startup service and init.d script from scratch, using chef and debian linux.

By C. Thomas Clark https://github.com/cthomaspdx

As a systems engineer, I have been tasked to help maintain up-time for our servers and services they provide. If a server does have to reboot unexpectedly it would be nice to have some kind of assurance that when our servers come back online they automatically start their services.

Case in point: Suppose your cloud server provider, very subtly notified you that your servers were due for an update and needed to be rebooted in order for the update to take effect. One of the major problem is that many of the homegrown services with out init.d script fail to start back up after reboot. I would like to not have to worry about that happening.

Understanding “Sys-v” style init scripts and runlevels

The /etc dir contains a set of directories named /rc<int>.d where <int> is their runlevel integers 1-6. A runlevel is basically the state of the system. i.e. /etc/rc0.d is the Halt state or shutdown of the system; while runlevel 1 is “single user” or “rescue mode” where only the most essential services are ran. Runlevel 6 /etc/rc6.d is the reboot runlevel and is the same as halt rc0.d but with a reboot call at the end. So this leaves us to play with runlevels 2-5 for multi-user system start up configurations.

You can check which runlevel you are on by runing /sbin/runlevel the second character it returns is the runlevel.

Take a look at what a the directory /etc/rc2.d for runlevel 2 contains. Run ls -la /etc/rc2.d I can see that it contains a bunch of symlinks to /etc/init.d/service_name these symlinks have prefixes of S or K (you may not have an example of K##service in the rc2.d) followed by two intergers 01, 02…99 and are excuted in alphabetical first, so K(kills) are run before S(starts), then numeric order the lowest number being the first service to start. Higher level services depend on other services to be running so the depencies need to start first and in turn a lower number number following the S or K in the symlink. So when the run level changes or on boot, init sends the signal start to the init script in order.

 S01vboxadd -> ../init.d/vboxadd
 S02vboxadd-service -> ../init.d/vboxadd-service
 S13rpcbind -> ../init.d/rpcbind
 S14nfs-common -> ../init.d/nfs-common
 S16chef-client -> ../init.d/chef-client
 S16datadog-agent -> ../init.d/datadog-agent
 S16elasticsearch -> ../init.d/elasticsearch
 S16rsyslog -> ../init.d/rsyslog
 S16sudo -> ../init.d/sudo

Here is a great article about runlevels if you would like more detail. https://www.debian-administration.org/article/212/An_introduction_to_run-levels

So with an understanding of how the symlink are called let’s take a look at how they are generated. If we open up any /etc/init.d/ init script, we can see that they contain a header ### BEGIN INIT INFO. This one is for elasticsearch.

### BEGIN INIT INFO
# Provides:          (name of the service)
# Required-Start:    (services that should start before this does.)
# Required-Stop:     (services that should stoped after this service is stopped.)
# Default-Start:     2 3 4 5 (these are the runlevels in which it should be started)
# Default-Stop:      0 1 6  (these are the runleves in which it should be stopped(halt, safe-mode and reboot).)
# Short-Description: Starts elasticsearch
# Description:       Starts elasticsearch using start-stop-daemon
### END INIT INFO


### BEGIN INIT INFO
# Provides:          elasticsearch
# Required-Start:    $network $remote_fs $named
# Required-Stop:     $network $remote_fs $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts elasticsearch
# Description:       Starts elasticsearch using start-stop-daemon
### END INIT INFO`

run update-rc.d <basename> default and the symlinks in the rc?.d files will be created according to INIT INFO and you are off to the races.

For more info check man update-rc.d

##Chef setup

Here is an example of an init.d scrip we added for our geoip sevice.

Add a a template for the init.d script.

Here is a link to a nice init.d script template https://github.com/fhd/init-script-template

Add the template to the /etc/init.d/ directory.

template "/etc/init.d/geoip" do
  source 'init.d.geoip.erb'
  mode 0755
end

Then start the service.

service 'geoip' do 
  supports :status => true, :start => true, :stop => true, :restart => true
  action [:enable, :start]
end

Service will update-rc.d with action :enable