SysV

From wikinotes

TODO:

System V unix inspired much more than an init system. This page should be renamed, and we should describe other parts that survived ex. SysV IPC

SysV is the classic linux init system. Your init system is responsible for:

  • starting programs at various key stages (boot, single-user, multi-user, shutdown, etc)
  • determining the program's load order (does your service need the internet? drive mounts? better wait until the network is up)
  • cleanly shutting down programs
  • single consistent method for managing all of the systems services.


Managing Services

Locations
/etc/rc.d/init.d rc-scripts location
/etc/rc.d/rc[0-6].d the various runlevels scripts are installed into
Primary Commands
chkconfig --list list all installed services
chkconfig <service> on/off enable/disable service in runlevels 2,3,4,5
chkconfig <service> --level 2 3 5 on/off enable/disable service in runlevels 2,3,5
service <service> status info about running service
service <service> start/stop/restart start/stop service

This is the old Redhat/CentOs init system, before they moved to systemd.

chkconfig --list


How Services Work

RunLevels

service files were installed in '/etc/init.d' and they could be called on at any one of 5 particular run levels:

0 -> Halt
1 -> Single User Mode (shell that executes as root. also known as the recovery line)
2 -> Local Multiuser with networking, but without network service
3 -> Multi-User Mode
4 -> ? (generally not used)
5 -> Multi-User Mode w/ GUI
6 -> Reboot

You can jump to a particular runlevel with the command:

telinit <runlevel number>


In order to add a script to a particular run level:

cd /etc/init.d
create a script (in this case fglrxfix)

chown root fglrxfix
chmod 4755 fglrxfix
update-rc.d fglrxfix start 20 2 3 4 5

navigate to etc/rc#.d and execute 'ls -la' to see the order that processes operate. Process names are listed with an S or a K and a number.

  • The number is the order in which the programs are executed
  • S indicates that a process is starting
  • K indicates that a process is being terminated.

example of an init script:

cd /etc/init.d
vim fglrxfix

chown root fglrxfix
chmod 4755 fglrxfix
update-rc.d fglrxfix start 20 2 3 4 5


Writing ServiceFiles

If you're looking for a quick ticket out without much reading, here is the file that I wrote for starting the pipeline_activityListener service. It's fairly reusable, and it kills the process by it's PID.

Part 1 - Header

#!/bin/sh
#
# /etc/init.d/pipeline_activityListener
#
# chkconfig:   2345 95 05	(1)
# description: receives activity events from 3D users. Enters in database.
#
# processname: pipeline_activityListener
# config:      maya_database.activityListenerConfigTable


## service name
prog="pipeline_activityListener"



## Configuration
##

## Environment Vars
export PIPELINE_PYTHONSTARTUP="/home/pipeline/.pythonrc.py"
export maya="/home/pipeline/pipeline_src"

## Variables
run_user="pipeline"
run_python="/usr/local/bin/python2.7"

Services are written in shellscript, and started from a shell with all of the environment variables stripped from it. Even if you have set global environment-variables in /etc/profile.d/*, they will not be accessible by the shell that starts your service. Make sure to set any environment variables you need here, and maybe set some other variables so the rest of your code is easier to keep upd-to-date, and easier to read.


Part 2 - Functions

# source function library
. /etc/rc.d/init.d/functions

# pull in sysconfig settings
[ -f /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

RETVAL=0



start() {

	if [ "$(_check_status)" == "1" ] ; then
		echo "Already Started $prog"


	else
		echo -n $"Starting $prog:"
	
		daemon                     \
			--user $run_user        \
			$run_python $run_prog &
		pid=$!	
		RETVAL=$?


		[ "$RETVAL" = 0 ] && touch /var/lock/subsys/$prog
		echo

	fi
}

stop() {
	echo -n $"Stopping $prog:"
	#killproc $prog -TERM

	pid=$(ps -ef | grep -v  "grep"  | grep -v  "bash"   | grep -E  "^$run_user.*?$run_python $run_prog"  | awk '{ print $2}')
	kill $pid
	[ "$RETVAL" = 0 ] && rm -f /var/lock/subsys/$prog
	echo
}

status() {
	## Tells user if service active or not
	echo -n $"Status $prog: "

	if [ "$(_check_status)" == "1" ] ; then
		echo -n "started"
	else
		echo -n "not started"
	fi

	echo

}



_check_status() {
	## Consistent way of checking if service is running 
	## returns 1 if service is active
	pid=$(ps -ef | grep -v  "grep"  | grep -v  "bash"   | grep -E  "^$run_user.*?$run_python $run_prog"  | awk '{ print $2}')
	if [[ -n "$pid" ]] ; then
		echo "1"
	else
		echo "0"
	fi
}

At the start of the functions section, /etc/rc.d/init.d/functions is sourced, which contains many general-purpose helper functions (such as the daemon function used above). It's location might change a bit depending on the distro.

These functions are responsible for starting,stopping,checking-up-on, your service, along with any thing else you might need to interact with your service to do. I have been following the python convention of using a prefix of '_' to indicate private functions, I don't believe that is the norm for shellscripts.

If there is a clean way of shutting down your script, make sure that you use that in your stop function. This is how anyone that interacts with the server will expect to interact with it. Otherwise, you can reuse the code I have written above to identify the process Id, and kill it.



Part 3 - Shell Interface and Code

case "$1" in
	start)
		start
		;;
	stop)
		stop
		;;
	status)
		status
		;;
	restart)
		stop
		start
		;;
	*)	(10)
		echo $"Usage: $0 {start|stop|restart}"
		RETVAL=1
esac
exit $RETVAL

This is where the arguments you issue to the service command are parsed. if your run service <my_service> restart, then both the stop and start functions are run.