Subject: FreeBSD Jail Boot/Shutdown Procedure Last-Modified: 2004-12-11 13:56 Improve automatic Jail boot/shutdown procedure: 1. allow the configuration of a stop/shutdown command (via $jail__exec_stop) in addition to the start/boot command (via $jail__exec_start). For backward compatibility reasons still support $jail__exec. Also, add the commands to the debug output. 2. Run the jail start/boot command in a cleaned environment through the use of jail(8)'s "-l" option. 3. Run the jail stop/shutdown command $jail__exec_stop on "/etc/rc.d/jail stop " to allow a graceful shutdown of the jail before its processes are just killed. 4. When killing the remaining jail processes, first give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations could fail (resource still in use). Additionally, if after trying to TERMinate the processes there are still processes hanging around, KILL them. 5. In rc.shutdown, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct use of $jail__exec_stop="/bin/sh /etc/rc.shutdown". Now the following usual Jail host-configuration work as expected and correctly starts and stops two jails on "/etc/rc.d/jail start" and "/etc/rc.d/jail stop" commands: ----------------------------------------------------------- # /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 -l /var/log/console.log" 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 ----------------------------------------------------------- The change against -CURRENT follows: Index: defaults/rc.conf =================================================================== RCS file: /home/ncvs/src/etc/defaults/rc.conf,v retrieving revision 1.233 diff -u -d -r1.233 rc.conf --- defaults/rc.conf 1 Dec 2004 22:05:50 -0000 1.233 +++ defaults/rc.conf 11 Dec 2004 15:15:29 -0000 @@ -493,7 +493,8 @@ #jail_example_rootdir="/usr/jail/default" # Jail's root directory #jail_example_hostname="default.domain.com" # Jail's hostname #jail_example_ip="192.168.0.10" # Jail's IP number -#jail_example_exec="/bin/sh /etc/rc" # command to execute in jail +#jail_example_exec_start="/bin/sh /etc/rc" # command to execute in jail for starting +#jail_example_exec_stop="/bin/sh /etc/rc.shutdown" # command to execute in jail for stopping #jail_example_devfs_enable="NO" # mount devfs in the jail #jail_example_fdescfs_enable="NO" # mount fdescfs in the jail #jail_example_procfs_enable="NO" # mount procfs in jail Index: rc.d/jail =================================================================== RCS file: /home/ncvs/src/etc/rc.d/jail,v retrieving revision 1.19 diff -u -d -r1.19 jail --- rc.d/jail 24 Nov 2004 10:44:39 -0000 1.19 +++ rc.d/jail 11 Dec 2004 15:15:30 -0000 @@ -34,7 +34,21 @@ eval jail_hostname=\"\$jail_${_j}_hostname\" eval jail_ip=\"\$jail_${_j}_ip\" eval jail_exec=\"\$jail_${_j}_exec\" - [ -z "${jail_exec}" ] && jail_exec="/bin/sh /etc/rc" + eval jail_exec_start=\"\$jail_${_j}_exec_start\" + eval jail_exec_stop=\"\$jail_${_j}_exec_stop\" + if [ -n "${jail_exec}" ]; then + # simple/backward-compatible execution + jail_exec_start="${jail_exec}" + jail_exec_stop="" + else + # flexible execution + if [ -z "${jail_exec_start}" ]; then + jail_exec_start="/bin/sh /etc/rc" + if [ -z "${jail_exec_stop}" ]; then + jail_exec_stop="/bin/sh /etc/rc.shutdown" + fi + fi + fi # The default jail ruleset will be used by rc.subr if none is specified. eval jail_ruleset=\"\$jail_${_j}_devfs_ruleset\" @@ -65,6 +79,8 @@ debug "$_j procdir: $jail_procdir" debug "$_j ruleset: $jail_ruleset" debug "$_j fstab: $jail_fstab" + debug "$_j exec start: $jail_exec_start" + debug "$_j exec stop: $jail_exec_stop" } # set_sysctl rc_knob mib msg @@ -177,8 +193,8 @@ fi fi _tmp_jail=${_tmp_dir}/jail.$$ - jail -i ${jail_rootdir} ${jail_hostname} \ - ${jail_ip} ${jail_exec} > ${_tmp_jail} 2>&1 + eval jail -l -U root -i ${jail_rootdir} ${jail_hostname} \ + ${jail_ip} ${jail_exec_start} > ${_tmp_jail} 2>&1 [ "$?" -eq 0 ] && echo -n " $jail_hostname" _jail_id=$(head -1 ${_tmp_jail}) tail +2 ${_tmp_jail} >${jail_rootdir}/var/log/console.log @@ -198,7 +214,13 @@ _jail_id=$(cat /var/run/jail_${_jail}.id) if [ ! -z "${_jail_id}" ]; then init_variables $_jail + if [ -n "${jail_exec_stop}" ]; then + eval env -i /usr/sbin/jexec ${_jail_id} ${jail_exec_stop} \ + >> ${jail_rootdir}/var/log/console.log 2>&1 + fi killall -j ${_jail_id} -TERM > /dev/null 2>&1 + sleep 1 + killall -j ${_jail_id} -KILL > /dev/null 2>&1 jail_umount_fs echo -n " $jail_hostname" fi Index: rc.shutdown =================================================================== RCS file: /home/ncvs/src/etc/rc.shutdown,v retrieving revision 1.29 diff -u -d -r1.29 rc.shutdown --- rc.shutdown 17 Oct 2004 13:39:42 -0000 1.29 +++ rc.shutdown 11 Dec 2004 15:15:30 -0000 @@ -80,7 +80,11 @@ # Determine the shutdown order of the /etc/rc.d scripts, # and perform the operation # -files=`rcorder -k shutdown /etc/rc.d/* 2>/dev/null` +rcorder_options="-k shutdown" +if [ `/sbin/sysctl -n security.jail.jailed` -eq 1 ]; then + rcorder_options="$rcorder_options -s nojail" +fi +files=`rcorder ${rcorder_options} /etc/rc.d/* 2>/dev/null` for _rc_elem in `reverse_list $files`; do debug "run_rc_script $_rc_elem faststop"