| 1 |
#!/bin/bash
|
| 2 |
################################################################################
|
| 3 |
# #
|
| 4 |
# Author: Sean E. Russell <ser@germane-software.com> #
|
| 5 |
# Version: 1.0 #
|
| 6 |
# Date: Jun 26, 2002 #
|
| 7 |
# Adaptation: Mike Frysinger [SpanKY] <vapier@gentoo.org> #
|
| 8 |
# Original code was in Ruby ... recoded into bash (at syntax level) #
|
| 9 |
# #
|
| 10 |
# This application displays information about the RC system used by Gentoo. #
|
| 11 |
# In particular, it displays a tree-like format of a run level, showing #
|
| 12 |
# all of the services that are installed at that level, and what each #
|
| 13 |
# service's status is (running, stopped, etc.) #
|
| 14 |
# #
|
| 15 |
# -a can be used to display all runlevels #
|
| 16 |
# -d can be used to display service dependancies #
|
| 17 |
# -u will display all unassigned services #
|
| 18 |
# -s will display all services #
|
| 19 |
# -h will display help #
|
| 20 |
# <runlevel> is used to choose the run level for which information is #
|
| 21 |
# displayed #
|
| 22 |
# #
|
| 23 |
# By default, rc-status only displays information about the current #
|
| 24 |
# runlevel; services installed and services running. #
|
| 25 |
# #
|
| 26 |
################################################################################
|
| 27 |
|
| 28 |
# grab code from functions.sh so we don't have to reproduce it
|
| 29 |
source /sbin/functions.sh
|
| 30 |
runleveldir=/etc/runlevels
|
| 31 |
|
| 32 |
# grab settings from conf.d/rc
|
| 33 |
source /etc/conf.d/rc
|
| 34 |
source "${svclib}/sh/rc-daemon.sh"
|
| 35 |
|
| 36 |
################################################################################
|
| 37 |
# Parse command line options #
|
| 38 |
################################################################################
|
| 39 |
do_opt() {
|
| 40 |
case $1 in
|
| 41 |
--all|-a)
|
| 42 |
ALL=true
|
| 43 |
;;
|
| 44 |
--depend)
|
| 45 |
DEPEND=true
|
| 46 |
;;
|
| 47 |
--unused|-u)
|
| 48 |
ALL=true
|
| 49 |
UNUSED=true
|
| 50 |
;;
|
| 51 |
--list|-l)
|
| 52 |
ls -1 ${runleveldir}
|
| 53 |
exit 0
|
| 54 |
;;
|
| 55 |
--servicelist|-s)
|
| 56 |
ALL=true
|
| 57 |
SERVICELIST=true
|
| 58 |
;;
|
| 59 |
--nocolor|-nc)
|
| 60 |
;;
|
| 61 |
--help|-h|-*)
|
| 62 |
echo "USAGE: $0 [command | <runlevel>]"
|
| 63 |
echo
|
| 64 |
echo "Commands:"
|
| 65 |
echo " -a, --all Show services at all run levels"
|
| 66 |
echo " -l, --list Show list of run levels"
|
| 67 |
echo " -u, --unused Show services not assigned to any run level"
|
| 68 |
echo " -s, --servicelist Show service list"
|
| 69 |
echo " -nc,--nocolor Monochrome output only"
|
| 70 |
echo " <runlevel> Show services assigned to <runlevel>"
|
| 71 |
echo
|
| 72 |
echo "If no arguments are supplied, shows services for current run level."
|
| 73 |
exit 0
|
| 74 |
;;
|
| 75 |
*)
|
| 76 |
runlevel=$1
|
| 77 |
;;
|
| 78 |
esac
|
| 79 |
}
|
| 80 |
for opt in "$@" ; do
|
| 81 |
do_opt ${opt}
|
| 82 |
[[ -n $2 ]] && shift
|
| 83 |
done
|
| 84 |
|
| 85 |
################################################################################
|
| 86 |
# Find the current runlevel being queried. This is either something supplied #
|
| 87 |
# on the command line, or pulled from softlevel #
|
| 88 |
################################################################################
|
| 89 |
if [[ -z ${runlevel} ]] ; then
|
| 90 |
if [[ -e ${svcdir}/softlevel ]] ; then
|
| 91 |
runlevel=$(<${svcdir}/softlevel)
|
| 92 |
else
|
| 93 |
ewarn "Could not locate current runlevel in ${svcdir}/softlevel"
|
| 94 |
if [[ -d ${runleveldir}/default ]] ; then
|
| 95 |
runlevel=default
|
| 96 |
else
|
| 97 |
eerror "Your installation is probably broken ... please \`emerge baselayout-vserver\`"
|
| 98 |
exit 1
|
| 99 |
fi
|
| 100 |
ewarn "Assuming current runlevel is '${runlevel}'"
|
| 101 |
fi
|
| 102 |
fi
|
| 103 |
if [[ ! -d ${runleveldir}/${runlevel} ]] ; then
|
| 104 |
eerror "${runlevel} is not a valid run level !"
|
| 105 |
eerror "Valid runlevels (obtained from \`rc-status --list\`):"
|
| 106 |
rc-status --list
|
| 107 |
exit 1
|
| 108 |
fi
|
| 109 |
|
| 110 |
################################################################################
|
| 111 |
# Build up a hash of the services associated with each run level. In the most #
|
| 112 |
# trivial case, this is simply the current runlevel. If --all was specified, #
|
| 113 |
# we gather information about all of the runlevels. If --unused was #
|
| 114 |
# specified, we pull info about all of the services and filter for the ones #
|
| 115 |
# that don't appear in any runlevel. #
|
| 116 |
################################################################################
|
| 117 |
runlevelidxs=$(ls ${runleveldir})
|
| 118 |
declare -a runlevels
|
| 119 |
# For each directory in /etc/runlevels, do ...
|
| 120 |
arridx=0
|
| 121 |
for level in ${runlevelidxs} ; do
|
| 122 |
if [[ ${level} == ${runlevel} || -n ${ALL} ]] ; then
|
| 123 |
runlevels[${arridx}]=$(find ${runleveldir}/${level} -maxdepth 1 -type l -printf '%f ')
|
| 124 |
let "arridx += 1"
|
| 125 |
fi
|
| 126 |
done
|
| 127 |
|
| 128 |
# In case --all was specified, get a list of all the services set up in
|
| 129 |
# /etc/init.d; services can be added, but not enabled, and we need to
|
| 130 |
# identify these 'orphan' services.
|
| 131 |
in_list() { #$1=list $2=find
|
| 132 |
for ele in $1 ; do
|
| 133 |
if [[ ${ele} == $2 ]] ; then
|
| 134 |
echo 1
|
| 135 |
return 0
|
| 136 |
fi
|
| 137 |
done
|
| 138 |
echo 0
|
| 139 |
return 0
|
| 140 |
}
|
| 141 |
if [[ -n ${ALL} ]] ; then
|
| 142 |
unassigned=
|
| 143 |
allservices=
|
| 144 |
for service in $(ls -1 /etc/init.d | grep -v '\.sh$') ; do
|
| 145 |
if [[ $(in_list "${runlevels[*]}" "${service}") -eq 0 ]] ; then
|
| 146 |
unassigned="${unassigned} ${service}"
|
| 147 |
fi
|
| 148 |
allservices="${allservices} ${service}"
|
| 149 |
done
|
| 150 |
runlevelidxs="${runlevelidxs} UNASSIGNED"
|
| 151 |
runlevels[${arridx}]="${unassigned}"
|
| 152 |
runlevels[${arridx}+1]="${allservices}"
|
| 153 |
fi
|
| 154 |
|
| 155 |
################################################################################
|
| 156 |
# Now collect information about the status of the various services; whether #
|
| 157 |
# they're started, broken, or failed. Put all of this into arrays. #
|
| 158 |
################################################################################
|
| 159 |
if [[ -x ${svcdir}/started ]]; then
|
| 160 |
started=$(ls ${svcdir}/started)
|
| 161 |
# If we're root then update service statuses incase any naughty daemons
|
| 162 |
# stopped running without our say so
|
| 163 |
if [[ ${EUID} == 0 ]]; then
|
| 164 |
for service in ${started}; do
|
| 165 |
update_service_status "${service}"
|
| 166 |
done
|
| 167 |
started=$(ls ${svcdir}/started)
|
| 168 |
fi
|
| 169 |
fi
|
| 170 |
[[ -x ${svcdir}/starting ]] && starting=$(ls ${svcdir}/starting)
|
| 171 |
[[ -x ${svcdir}/inactive ]] && inactive=$(ls ${svcdir}/inactive)
|
| 172 |
[[ -x ${svcdir}/stopping ]] && stopping=$(ls ${svcdir}/stopping)
|
| 173 |
|
| 174 |
################################################################################
|
| 175 |
# Now print out the information we've gathered. We do this by going through #
|
| 176 |
# the hash of 'runlevels' information, and for each String key/Array value #
|
| 177 |
# pair, print the runlevel; then for each service in that runlevel, print the #
|
| 178 |
# service name and its status. #
|
| 179 |
################################################################################
|
| 180 |
# Define a helper method for printing the status of a service; '[ xxx ]'
|
| 181 |
print_msg() {
|
| 182 |
printf " %-$((COLS - 5 - ${#3}))s%s\n" "$1" "${BRACKET}[ $2$3 ${BRACKET}]${NORMAL}"
|
| 183 |
}
|
| 184 |
|
| 185 |
# if --all wasnt specified, dont print everything
|
| 186 |
[[ -z ${ALL} ]] && runlevelidxs=${runlevel}
|
| 187 |
if [[ -z ${UNUSED} ]] ; then
|
| 188 |
if [[ -z ${SERVICELIST} ]] ; then
|
| 189 |
arridx=0
|
| 190 |
else
|
| 191 |
runlevelidxs="all"
|
| 192 |
let "arridx += 1"
|
| 193 |
fi
|
| 194 |
else
|
| 195 |
runlevelidxs="unused"
|
| 196 |
fi
|
| 197 |
|
| 198 |
if [[ -f "/etc/runlevels/${BOOTLEVEL}/.critical" ]]; then
|
| 199 |
boot_crit=
|
| 200 |
for x in $(< /etc/runlevels/${BOOTLEVEL}/.critical); do
|
| 201 |
boot_crit="${boot_crit} ${x##*/}"
|
| 202 |
done
|
| 203 |
else
|
| 204 |
boot_crit="checkroot hostname modules checkfs localmount clock"
|
| 205 |
fi
|
| 206 |
|
| 207 |
for level in ${runlevelidxs} ; do
|
| 208 |
echo "Runlevel: ${HILITE}${level}${NORMAL}"
|
| 209 |
for service in ${runlevels[${arridx}]} ; do
|
| 210 |
if [[ ! -e ${runleveldir}/${level}/${service} \
|
| 211 |
&& ${level} != "UNASSIGNED" \
|
| 212 |
&& ${level} != "${BOOTLEVEL}" \
|
| 213 |
&& " ${boot_crit} " != *" ${service} " ]]; then
|
| 214 |
print_msg "${service}" "${BAD}" 'broken '
|
| 215 |
elif [[ -n ${inactive} && $(in_list "${inactive}" "${service}") -eq 1 ]] ; then
|
| 216 |
print_msg "${service}" "${WARN}" 'inactive'
|
| 217 |
elif [[ $(in_list "${started}" "${service}") -eq 1 ]] ; then
|
| 218 |
print_msg "${service}" "${GOOD}" 'started '
|
| 219 |
elif [[ -n ${starting} && $(in_list "${starting}" "${service}") -eq 1 ]] ; then
|
| 220 |
print_msg "${service}" "${GOOD}" 'starting'
|
| 221 |
elif [[ -n ${stopping} && $(in_list "${stopping}" "${service}") -eq 1 ]] ; then
|
| 222 |
print_msg "${service}" "${BAD}" 'stopping'
|
| 223 |
else
|
| 224 |
print_msg "${service}" "${BAD}" 'stopped '
|
| 225 |
fi
|
| 226 |
done
|
| 227 |
let "arridx += 1"
|
| 228 |
[ -n "${UNUSED}" ] && exit 0
|
| 229 |
done
|