#!/bin/bash # # plc Manages all PLC services on this machine # # chkconfig: 2345 99 5 # # description: Manages all PLC services on this machine # # $Id$ # PATH=/sbin:/bin:/usr/bin:/usr/sbin # Source function library. if [ -f /etc/init.d/functions ] ; then . /etc/init.d/functions fi # If success() or failure() are not defined if ! type -type success >/dev/null || ! type -type failure >/dev/null ; then success() { echo -ne "[ OK ]\r" return 0 } failure() { echo -ne "[FAILED]\r" return 1 } fi # Source configuration SERVICE=$(basename $0) if [ ! -f /etc/sysconfig/$SERVICE ] ; then SERVICE=plc fi if [ -f /etc/sysconfig/$SERVICE -a -z "${PLC_ROOT}${PLC_DATA}" ] ; then . /etc/sysconfig/$SERVICE fi # Total number of errors ERRORS=0 # Count the exit status of the last command check () { ERRORS=$(($ERRORS+$?)) } mounted () { if cut -d' ' -f2 /proc/mounts | grep -q "$1" ; then return 0 else return 1 fi } mount_plc () { echo -n $"Mounting PLC: " if ! mounted $PLC_ROOT ; then if ! e2fsck -a $PLC_ROOT.img | logger -t "PLC" ; then e2fsck $PLC_ROOT.img fi mount -o loop $PLC_ROOT.img $PLC_ROOT check fi if ! mounted $PLC_ROOT/data ; then mount -t none -o bind,rw $PLC_DATA $PLC_ROOT/data check fi if ! mounted $PLC_ROOT/proc ; then mount -t proc none $PLC_ROOT/proc check fi [ $ERRORS -eq 0 ] && success $"PLC unmount" || failure $"PLC unmount" echo } start () { # Starting everything if [ -z "$1" ] ; then mount_plc fi chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS start $* check } umount_plc () { echo -n $"Unmounting PLC: " for dir in $PLC_ROOT/proc $PLC_ROOT/data $PLC_ROOT ; do if mounted $dir ; then umount $dir check fi done [ $ERRORS -eq 0 ] && success $"PLC unmount" || failure $"PLC unmount" echo } stop () { if mounted $PLC_ROOT ; then chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS stop $* check fi # Stopped everything if [ -z "$1" ] ; then umount_plc fi } mountstatus_plc () { for dir in $PLC_ROOT/proc $PLC_ROOT/data $PLC_ROOT ; do if mounted $dir ; then echo $dir fi done } # safestop : tries to stop normally; if that fails, kills processes that are still using /plc # needs the lsof rpm in the root context (should be a dependency of the myplc spec) function check_command () { command=$1; shift found=$(type -p $command) if [ -z "$found" ] ; then echo "$COMMAND : requires command $command, was not found - exiting" exit 1 fi } ### when process stil use /plc/root, we cannot umount it function kill_all () { [ -n "$DEBUG" ] && set -x check_command lsof echo -n "Killing processes using $PLC_ROOT and $PLC_DATA: " # initialize process list former_process_list="unlikely" # we ignore unknown uids for now, since we run in the chroot jail anyway # not too sure about that though, while true; do # get the list of processes - collapse and remove empty lines process_list=$(lsof -t +D $PLC_ROOT +D $PLC_DATA) if [ -z "$process_list" ] ; then # we are done, let's bail out success "$PLC_ROOT clear" ; echo ; return fi if [ "$process_list" = "$former_process_list" ] ; then # we are stuck, no progress since last time : exit on error failure "$PLC_ROOT locked" ; echo ; return fi # record for next loop former_process_list="$process_list" # kill them kill $process_list sleep 2 # check there are dead for pid in $process_list ; do ps -o pid $pid &> /dev/null if [ "$?" = 0 ] ; then [ -n "$DEBUG" ] && echo "$pid survived kill - forcing kill -9" kill -9 $pid fi done done } # Get command shift $(($OPTIND - 1)) command=$1 # Get step(s) shift 1 case "$command" in start|stop) $command $* ;; restart) stop $* ERRORS=0 start $* ;; reload) chroot $PLC_ROOT /sbin/service plc $PLC_OPTIONS reload $* ;; mount|umount|mountstatus) ${command}_plc ;; kill) kill_all ;; safestop) stop ### Checking : we might need to run kill mounted=$(mountstatus_plc) if [ -n "$mounted" ] ; then echo "Umount failed : killing remaining processes and trying again" ERRORS=0 kill_all ERRORS=0 stop fi ;; *) echo "Usage: $0 {start|stop|restart|reload|mount|umount|mountstatus|kill|safestop}" RETVAL=1 ;; esac exit $ERRORS