CHARS="" # Characters displayed on the beginning of show line
CCHARS="$NORMAL" # Color of these characters (look at /etc/sysconfig/init-colors.gentoo example)
-# save from env, set by /sbin/service
-env_upstart=$USE_UPSTART
-
# Source configuration if available - may override default values
[ -r /etc/sysconfig/init-colors ] && . /etc/sysconfig/init-colors
[ -r /etc/sysconfig/system ] && . /etc/sysconfig/system
unset RC_FEDORA || :
fi
-[ "$env_upstart" ] && USE_UPSTART=$env_upstart
-
if [ -z "$VSERVER" -o "$VSERVER" = "detect" ]; then
{
while read _f _ctx; do
VSERVER_ISOLATION_NET=no
if [ "$VSERVER" = "yes" ]; then
if [ -f /proc/self/nsproxy ]; then
+ # older kernels
{
while read _t _data; do
[ "$_t" = "net:" ] && break
done < /proc/self/nsproxy
} 2> /dev/null
+ if [ "${_data##*\(}" = "I)" ]; then
+ VSERVER_ISOLATION_NET=yes
+ fi
+ elif [ -f /proc/self/ninfo ]; then
+ # newer kernels
+ {
+ while read _t _data; do
+ [ "$_t" = "NCaps:" ] && break
+ done < /proc/self/ninfo
+ } 2> /dev/null
+ if [ "${_t}" = "NCaps:" ]; then
+ VSERVER_ISOLATION_NET=yes
+ fi
else
- # assume old kernel mode
- VSERVER_ISOLATION_NET=yes
- fi
- if [ "${_data##*\(}" = "I)" ]; then
+ # assume (very?) old kernel mode
VSERVER_ISOLATION_NET=yes
fi
unset _f _data
# returns OK if $1 contains $2
strstr() {
- local a=$2
- [ "${1#*$a*}" = "$1" ] && return 1
+ [ "${1#*$2*}" = "$1" ] && return 1
return 0
}
local file
for file in /usr/lib/sysctl.d/*.conf; do
- [ -f /run/sysctl.d/${file##*/} ] && continue
- [ -f /etc/sysctl.d/${file##*/} ] && continue
+ [ -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
+ [ -f "/etc/sysctl.d/${file##*/}" ] && continue
test -f "$file" && sysctl -q -e -p "$file"
done
for file in /etc/sysctl.d/*.conf; do
# (note: some processes like named are chrooted but run outside chroot)
# - do nothing inside vserver
filter_chroot() {
+ # no pids, exit early
+ [ $# -eq 0 ] && return
+
# 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
done
}
+# inner function used by daemon().
+# do not call this directly, as it expects variables being inherited.
+# also it expects to be called from subshell as it exports env.
+# it expects options parsed by daemon() and command to be executed in "$@".
+_daemon_exec() {
+ local prog=""
+ 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<&-
+ elif [ "$redirfds" = 1 ]; then
+ exec 1>/dev/null
+ exec 2>/dev/null
+ exec 0</dev/null
+ else
+ exec 2>&1
+ exec 0</dev/null
+ fi
+
+ if is_no "$RC_LOGGING"; then
+ prog=$1; shift
+ if [ ! -x $prog ]; then
+ logger -t rc-scripts -p daemon.debug "daemon: Searching PATH for $prog, consider using full path in initscript"
+ local a o=$IFS
+ IFS=:
+ for a in $PATH; do
+ if [ -x $a/$prog ]; then
+ prog=$a/$prog
+ break
+ fi
+ done
+ IFS=$o
+ fi
+ set -- "$prog" "$@"
+
+ # use setsid to detach from terminal,
+ # NOTE: setsid needs to be "outer" program
+ # otherwise start-stop-daemon would capture the setsid pid not the actual program
+
+ prog=$1; shift
+ /usr/bin/setsid \
+ /sbin/start-stop-daemon -q --start \
+ --nicelevel $nice \
+ ${pidfile:+--pidfile $pidfile} \
+ ${makepid:+--make-pidfile} \
+ ${user:+--chuid $user} \
+ ${chdir:+--chdir "$chdir"} \
+ ${fork:+--background} \
+ ${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \
+ --exec "$prog" \
+ -- "$@"
+ else
+ if [ "$fork" = "1" ]; then
+ export PIDFILE="/dev/null"
+ if [ "$makepid" ] && [ "$pidfile" ]; then
+ export PIDFILE="$pidfile"
+ fi
+ set -- /lib/rc-scripts/makepid "$@"
+ set -- /usr/bin/setsid "$@"
+ fi
+ if [ -n "$user" -a "$user" != "root" ]; then
+ set -- /bin/runuser -u "$user" -- "$@"
+ fi
+
+ nice -n $nice initlog -c "$*" 2>&1 </dev/null
+ fi
+}
+
# A function to start a program (now it's useful on read-only filesystem too)
daemon() {
- local errors="" prog="" end="" waitname="" waittime=""
+ local errors="" waitname="" waittime=0
local exit_code=0
local nice=$SERVICE_RUN_NICE_LEVEL
local fork user closefds redirfds pidfile makepid chdir=/
- # NOTE: if you wonder how the shellish (by syntax) $prog works in ssd mode,
- # then the answer is: it totally ignores $prog and uses "$@" itself.
-
while [ $# -gt 0 ]; do
case $1 in
'')
;;
--fork)
fork=1
- end='&'
;;
--chdir)
shift
;;
--makepid)
makepid=1
+ # makepid implies fork
+ fork=1
;;
-*|+*)
nice=$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
- prog="$prog $*$end\""
- else
- prog="$prog $*$end"
- fi
_daemon_set_ulimits
busy
cd $chdir
[ -n "$SERVICE_CPUSET" ] && is_yes "$CPUSETS" && echo $$ > "/dev/cpuset/${SERVICE_CPUSET}/tasks"
- 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>&-
- elif [ "$redirfds" = 1 ]; then
- exec 1>/dev/null
- exec 2>/dev/null
- exec 0>/dev/null
- else
- exec 2>&1
- fi
-
- if is_no "$RC_LOGGING"; then
- prog=$1; shift
- if [ ! -x $prog ]; then
- logger -t rc-scripts -p daemon.debug "daemon: Searching PATH for $prog, consider using full path in initscript"
- local a o=$IFS
- IFS=:
- for a in $PATH; do
- if [ -x $a/$prog ]; then
- prog=$a/$prog
- break
- fi
- done
- IFS=$o
- fi
- /sbin/start-stop-daemon -q --start \
- --nicelevel $nice \
- ${pidfile:+--pidfile $pidfile} \
- ${makepid:+--make-pidfile} \
- ${user:+--chuid $user} \
- ${chdir:+--chdir "$chdir"} \
- ${fork:+--background} \
- ${waitname:+--name $waitname} \
- ${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \
- --exec "$prog" \
- -- ${1:+"$@"}
- else
- nice -n $nice initlog -c "$prog" 2>&1 </dev/null
- fi
- ); then
-
- if [ -n "$waitname" -a -n "$waittime" ]; then
- # Save basename.
- base=${waitname##*/}
- # Find pid.
- pid=$(pidofproc "$waitname" "$pidfile")
- [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile")
- i=0
- while [ "$i" -lt "$waittime" ]; do
- i=$((i + 1))
- checkpid $pid && sleep 1 || break
- done
+ if errors=$(_daemon_exec "$@"); then
+ # wait for process (or pidfile) to be created
+ if [ "$waittime" -gt 0 ]; then
+ # waitname can be empty, as if pidfile is in use, it is not relevant
+ waitproc "$waittime" "$waitname" "$pidfile"
fi
log_success "$1 startup"
ok
return $exit_code
}
+# wait (in seconds) for process (or pidfile) to be created
+# example: waitproc 30 httpd /var/run/httpd.pid
+waitproc() {
+ local waittime=$1 procname=$2 pidfile=$3
+ local pid
+ local now=$(date +%s)
+ local maxtime=$(($now + $waittime))
+
+ if [ -z "$procname" -a -z "$pidfile" ]; then
+ msg_usage "waitproc: procname or pidfile must be specified"
+ return 2
+ fi
+
+ while [ "$(date +%s)" -lt "$maxtime" ]; do
+ pid=$(pidofproc "$procname" "$pidfile")
+ [ -n "$pid" ] && break
+
+ # start-stop-daemon uses same delay
+ usleep 20000
+ done
+}
+
# A function to stop a program.
killproc() {
local notset killlevel base pid pidfile result delay=3 try
# works only with pidfile
if is_no "$RC_LOGGING" && [ "$pidfile" ]; then
local sig=${killlevel:--TERM} retry
- # retry only if signal is not specified,
+ # do not retry if signal is specified,
# as otherwise impossible to send HUP if process pid stays in pidfile.
- if [ "${killlevel+set}" = "set" ]; then
+ # however, do retry if --waitfortime was specified
+ if [ "${killlevel+set}" = "set" ] && [ -z "$waittime" ]; then
# if we send HUP it's ok if process does not die
retry="--oknodo"
else
- retry="--retry ${sig#-}/10/${sig#-}/60/KILL/10"
+ local waitretry
+ : ${waittime=10}
+ : ${waitretry=$(($waittime * 2))}
+
+ # 1. kill with $sig, wait $delay
+ # 2. kill with $sig, wait $waittime
+ # 3. kill with KILL, wait $waitretry
+ retry="--retry ${sig#-}/${delay}/${sig#-}/${waittime}/KILL/${waitretry}"
fi
/sbin/start-stop-daemon -q --stop \
$retry \
+ ${waitname:+--name $waitname} \
-s ${sig#-} \
${pidfile:+--pidfile $pidfile}
result=$?
*) pidfile="/var/run/$pidfile";;
esac
if [ -f "${pidfile}" ]; then
- local p pid=""
+ local p
for p in $(< "${pidfile}"); do
[ -z "$(echo "$p" | awk '{gsub(/[0-9]/,"");print;}')" ] && pid="$pid $p"
done
fi
- # Next try "pidof"
- [ -z "$pid" ] && pidof -o $$ -o $PPID -o %PPID -x "$1"
+ # Next try "pidof" if pidfile is not specified
+ if [ -z "$pid" ] && [ -z "$2" ]; then
+ pid=$(pidof -o $$ -o $PPID -o %PPID -x "$1")
+ fi
+
pid=$(filter_chroot $pid)
echo $pid
}
}
use_upstart () {
- # True when upstart-event-based boot should be used
- is_yes "$USE_UPSTART" && return 0
- is_no "$USE_UPSTART" && return 1
- if [ ! -x /sbin/initctl ] ; then
- USE_UPSTART="no"
- return 1
- fi
- local cmdline=$(cat /proc/cmdline 2>/dev/null)
- if strstr "$cmdline" "pld.no-upstart" ; then
- USE_UPSTART="no"
- return 1
- else
- USE_UPSTART="yes"
- return 0
- fi
+ return 1
}
-
emit () {
- # emit upstart signal
- # only when 'upstart' boot is enabled
- use_upstart || return 0
- /sbin/initctl emit "$@"
+ return 0
}
-
is_upstart_task() {
- # Return 0 if the given service is an upstart task.
- grep -q '^task' "/etc/init/$1.conf"
+ return 1
}
is_upstart_running() {
- # Return 0 if the given service is running via upstart
- initctl status "$1" 2>/dev/null | grep -q running
+ return 1
}
upstart_start() {
- local service=$1
- 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
- return 0
- else
- fail
- echo "$errors" >&2
- return 1
- fi
+ return 1
}
upstart_stop() {
- local service=$1
- if ! is_upstart_running "${service}"; then
- msg_not_running "$name"
- return 0
- fi
- msg_stopping "${service}"
- if errors=$(/sbin/initctl stop ${service}) ; then
- ok
- return 0
- else
- fail
- echo "$errors" >&2
- return 1
- fi
+ return 1
}
upstart_reload() {
- local service=$1
- if ! is_upstart_running "${service}" && ! is_upstart_task "${service}" ; then
- return 0
- fi
- msg_reloading "${service}"
- if errors=$(/sbin/initctl reload ${service}) ; then
- ok
- return 0
- else
- fail
- echo "$errors" >&2
- return 1
- fi
+ return 0
}
upstart_status() {
- # get service status
- # should be compliant with
- # http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
- local service=$1
- local status
- if is_upstart_task "${service}" ; then
- # we probably should have a way to handle task status
- return 0
- fi
- if ! status=$(/sbin/initctl status "${service}") ; then
- # program or service status is not known
- return 4
- fi
- if strstr "$status" "running" ; then
- # program is running or service is OK
- echo "$status"
- return 0
- else
- # program is not running
- echo "$status"
- return 3
- fi
- # TODO: other statuses
+ return 1
}
-
_upstart_controlled() {
- # If the service is to be handled by upstart
- # execute the start/stop/etc. commands the upstart way
- if ! use_upstart; then
- return 0
- fi
- local script=$1
- shift
- local command=$1
- [ $# -gt 0 ] && shift
- local name=$(basename "$script")
- if [ ! -f /etc/init/${name}.conf ] ; then
- return 0
- fi
- local commands
- local extra_commands
- local has_configtest
- if [ "$1" = "--except" ] ; then
- shift
- commands="$*"
- for cmd in $commands ; do
- if [ "$command" = "$cmd" ] ; then
- return 0
- fi
- case "$cmd" in
- start|stop|status|reload|restart|try-restart|force-reload)
- ;;
- configtest)
- has_configtest=yes
- extra_commands="|$cmd"
- ;;
- *)
- extra_commands="|$cmd"
- ;;
- esac
- done
- elif [ -n "$*" ] ; then
- commands="$*"
- local cmd
- local found=0
- # is there a better way
- for cmd in $commands ; do
- if [ "$command" = "$cmd" ] ; then
- found=1
- break;
- fi
- done
- if [ $found = 0 ] ; then
- # let the script handle it
- return 0
- fi
- fi
- case "$command" in
- start)
- upstart_start $name
- exit $?
- ;;
- stop)
- upstart_stop $name
- exit $?
- ;;
- status)
- upstart_status $name
- exit $?
- ;;
- restart)
- if is_yes "$has_configtest" ; then
- "$script" configtest || exit 1
- fi
- upstart_stop $name
- upstart_start $name
- exit $?
- ;;
- try-restart)
- if ! is_upstart_running "$name" ; then
- exit 0
- fi
- if is_yes "$has_configtest" ; then
- "$script" configtest || exit 1
- fi
- upstart_stop $name
- upstart_start $name
- exit $?
- ;;
- reload)
- if is_yes "$has_configtest" ; then
- "$script" configtest || exit 1
- fi
- if is_upstart_task "$name" ; then
- nls "$command not implemented for $name"
- exit 3
- else
- upstart_reload "$name"
- exit $?
- fi
- ;;
- force-reload)
- if is_yes "$has_configtest" ; then
- "$script" configtest || exit 1
- fi
- if is_upstart_task "$name" ; then
- upstart_stop "$name"
- upstart_start "$name"
- exit $?
- else
- upstart_reload "$name"
- exit $?
- fi
- ;;
- *)
- msg_usage "$0 {start|stop|restart|reload|force-reload|status$extra_commands}"
- exit 3
- ;;
- esac
- return 1 # should not happen
+ return 0
}
-
-# Usage:
-# somewhere at the begining of init script:
-# upstart_controlled
-# - to pass implement all upstart commands via initctl
-# start, stop, status, restart, reload and force_reload
-# are implemented
-# upstart_controlled command...
-# - to pass handle only specific commands the upstart way
-# and leave the rest to the script
-#
alias upstart_controlled='_upstart_controlled $0 "$@"'
rc_gettext_init