freebsd-skq/libexec/rc/rc.shutdown

117 lines
3.3 KiB
Plaintext
Raw Normal View History

#!/bin/sh
#
# Copyright (c) 1997 Ollivier Robert
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
1999-08-27 23:37:10 +00:00
# $FreeBSD$
#
# Site-specific closing actions for daemons run by init on shutdown,
# or before going single-user from multi-user.
# Output and errors are directed to console by init, and the
# console is the controlling terminal.
stty status '^T' 2> /dev/null
# Set shell to ignore SIGINT (2), but not children;
# shell catches SIGQUIT (3) and returns to single user after fsck.
trap : 2
trap : 3 # shouldn't be needed
HOME=/
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin
export HOME PATH
add ability to set watchdog timeout for a shutdown This change allows to specify a watchdog(9) timeout for a system shutdown. The timeout is activated when the watchdogd daemon is stopped. The idea is to a prevent any indefinite hang during late stages of the shutdown. The feature is implemented in rc.d/watchdogd, it builds upon watchdogd -x option. Note that the shutdown timeout is not actiavted when the watchdogd service is individually stopped by an operator. It is also not activated for the 'shutdown' to the single-user mode. In those cases it is assumed that the operator knows what they are doing and they have means to recover the system should it hang. Significant subchanges and implementation details: - the argument to rc.shutdown, completely unused before, is assigned to rc_shutdown variable that can be inspected by rc scripts - init(8) passes "single" or "reboot" as the argument, this is not changed - the argument is not mandatory and if it is not set then rc_shutdown is set to "unspecified" - however, the default jail management scripts and jail configuration examples have been updated to pass "jail" to rc.shutdown, just in case - the new timeout can be set via watchdogd_shutdown_timeout rc option - for consistency, the regular timeout can now be set via watchdogd_timeout rc option - watchdogd_shutdown_timeout and watchdogd_timeout override timeout specifications in watchdogd_flags - existing configurations, where the new rc options are not set, should keep working as before I am not particularly wed to any of the implementation specifics. I am open to changing or removing any of them as long as the provided functionality is the same (or very close) to the proposed one. For example, I think it can be implemented without using watchdogd -x, by means of watchdog(1) alone. In that case there would be a small window between stopping watchdogd and running watchdog, but I think that that is acceptable. Reviewed by: bcr (man page changes) MFC after: 5 weeks Relnotes: yes Differential Revision: https://reviews.freebsd.org/D21221
2019-10-03 11:23:10 +00:00
rc_shutdown=${1:-"unspecified"}
2003-07-08 02:52:14 +00:00
. /etc/rc.subr
load_rc_config
# reverse_list list
# print the list in reverse order
#
reverse_list()
{
_revlist=
for _revfile in $*; do
_revlist="$_revfile${script_name_sep}$_revlist"
done
echo $_revlist
}
2003-07-08 02:52:14 +00:00
# If requested, start a watchdog timer in the background which
# will terminate rc.shutdown if rc.shutdown doesn't complete
# within the specified time.
#
2003-07-08 02:52:14 +00:00
_rcshutdown_watchdog=
if [ -n "$rcshutdown_timeout" ]; then
debug "Initiating watchdog timer."
2004-06-06 11:46:29 +00:00
sleep $rcshutdown_timeout && (
_msg="$rcshutdown_timeout second watchdog"
_msg="$_msg timeout expired. Shutdown terminated."
2003-07-08 02:52:14 +00:00
logger -t rc.shutdown "$_msg"
echo
2003-07-08 02:52:14 +00:00
echo "$_msg"
date
kill -KILL $$ >/dev/null 2>&1
2003-07-08 02:52:14 +00:00
) &
_rcshutdown_watchdog=$!
fi
2003-07-08 02:52:14 +00:00
# Determine the shutdown order of the /etc/rc.d scripts,
# and perform the operation
#
Improve the RC framework for the clean booting/shutdown of Jails: 1. Feature: for flexibility reasons and as a prerequisite to clean shutdowns, allow the configuration of a stop/shutdown command via rc.conf variable "jail_<name>_exec_stop" in addition to the start/boot command (rc.conf variable "jail_<name>_exec_start"). For backward compatibility reasons, rc.conf variable "jail_<name>_exec" is still supported, too. 2. Debug: Add the used boot/shutdown commands to the debug output of the /etc/rc.d/jail script, too. 3. Security: Run the Jail start/boot command in a cleaned environment to not leak information from the host to the Jail during startup. 4. Feature: Run the Jail stop/shutdown command "jail_<name>_exec_stop" on "/etc/rc.d/jail stop <name>" to allow a graceful shutdown of the Jail before its processes are just killed. 5. Bugfix: When killing the remaining Jail processes give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations usually fail because the resources are still in use. Additionally, if after trying to TERM-inate the processes there are still processes hanging around, finally just KILL them. 6. Bugfix: In rc.shutdown, if running inside a Jail, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct operation of rc.shutdown under jail_<name>_exec_stop="/bin/sh /etc/rc.shutdown". This is analogous to what /etc/rc does inside a Jail. Now the following typical host-configuration for two Jails works as expected and correctly boots and shutdowns the Jails: ----------------------------------------------------------- # /etc/rc.conf: jail_enable="YES" jail_list="foo bar" jail_foo_rootdir="/j/foo" jail_foo_hostname="foo.example.com" jail_foo_ip="192.168.0.1" jail_foo_devfs_enable="YES" jail_foo_mount_enable="YES" jail_foo_exec_start="/bin/sh /etc/rc" jail_foo_exec_stop="/bin/sh /etc/rc.shutdown" jail_bar_rootdir="/j/bar" jail_bar_hostname="bar.example.com" jail_bar_ip="192.168.0.2" jail_bar_devfs_enable="YES" jail_bar_mount_enable="YES" jail_bar_exec_start="/path/to/kjailer -v" jail_bar_exec_stop="/bin/sh -c 'killall kjailer && sleep 60'" ----------------------------------------------------------- # /etc/fstab.foo /v/foo /j/foo/v/foo nullfs rw 0 0 ----------------------------------------------------------- # /etc/fstab.bar /v/bar /j/bar/v/bar nullfs rw 0 0 ----------------------------------------------------------- Reviewed by: freebsd-hackers MFC after: 2 weeks
2004-12-14 14:36:35 +00:00
rcorder_opts="-k shutdown"
if [ `/sbin/sysctl -n security.jail.jailed` -eq 1 ]; then
rcorder_opts="$rcorder_opts -s nojail"
if [ `/sbin/sysctl -n security.jail.vnet` -ne 1 ]; then
rcorder_opts="$rcorder_opts -s nojailvnet"
fi
fi
case ${local_startup} in
[Nn][Oo] | '') ;;
*) find_local_scripts_new ;;
esac
files=`rcorder ${rcorder_opts} /etc/rc.d/* ${local_rc} 2>/dev/null`
2003-07-08 02:52:14 +00:00
for _rc_elem in `reverse_list $files`; do
debug "run_rc_script $_rc_elem faststop"
run_rc_script $_rc_elem faststop
2003-07-08 02:52:14 +00:00
done
2003-07-08 02:52:14 +00:00
# Terminate the background watchdog timer (if it is running)
#
if [ -n "$_rcshutdown_watchdog" ]; then
pkill -TERM -P $_rcshutdown_watchdog >/dev/null 2>&1
2003-07-08 02:52:14 +00:00
fi
# Insert other shutdown procedures here
echo '.'
exit 0