# functions This file contains functions to be used by most or all
# shell scripts in the /etc/rc.d/init.d directory.
#
-# $Id$
#
# Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
# Hacked by: Greg Galloway and Marc Ewing
[ -r /etc/sysconfig/system ] && . /etc/sysconfig/system
[ -r /etc/sysconfig/bootsplash ] && . /etc/sysconfig/bootsplash
+# if initscript is invoked via bash, enable RedHat/Fedora compatibility
+# RC_FEDORA is "set" if enabled and "unset" when not, but it's "value" is always empty
+# this is useful for inline constructs
+if [ "${BASH_VERSION+set}" = "set" ]; then
+ RC_LOGGING=yes
+ FASTRC=no
+ RC_FEDORA=
+else
+ unset RC_FEDORA || :
+fi
+
[ "$env_upstart" ] && USE_UPSTART=$env_upstart
if [ -z "$VSERVER" -o "$VSERVER" = "detect" ]; then
return 0
}
+# Apply sysctl settings, including files in /etc/sysctl.d
+apply_sysctl() {
+ if [ -x /lib/systemd/systemd-sysctl ]; then
+ /lib/systemd/systemd-sysctl
+ return
+ fi
+
+ local file
+ for file in /usr/lib/sysctl.d/*.conf; do
+ [ -f /run/sysctl.d/${file##*/} ] && continue
+ [ -f /etc/sysctl.d/${file##*/} ] && continue
+ test -f "$file" && sysctl -q -e -p "$file"
+ done
+ for file in /run/sysctl.d/*.conf; do
+ [ -f /etc/sysctl.d/${file##*/} ] && continue
+ test -f "$file" && sysctl -q -e -p "$file"
+ done
+ for file in /etc/sysctl.d/*.conf; do
+ test -f "$file" && sysctl -q -e -p "$file"
+ done
+ sysctl -q -e -p /etc/sysctl.conf
+}
+
if is_yes "$FASTRC" || is_yes "$IN_SHUTDOWN"; then
RC_LOGGING=no
fi
# Some functions to handle PLD Linux-style messages
show() {
- local text len
+ local text len time
+
+ if is_yes "$RC_UPTIME"; then
+ time=$(awk '{printf("[%8.2f] ", $1)}' /proc/uptime)
+ fi
if is_no "$FASTRC" && is_yes "$GETTEXT"; then
- text=$(nls -n "$@")
+ text=$time$(nls -n "$@")
else
- text=$(printf "$@")
+ text=$time$(printf "$@")
fi
len=${#text}
while [ $((len++)) -lt $INIT_COL ]; do
}
ok() {
- echo "$_ok"
+ echo -ne "$_ok${RC_FEDORA+\\r}${RC_FEDORA-\\n}"
}
started() {
}
fail() {
- echo "$_fail"
+ echo -ne "$_fail${RC_FEDORA+\\r}${RC_FEDORA-\\n}"
return 1
}
# (note: some processes like named are chrooted but run outside chroot)
# - do nothing inside vserver
filter_chroot() {
+ # filter by pid namespace if such dir exists for current process
+ # we do filter in containers as stacked containers are possible with LXC
+ if [ -d /proc/$$/ns ]; then
+ local pids
+ pids=$(filter_ns "$@") && set -- "$pids"
+ fi
+
if is_yes "$VSERVER"; then
echo $@
return
fi
+
if [ $# -lt 1 -o ! -d /proc/1 ]; then
echo $@
return
fi
+
local root_dir good_pids="" good_add_pid
for root_pid in $@; do
root_dir=$(resolvesymlink /proc/${root_pid}/root)
echo $good_pids
}
+# similar to filter_chroot, but filter based on /proc/PID/ns/pid value
+filter_ns() {
+ local cur_ns=$(resolvesymlink /proc/$$/ns/pid)
+ [ "$cur_ns" ] || return 1
+
+ local pid ns pids=""
+ # add pids if it matches current pid namespace
+ # we should add pids what do not exist (dead processes),
+ # but not add pids whose namespace does not match
+ # (processes belonging to different NS do exist in /proc)
+ for pid in "$@"; do
+ if [ ! -d /proc/$pid ]; then
+ pids="$pids $pid"
+ continue
+ fi
+ ns=$(resolvesymlink /proc/$pid/ns/pid)
+ if [ "$ns" = "$cur_ns" ]; then
+ pids="$pids $pid"
+ fi
+ done
+ echo $pids
+ return 0
+}
+
# Usage:
# run_cmd Message command_to_run
# run_cmd -a Message command_to_run
;;
--user)
shift
- [ "$1" != "root" ] && prog="/bin/su $1 -s /bin/sh -c \""
user=$1
;;
--fork)
fork=1
- prog="/usr/bin/setsid sh -c \""
end='&'
;;
--chdir)
shift
waittime="$1"
;;
+ --pidfile=?*)
+ pidfile="${1#--pidfile=}"
+ case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac
+ ;;
--pidfile)
shift
pidfile="$1"
esac
shift
done
+ if [ -n "$user" -a "$user" != "root" ]; then
+ prog="/bin/su $user -s /bin/sh -c \""
+ fi
+ if [ "$fork" = "1" ]; then
+ prog="/usr/bin/setsid ${prog:-sh -c \"}"
+ fi
# If command to execute ends with quotation mark, add remaining
# arguments and close quotation.
if [ "$prog" != "${prog%\"}" ]; then
if errors=$(
umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK};
export USER=root HOME=/tmp TMPDIR=/tmp
+
nice=${nice:-$DEFAULT_SERVICE_RUN_NICE_LEVEL}
nice=${nice:-0}
+ # make nice level absolute, not to be dependant of nice level of shell where service started
+ nice=$(($nice - $(nice)))
+
if [ "$closefds" = 1 ]; then
exec 1>&-
exec 2>&-
- exec 0>&-
+ exec 0<&-
elif [ "$redirfds" = 1 ]; then
exec 1>/dev/null
exec 2>/dev/null
- exec 0>/dev/null
+ exec 0</dev/null
else
exec 2>&1
+ exec 0</dev/null
fi
if is_no "$RC_LOGGING"; then
done
IFS=$o
fi
+ set -- "$prog" "$@"
+
+ # use setsid to detach from terminal,
+ # needs pidfile or ssd would check setsid program instead of real program
+ if [ "$pidfile" ]; then
+ set -- /usr/bin/setsid "$@"
+ fi
+
/sbin/start-stop-daemon -q --start \
--nicelevel $nice \
${pidfile:+--pidfile $pidfile} \
${fork:+--background} \
${waitname:+--name $waitname} \
${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \
- --exec "$prog" \
- -- ${1:+"$@"}
+ --exec "$1" \
+ -- "$@"
else
- nice -n $nice initlog -c "$prog" 2>&1
+ nice -n $nice initlog -c "$prog" 2>&1 </dev/null
fi
); then
# A function to stop a program.
killproc() {
- local notset killlevel base pid pidfile result
+ local notset killlevel base pid pidfile result delay=3 try
# Test syntax.
if [ $# = 0 ]; then
- msg_usage " killproc [--pidfile PIDFILE] {program} [-SIGNAME]"
+ msg_usage " killproc [--pidfile|-p PIDFILE] [-d DELAY] {program} [-SIGNAME]"
return 2
fi
while [ "$1" != "${1##-}" ]; do
case $1 in
+ -d)
+ delay="$2"
+ shift 2
+ ;;
--pidfile|-p)
pidfile="$2"
case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac
# experimental start-stop-daemon based killing.
# works only with pidfile
if is_no "$RC_LOGGING" && [ "$pidfile" ]; then
- local sig=${killlevel:--TERM}
+ local sig=${killlevel:--TERM} retry
+ # retry only if signal is not specified,
+ # as otherwise impossible to send HUP if process pid stays in pidfile.
+ if [ "${killlevel+set}" = "set" ]; then
+ # if we send HUP it's ok if process does not die
+ retry="--oknodo"
+ else
+ retry="--retry ${sig#-}/10/${sig#-}/60/KILL/10"
+ fi
/sbin/start-stop-daemon -q --stop \
- --retry ${sig#-}/10/${sig#-}/60/KILL/10 \
+ $retry \
-s ${sig#-} \
${pidfile:+--pidfile $pidfile}
result=$?
if checkpid $pid 2>&1; then
# TERM first, then KILL if not dead
kill -TERM $pid
- usleep 100000
- if checkpid $pid && sleep 1 &&
- checkpid $pid && sleep 3 &&
- checkpid $pid; then
+ usleep 50000
+
+ try=0
+ while [ $try -lt $delay ]; do
+ checkpid $pid || break
+ sleep 1
+ try=$((try+1))
+ done
+ if checkpid $pid; then
# XXX: SIGKILL is sent already on 4th second!
# HARMFUL for example to mysqld (which is already workarounded)
kill -KILL $pid
- usleep 100000
+ usleep 50000
fi
fi
checkpid $pid
# Next try "pidof"
[ -z "$pid" ] && pidof -o $$ -o $PPID -o %PPID -x "$1"
- pid=$(filter_chroot "$pid")
+ pid=$(filter_chroot $pid)
echo $pid
}
else
pid=$(pidof -o $$ -o $PPID -o %PPID -x $daemon)
fi
- pid=$(filter_chroot "$pid")
+ pid=$(filter_chroot $pid)
if [ "$pid" ]; then
cpuset_msg="..."
local base=${daemon##*/}
if [ -z "$pidfile" -a -f /var/run/${base}.pid ]; then
read pid < /var/run/${base}.pid
- pid=$(filter_chroot "$pid")
+ pid=$(filter_chroot $pid)
if [ "$pid" ]; then
nls "%s dead but pid file (%s) exists" "$subsys" /var/run/${base}.pid
return 1
}
upstart_start() {
local service=$1
- is_upstart_running "${service}" && return 0
+ if is_upstart_running "${service}"; then
+ msg_already_running "$service"
+ return 0
+ fi
+
msg_starting "${service}"
if errors=$(/sbin/initctl start ${service} 2>&1) ; then
ok
}
upstart_stop() {
local service=$1
- if ! is_upstart_running "${service}" && ! is_upstart_task "${service}" ; then
+ if ! is_upstart_running "${service}"; then
+ msg_not_running "$name"
return 0
fi
msg_stopping "${service}"