SysV
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 -> RebootYou 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 5navigate 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 thedaemon
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 $RETVALThis is where the arguments you issue to the
service
command are parsed. if your runservice <my_service> restart
, then both the stop and start functions are run.