2020-11-06 20:37:13 +01:00
#!/bin/sh
2020-11-29 18:46:50 +01:00
version=1.08
2020-11-06 20:37:13 +01:00
usage_jaildk() {
beg=`tput -T ${TERM:-cons25} md`
end=`tput -T ${TERM:-cons25} me`
usage=$(cat <<EOF
This is jaildk version $version, a jail management toolkit.
Usage: $0 <command> <mode-args>
${beg}Building Jails:${end}
2020-11-29 16:22:36 +01:00
base -b <name> [-w] - build a new base
build <jail> <mode> [-b <base>] [-v <version>] - install a build chroot of a jail
create - create a new jail from a template
clone -s <src> -d <dst> [-o <v>] [-n <v>] - clone an existing jail or jail version
fetch - fetch current port collection
2020-11-06 20:37:13 +01:00
${beg}Installing Jails:${end}
2020-11-29 16:22:36 +01:00
install <jail> <mode> [-r function] - install a jail (prepare mounts, devfs etc)
2020-11-29 18:46:50 +01:00
uninstall <jail> [-w] - uninstall a jail
remove <jail> - remove a jail or a jail version
reinstall <jail> - stop, remove, install and start a jail
2020-11-06 20:37:13 +01:00
${beg}Maintaining Jails:${end}
2020-11-29 18:46:50 +01:00
start <jail> - start a jail
stop <jail> - stop a jail
restart <jail> - restart a jail
status [<jail>] - display a jail's status
rc <jail> <mode> [-r <rc.d script>] - execute an rc-script inside a jail
2020-11-06 20:37:13 +01:00
${beg}Managing Jails:${end}
2020-11-29 18:46:50 +01:00
login <jail> [<user>] - login into a jail
blogin <jail> - chroot into a build jail
2020-11-06 20:37:13 +01:00
2020-11-28 20:41:05 +01:00
${beg}Transferring Jails:${end}
2020-11-29 18:46:50 +01:00
freeze <jail> [-a -b -v <version>] - freeze (build an image of) a jail
thaw <image> - thaw (install) an image of a jail
2020-11-28 20:41:05 +01:00
2020-11-29 18:46:50 +01:00
${beg}Getting help:${end}
help <command> - request help on <command>
2020-11-06 20:37:13 +01:00
EOF
)
2020-11-29 18:46:50 +01:00
echo "$usage"
exit 1
}
usage_help() {
command=$1
usage="usage_${command}"
if ! type "$usage" > /dev/null 2>&1; then
die "Unknown command $command!"
else
$usage
fi
2020-11-06 20:37:13 +01:00
}
ex() {
echo $rcscript - $*
$*
}
err () {
2020-11-27 19:08:57 +01:00
echo "$@" >&2
2020-11-06 20:37:13 +01:00
}
bold() {
if [ -z "$BOLD_ON" ]; then
BOLD_ON=`tput -T ${TERM:-cons25} md`
export BOLD_ON
BOLD_OFF=`tput -T ${TERM:-cons25} me`
export BOLD_OFF
fi
echo -n "$BOLD_ON"
echo "$@"
echo -n "$BOLD_OFF"
}
2020-11-29 18:46:50 +01:00
fin() {
echo "$*" >&2
exit
}
2020-11-06 20:37:13 +01:00
die() {
bold "$*" >&2
exit 1
}
load-jail-config() {
jail=$1
if test -d $j/etc/$jail; then
. $j/etc/$jail/jail.conf
else
die "Jail $jail is not configured!"
fi
}
die_if_not_exist() {
jail=$1
which=$2
2020-11-28 20:41:05 +01:00
VERSION=$3
2020-11-06 20:37:13 +01:00
if test -z "$which"; then
which="Jail"
fi
2020-11-28 20:41:05 +01:00
2020-11-06 20:37:13 +01:00
if ! test -d $j/etc/$jail; then
die "$which $jail doesn't exist!"
fi
2020-11-28 20:41:05 +01:00
if test -n "$VERSION"; then
if ! test -d $j/etc/$jail/etc-$VERSION; then
die "$which $jail $version doesn't exist!"
fi
fi
2020-11-06 20:37:13 +01:00
}
2020-11-29 16:22:36 +01:00
usage_build() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 build <jail> [<start|stop|status>] [-b <base>] [-v <version>]
Mount <jail> to $j/build read-writable for maintenance. Options:
-b <base> Use specified <base>. default: use configured base.
-v <version> Mount <version> of <jail>.
<mode> One of start, stop or status. default: start."
2020-11-29 16:22:36 +01:00
}
2020-11-06 20:37:13 +01:00
jaildk_build() {
jail=$1
mode=$2
2020-11-29 16:22:36 +01:00
shift
shift
base=''
version=''
2020-11-06 20:37:13 +01:00
2020-11-29 16:22:36 +01:00
while getopts "b:v:" arg; do
case $arg in
2020-11-29 18:46:50 +01:00
b) base=${OPTARG};;
2020-11-29 16:22:36 +01:00
v) version=${OPTARG};;
*) usage_build;;
esac
done
2020-11-27 08:52:58 +01:00
2020-11-06 20:37:13 +01:00
if test -z "$mode"; then
2020-11-29 18:46:50 +01:00
mode=start
2020-11-06 20:37:13 +01:00
fi
2020-11-29 16:22:36 +01:00
die_if_not_exist $jail $version
load-jail-config $jail
2020-11-27 23:21:34 +01:00
if test -n "$buildbase"; then
2020-11-27 19:08:57 +01:00
base="$buildbase"
2020-11-27 08:52:58 +01:00
elif test -z "$base"; then
2020-11-29 16:22:36 +01:00
# nothing configured, use default: latest
2020-11-06 20:37:13 +01:00
base=`ls $j/base | tail -1`
fi
2020-11-28 11:51:38 +01:00
# install the jail to build/
2020-11-29 16:22:36 +01:00
jaildk_install $jail $mode -r all -w -b $base -v $version
2020-11-28 11:18:39 +01:00
2020-11-28 11:51:38 +01:00
case $mode in
start)
# make it usable
ex chroot $j/build/$jail /etc/rc.d/ldconfig onestart
2020-11-28 12:35:48 +01:00
ex mkdir -p $j/build/$jail/usr/local/db
2020-11-28 11:51:38 +01:00
;;
esac
}
2020-11-28 12:26:24 +01:00
jaildk_rc_mtree() {
jail=$1
mode=$2
base=$3
version=$4
rw=$5
2020-11-29 18:46:50 +01:00
rcscript=mtree
2020-11-28 12:26:24 +01:00
if [ $mode = "start" ]; then
if test -n "$rw"; then
run=$j/build/$jail/
else
run=$j/run/$jail/
fi
ex mtree -p $run -Ue -f $j/etc/$jail/mtree.conf | grep -v "extra:"
fi
}
2020-11-28 11:51:38 +01:00
jaildk_rc_rcoff() {
# avoid starting services inside the build chroot
2020-11-28 12:26:24 +01:00
# + jaildk_rc_rcoff db start 12.1-RELEASE-p10 20201026
2020-11-28 11:51:38 +01:00
jail=$1
mode=$2
2020-11-28 12:26:24 +01:00
BASE=$3
VERSION=$4
rw=$5
2020-11-28 11:51:38 +01:00
rcscript=rcoff
if test -n "$rw"; then
# not required in run mode
case $mode in
start)
2020-11-28 11:59:19 +01:00
if mount | egrep -q "rcoff.*build/$jail"; then
bold "union mount $j/build/jail/etc already mounted"
else
if ! test -d $j/etc/rcoff; then
# in order to be backwards compatible to older jaildk
# create the rcoff directory on the fly
2020-11-28 12:36:49 +01:00
mkdir -p $j/etc/rcoff
2020-11-28 11:59:19 +01:00
( echo "#!/bin/sh"
echo 'echo "$0 disabled in build chroot!"' ) > $j/etc/rcoff/rc
fi
ex mount -t unionfs $j/etc/rcoff $j/build/$jail/etc
2020-11-28 11:51:38 +01:00
fi
;;
stop)
# might fail if executed on a yet not union'ed etc
if mount | egrep -q "rcoff.*build/$jail"; then
ex umount $j/build/$jail/etc
fi
;;
esac
fi
2020-11-06 20:37:13 +01:00
}
2020-11-27 08:52:58 +01:00
jaildk_rc_ports() {
jail=$1
mode=$2
2020-11-28 12:26:24 +01:00
BASE=$3
VERSION=$4
rw=$5
2020-11-27 08:52:58 +01:00
rcscript=ports
load-jail-config $jail
2020-11-27 19:08:57 +01:00
if test -n "$ports"; then
version="$ports"
fi
2020-11-27 08:52:58 +01:00
if test -n "$buildbase" -a -n "$rw"; then
# we only support ports if a buildbase is configured
case $mode in
start)
if mount -v | grep -q " $j/build/$jail/usr/ports "; then
bold "$j/build/$jail/usr/ports already mounted!"
else
ex mount -t nullfs -o rw $j/ports/$version $j/build/$jail/usr/ports
fi
;;
stop)
if mount -v | grep -q " $j/build/$jail/usr/ports "; then
ex umount $j/build/$jail/usr/ports
else
bold "$j/build/$jail/usr/ports not mounted!"
fi
;;
esac
fi
}
2020-11-06 20:37:13 +01:00
jaildk_rc_mount() {
jail=$1
mode=$2
2020-11-28 12:26:24 +01:00
BASE=$3
VERSION=$4
rw=$5
2020-11-06 20:37:13 +01:00
rcscript=mount
load-jail-config $jail
conf=$j/etc/$jail/$rcscript.conf
if ! test -e "$conf"; then
return
fi
if test -n "$rw"; then
run=$j/build
if test -n "$BASE"; then
base=$BASE
fi
if test -n "$VERSION"; then
version=$VERSION
fi
else
run=$j/run
fi
die_if_not_exist $jail
# parse the config and (u)mount
case $mode in
stop)
tail -r $conf | grep -v "#"
;;
*)
grep -v "#" $conf
;;
esac | while read LINE; do
# This command expands variables and performs field-splitting:
set -- $(eval echo \""$LINE"\")
# Skip empty lines:
case "$1" in
"") continue ;;
esac
src=$1
dest=$2
fs=$3
opts=$4
size=$5
perm=$6
if test -n "$rw"; then
2020-11-25 11:09:10 +01:00
if ! echo $src | grep -q base/; then
opts=`echo "$opts" | sed 's/ro/rw/g'`
fi
2020-11-06 20:37:13 +01:00
fi
case $mode in
start)
if mount -v | grep " $run/$dest " > /dev/null ; then
bold "$run/$dest already mounted!"
else
case $fs in
mfs)
ex mdmfs -o $opts -s $size -p $perm md $run/$dest
;;
nullfs)
source=$j/$src
if echo $src | egrep -q "^/"; then
source=$src
fi
2020-11-27 19:08:57 +01:00
if ! test -d "$source"; then
die "Source dir $source doesn't exist!"
fi
if ! test -d "$run/$dest"; then
die "Dest dir $run/$dest doesn't exist!"
fi
2020-11-06 20:37:13 +01:00
ex mount -t $fs -o $opts $source $run/$dest
;;
devfs)
ex mount -t devfs dev $run/$dest
;;
*)
bold "unknown filesystem type $fs!"
;;
esac
fi
;;
stop)
if mount -v | grep " $run/$dest " > /dev/null ; then
ex umount $run/$dest
if mount -v | grep " $run/$dest " > /dev/null ; then
# still mounted! forcing
ex umount -f $run/$dest
fi
else
bold "$run/$dest not mounted!"
fi
;;
status)
if mount -v | grep " $run/$dest " > /dev/null ; then
echo "$run/$dest mounted"
else
bold "$run/$dest not mounted"
fi
;;
*)
bold "Usage: $0 install <jail> mount {start|stop|status|restart}"
;;
esac
done
}
2020-11-29 16:22:36 +01:00
usage_install() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 install <jail> [<mode>] [-r rc-function]
2020-11-29 16:22:36 +01:00
Install <jail> according to its config. Options:
<mode> Mode can either be start, stop or status. default: start
-r <function> Only execute function with <mode> parameter. default: all.
Available rc.d-scripts: $RCSCRIPTS_START"
2020-11-06 20:37:13 +01:00
}
jaildk_install() {
jail=$1
2020-11-29 16:22:36 +01:00
mode=$2
shift
shift
rcd=''
2020-11-06 20:37:13 +01:00
2020-11-29 16:22:36 +01:00
# options -b -w -v are undocumented, used by jaildk_build() only
rw=''
base=''
version=''
2020-11-29 18:46:50 +01:00
while getopts "r:b:v:w" arg; do
2020-11-29 16:22:36 +01:00
case $arg in
w) rw=1;;
b) base=${OPTARG};;
v) version=${OPTARG};;
r) rcd=${OPTARG};;
2020-11-29 19:03:57 +01:00
*) usage_install;;
2020-11-29 16:22:36 +01:00
esac
done
2020-11-06 20:37:13 +01:00
if test -z "$jail"; then
2020-11-29 16:22:36 +01:00
usage_install
2020-11-06 20:37:13 +01:00
fi
2020-11-29 16:22:36 +01:00
if test -z "$mode"; then
2020-11-06 20:37:13 +01:00
mode=start
fi
2020-11-29 16:22:36 +01:00
if test -z "$rcd"; then
# default just install everything
rcd=all
2020-11-06 20:37:13 +01:00
fi
2020-11-29 16:22:36 +01:00
case $mode in
start|stop|restart|status) :;;
*) usage_install;;
esac
2020-11-06 20:37:13 +01:00
die_if_not_exist $jail
if test "$rcd" = "all"; then
2020-11-28 11:51:38 +01:00
case $mode in
start) rcscripts="$RCSCRIPTS_START";;
stop) rcscripts="$RCSCRIPTS_STOP";;
esac
2020-11-06 20:37:13 +01:00
else
rcscripts="jaildk_rc_${rcd}"
if ! type "$rcscripts" > /dev/null 2>&1; then
die "rc function $rcd doesn't exist!"
fi
fi
case $mode in
start)
bold "Installing jail $jail"
;;
stop)
bold "Unstalling jail $jail"
;;
esac
2020-11-26 22:25:45 +01:00
2020-11-06 20:37:13 +01:00
for rcscript in $rcscripts; do
2020-11-28 12:26:24 +01:00
$rcscript $jail $mode $base $version $rw || exit 1
2020-11-06 20:37:13 +01:00
done
}
2020-11-29 18:46:50 +01:00
usage_uninstall() {
fin "Usage: $0 uninstall <jail> [-w]
Uninstall <jail>. Options:
-w Uninstall writable build chroot."
}
2020-11-06 20:37:13 +01:00
jaildk_uninstall() {
# wrapper around _install
jail=$1
2020-11-29 18:46:50 +01:00
shift
rw=''
while getopts "w" arg; do
case $arg in
w) rw=1;;
*) usage_uninstall;;
esac
done
2020-11-06 20:37:13 +01:00
if test -z "$jail"; then
2020-11-29 18:46:50 +01:00
usage_uninstall
2020-11-06 20:37:13 +01:00
fi
die_if_not_exist $jail
if jls | egrep -q "${jail}"; then
die "Jail $jail($version) is still running, stop it before removing!"
fi
2020-11-29 16:22:36 +01:00
jaildk_install $jail stop -r all -w
}
usage_base() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 base -b <basename|basedir> [-w]
Build a base directory from bsd install media. Options:
2020-11-29 16:22:36 +01:00
-b <name> <name> can be the name of a base (e.g. 12.2-RELEASE)
or a directory where it shall be created
-w Create a writable base, including compiler and other
build stuff. Use this if you want to use the ports
collection."
2020-11-06 20:37:13 +01:00
}
jaildk_base() {
2020-11-29 16:22:36 +01:00
base=""
rw=""
while getopts "b:w" arg; do
case $arg in
w) rw=1;;
b) base=${OPTARG};;
*) usage_base;;
esac
done
2020-11-27 08:52:58 +01:00
if test -z "$base"; then
2020-11-29 16:22:36 +01:00
usage_base
2020-11-06 20:37:13 +01:00
fi
removelist="tests
usr/bin/objdump
usr/bin/llvm-profdata
usr/bin/ranlib
usr/bin/ar
usr/bin/as
usr/bin/llvm-tblgen
usr/bin/llvm-symbolizer
usr/bin/llvm-cov
usr/bin/llvm-objdump
usr/bin/ld.lld
usr/bin/lldb
usr/bin/cpp
usr/bin/clang-cpp
usr/bin/clang++
usr/bin/clang
usr/bin/cc
usr/bin/c++
usr/bin/lex
usr/bin/lex++
usr/bin/flex
usr/bin/flex++
usr/bin/telnet
usr/bin/kadmin
usr/bin/kcc
usr/bin/kdestroy
usr/bin/kdump
usr/bin/keylogin
usr/bin/keylogout
usr/bin/kf
usr/bin/kgetcred
usr/bin/kinit
usr/bin/klist
usr/bin/kpasswd
usr/bin/krb5-config
usr/bin/ksu
usr/bin/kswitch
usr/bin/ktrace
usr/bin/ktrdump
usr/bin/finger
usr/bin/crunch*
usr/bin/ibv*
usr/bin/nc
usr/bin/pftp
usr/bin/ssh*
usr/bin/scp
usr/bin/sftp
usr/bin/svn*
usr/bin/yacc
usr/include
usr/lib/*.a
usr/lib32/*.a
usr/share/doc
usr/share/dict
usr/share/examples
usr/share/man
rescue
media
mnt
2020-11-27 23:21:34 +01:00
boot
var/run
var/cache
var/tmp"
2020-11-27 08:52:58 +01:00
if echo "$base" | egrep -vq "^/"; then
basedir=$j/base/$base
else
basedir=$base
2020-11-06 20:37:13 +01:00
fi
if test -d "$basedir"; then
echo "base $basedir already exist!"
exit 1
else
ex mkdir -p $basedir
2020-11-29 18:46:50 +01:00
bsdinstall jail $basedir || exit 1
2020-11-06 20:37:13 +01:00
2020-11-27 19:08:57 +01:00
if test -z "$rw"; then
# run base
2020-11-27 08:52:58 +01:00
for file in $removelist; do
ex rm -rf $basedir/$file
done
2020-11-27 19:08:57 +01:00
else
# build base with ports support
2020-11-27 08:52:58 +01:00
ex mkdir -p $basedir/usr/ports
fi
2020-11-27 19:08:57 +01:00
ex mkdir $basedir/home
2020-11-06 20:37:13 +01:00
ex rm -rf $basedir/var/db
ex ln -s /usr/local/db $basedir/var/db
2020-11-27 19:08:57 +01:00
2020-11-27 23:21:34 +01:00
# add some symlinks from /var to /tmp to make pkg work properly
2020-11-28 11:18:39 +01:00
ex rm -rf $basedir/var/tmp $basedir/var/cache $basedir/var/run
ex ln -s /tmp $basedir/var/tmp
ex ln -s /tmp $basedir/var/cache
ex ln -s /tmp $basedir/var/run
2020-11-27 23:21:34 +01:00
2020-11-27 19:08:57 +01:00
if test -n "$rw"; then
echo "You have choosen to create a build base with ports support"
echo -n "Want to fetch the ports collection now [Yn]? "
read yesno
case $yesno in
y|Y|yes|YES)
jaildk_fetch
;;
esac
fi
2020-11-06 20:37:13 +01:00
fi
}
clone() {
srcdir=$1
dstdir=$2
if test -d $srcdir; then
if ! test -d $dstdir; then
mkdir -p $dstdir
fi
ex cpdup -x $srcdir $dstdir
else
echo "$srcdir doesn't exist, ignored"
fi
}
2020-11-29 16:22:36 +01:00
usage_clone() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 clone -s <jail> -d <jail> [-o <version>] [-n <version>]
2020-11-29 16:22:36 +01:00
-s <jail> Source jail to clone from
-d <jail> Destionation jail to create from source
-o <version> Old version
-n <version> New version
Hints:
- if no source version has been given, tha latest version will be used.
- if no new version has been given, source version will be used.
- if source and new jail are the same, both versions must be given
and a new version of the same jail will be created (update)"
}
2020-11-06 20:37:13 +01:00
jaildk_clone() {
2020-11-29 16:22:36 +01:00
src=''
new=''
srcversion=''
newversion=''
update=''
while getopts "s:d:o:n:" arg; do
case $arg in
o) srcversion=${OPTARG};;
n) newversion=${OPTARG};;
s) src=${OPTARG};;
d) new=${OPTARG};;
*) usage_clone;;
esac
done
2020-11-06 20:37:13 +01:00
if test -z "$new"; then
2020-11-29 16:22:36 +01:00
usage_clone
2020-11-06 20:37:13 +01:00
fi
if test "$src" = "$new"; then
# same jail, expect different versions
if test -z "$newversion" -o -z "$srcversion"; then
die "source and new version required!"
fi
if test "$srcversion" = "$newversion"; then
die "new version must be different from source version!"
fi
update=1
else
# clone from A to B
die_if_not_exist $src "Source jail"
if test -z "$srcversion"; then
. $j/etc/$src/jail.conf
srcversion=$version
newversion=$version
else
if ! test -d $j/etc/$src/etc-$srcversion; then
die "Version $srcversion of source jail $src doesn't exist!"
else
if test -z "$newversion"; then
newversion=$srcversion
fi
fi
fi
fi
clone $j/log/$src-$srcversion $j/log/$new-$newversion
clone $j/home/$src/root-$srcversion $j/home/$new/root-$newversion
clone $j/etc/$src/etc-$srcversion $j/etc/$new/etc-$newversion
clone $j/etc/$src/local-etc-$srcversion $j/etc/$new/local-etc-$newversion
if test -z "$update"; then
clone $j/data/$src/www $j/data/$new/www
clone $j/data/$src/spool $j/data/$new/spool
ex cp -pRp $j/etc/$src/mount.conf $j/etc/$src/ports.conf $j/etc/$src/mtree.conf $j/etc/$new/
echo "Creating $j/etc/$src/jail.conf"
cat $j/etc/$src/jail.conf | egrep -v "^(name|version)=" > $j/etc/$new/jail.conf
(echo "name=$new"; echo "version=$newversion") >> $j/etc/$new/jail.conf
echo "Creating run and build dirs"
ex mkdir -p $j/run/$new
ex mkdir -p $j/build/$new
fi
echo "DONE."
if test -z "$update"; then
if ! egrep -q "^$new" /etc/jail.conf; then
bold "Consider adding the jail $new to /etc/jail.conf!"
echo
fi
bold "To mount the build chroot of the new jail, execute:"
echo "jaildk build $new start"
echo
bold "To login into the build chroot"
echo "jaildk blogin $new"
echo
bold "To mount the production chroot of the new jail, execute:"
echo "jaildk install $new"
echo
bold "To login into the build chroot"
echo "jaildk login $new"
echo
bold "To start the jail, execute:"
echo "jaildk start $new"
echo
else
. $j/etc/$src/jail.conf
bold "To mount the build chroot of the new jail, execute:"
echo "jaildk build $new start $base $newversion"
fi
}
2020-11-29 16:22:36 +01:00
usage_create() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 create <jail>
Create a new jail from template."
2020-11-29 16:22:36 +01:00
}
2020-11-06 20:37:13 +01:00
jaildk_create() {
jail=$1
src=.template
if test -z "$jail"; then
2020-11-29 16:22:36 +01:00
usage_create
2020-11-06 20:37:13 +01:00
fi
. $j/etc/$src/jail.conf
srcversion=$version
newversion=`date +%Y%m%d`
mkdir -p $j/etc/$jail
2020-11-29 16:22:36 +01:00
jaildk_clone -s $src -d $jail -o $srcversion -n $newversion
2020-11-06 20:37:13 +01:00
}
remove() {
dir=$1
if test -d $dir; then
ex rm -rf $dir
else
echo "$dir doesn't exist anymore"
fi
}
2020-11-29 18:46:50 +01:00
usage_remove() {
fin "Usage: $0 remove <jail> [-v <version>]
Remove <jail> from disk."
}
2020-11-06 20:37:13 +01:00
jaildk_remove() {
jail=$1
2020-11-29 18:46:50 +01:00
shift
version=''
while getopts "v:" arg; do
case $arg in
v) version=${OPTARG};;
*) usage_remove;;
esac
done
2020-11-06 20:37:13 +01:00
if test -z "$jail"; then
2020-11-29 18:46:50 +01:00
usage_remove
2020-11-06 20:37:13 +01:00
fi
if jls | egrep -q "${jail}"; then
die "Jail $jail($version) is still running, stop it before removing!"
fi
if mount | egrep -q "${jail}.*${version}"; then
die "Jail $jail($version) is still mounted, umount it before removing!"
fi
die_if_not_exist $jail
if test -n "$version"; then
if ! test -d $j/etc/$jail/etc-$version; then
die "Jail $jail $version doesn't exist!"
fi
remove $j/etc/$jail/etc-$version
remove $j/etc/$jail/local-etc-$version
remove $j/home/$jail/root-$version
remove $j/log/$jail-$version
remove $j/data/$jail/www
remove $j/data/$jail/spool
else
remove $j/etc/$jail
remove $j/home/$jail
remove $j/log/$jail-*
remove $j/data/$jail
fi
}
jaildk_jail_usage() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 <start|stop|restart|status> <jail> | status"
}
usage_start() {
fin "Usage $0 start <jail>
Start <jail>."
}
usage_stop() {
fin "Usage $0 stop <jail>
Stop <jail>."
}
usage_restart() {
fin "Usage $0 restart <jail>
Restart <jail>."
}
usage_status() {
fin "Usage $0 status [<jail>]
Show status of <jail>. Without <jail>, show status of all jails."
2020-11-06 20:37:13 +01:00
}
jaildk_jail() {
jail=$2
2020-11-29 18:46:50 +01:00
mode=$1
2020-11-06 20:37:13 +01:00
2020-11-29 18:46:50 +01:00
if test -z "$jail"; then
usage_$mode
elif test -z "$jail" -a $mode = "status"; then
2020-11-06 20:37:13 +01:00
bold "Running jails:"
bold " JID IP Address Hostname Path"
jls | grep -v JID
bold "Mounted build jails:"
format=" %-15s %-29s %s\n"
bold " Version Hostname Path"
mount | egrep "local-etc.*build" | awk '{print $1}' | sed -e 's|/| |g' -e 's/local-etc-//' | while read j e jail version; do
printf "$format" $version $jail $j/build/$jail
done
jls | grep -v JID | awk '{print $3}' | while read J; do
jaildk_rc $J status
done
else
bold "Jail $jail $mode:"
case $mode in
status)
service jail $mode $jail | egrep "IP|$jail"
jaildk_rc $jail status
;;
*)
service jail $mode $jail
;;
esac
fi
}
2020-11-28 12:26:24 +01:00
get_rc_scripts() {
2020-11-28 15:16:40 +01:00
jail="$1"
2020-11-06 20:37:13 +01:00
2020-11-28 15:16:40 +01:00
files=$(ls $j/run/$jail/usr/local/etc/rc.d/* $j/run/$jail/etc/rc.d/*)
rcorder $files | while read SCRIPT; do
rcvar=`egrep "^rcvar=" $SCRIPT | cut -d= -f2 | sed 's/"//g' | tail -1`
if egrep -iq "^${rcvar}=.*yes" $j/run/$jail/usr/local/etc/rc.conf; then
echo $SCRIPT | sed "s|$j/run/$jail||"
fi
done
2020-11-06 20:37:13 +01:00
}
2020-11-29 18:46:50 +01:00
usage_rc() {
fin "Usage: $0 rc <jail> [<mode>] [-r <rc.d script]
Execute an rc.d script inside <jail> with parameter <mode>. Options:
-r <rc.d script> Execute <rc.d script>. default: execute all enabled scripts."
2020-11-06 20:37:13 +01:00
}
jaildk_rc() {
jail=$1
2020-11-29 18:46:50 +01:00
mode=$1
shift
shift
rc=''
while getopts "r:" arg; do
case $arg in
r) rcd=${OPTARG};;
*) usage_rc;;
esac
done
2020-11-06 20:37:13 +01:00
if test -z "$rc"; then
2020-11-29 18:46:50 +01:00
rc='all'
2020-11-06 20:37:13 +01:00
fi
2020-11-29 18:46:50 +01:00
if test -z "$jail" -o -z "$mode"; then
usage_rc
2020-11-06 20:37:13 +01:00
fi
if ! jls | egrep -q "${jail}"; then
die "Jail $jail is not running."
fi
2020-11-28 12:26:24 +01:00
rcs=`get_rc_scripts $jail`
2020-11-06 20:37:13 +01:00
if test $rc = "all"; then
bold "Jail $jail rc status:"
for script in $rcs; do
jexec $jail $script $mode
done
else
ok=''
for script in $rcs; do
if echo "$script" | egrep -q "/$rc"; then
jexec $jail $script $mode
ok=1
fi
done
if test -z "$ok"; then
die "Script $rc doesn't exist in $jail or is not enabled."
fi
fi
}
2020-11-29 18:46:50 +01:00
usage_blogin() {
err "Usage: $file <jail>
Chroot into a build jail.
Mounted build chroot's:"
mount|egrep "base.*build" | awk '{print $3}' | cut -d/ -f 4
exit 1
}
2020-11-27 23:21:34 +01:00
2020-11-06 20:37:13 +01:00
jaildk_blogin() {
jail=$1
if test -z "$jail"; then
file=`basename $0`
if test "$file" = "jaildk"; then
file="$0 blogin"
else
file="$0"
fi
2020-11-29 18:46:50 +01:00
usage_blogin
2020-11-06 20:37:13 +01:00
fi
chroot="$j/build/$jail"
if ! test -d $chroot/root; then
echo "build jail $jail not mounted!"
echo "Mount it with jaildk build $jail start"
exit 1
fi
shell=/bin/csh
term=vt100
home=/root
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
if test -e $chroot/root/.bashrc; then
shell=/usr/local/bin/bash
fi
chroot $chroot /etc/rc.d/ldconfig onestart > /dev/null 2>&1
2020-11-28 14:34:10 +01:00
env - HOME=$home TERM=$term SHELL=$shell PATH=$path chroot $chroot $shell
2020-11-06 20:37:13 +01:00
}
2020-11-29 18:46:50 +01:00
usage_login() {
err "Usage: $file <jail-name|jail-domain|jail-ip> [<user>]
Login into a jail by name, ip or domain. If <user> has not been
specified, login as root.
Available jails:"
jls
exit 1
}
2020-11-06 20:37:13 +01:00
jaildk_login() {
jail=$1
user=$2
me=`id -u`
jexec="jexec"
if test -z "$jail"; then
file=`basename $0`
if test "$file" = "jaildk"; then
file="$0 jlogin"
else
file="$0"
fi
2020-11-29 18:46:50 +01:00
usage_login
2020-11-06 20:37:13 +01:00
fi
jid=""
2020-11-27 23:21:34 +01:00
echo $jail
jid=`jls | grep "$jail" | awk '{print $1}'`
echo $jid
2020-11-06 20:37:13 +01:00
if test -z "$jid"; then
echo "jail $jail doesn't run!"
exit 1
fi
shell=sh
home=/home/$user
term=vt100
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
chroot_subdir=`grep "jail_${name}_rootdir" /etc/rc.conf | awk -F\" '{print $2}'`
if test -z "$user"; then
user=root
fi
if test "$me" != "0"; then
jexec="sudo $jexec"
fi
shell=/bin/sh
home=/
if grep "^$user" $chroot_subdir/etc/passwd > /dev/null 2>&1; then
shell=`grep "^$user" $chroot_subdir/etc/passwd | awk -F: '{print $7}' | sed 's/ //g'`
home=`grep "^$user" $chroot_subdir/etc/passwd | awk -F: '{print $6}' | sed 's/ //g'`
fi
env - JAIL=$jail HOME=$home TERM=$term SHELL=$shell PATH=$path $jexec -U $user $jid $shell
}
2020-11-29 18:46:50 +01:00
usage_reinstall() {
fin "Usage: $0 reinstall <jail>
Stop, uninstall, install and start <jail>.
"
}
2020-11-06 20:37:13 +01:00
jaildk_reinstall() {
jail=$1
2020-11-29 18:46:50 +01:00
if test -z "$jail"; then
usage_reinstall
fi
2020-11-06 20:37:13 +01:00
die_if_not_exist $jail
if jls | egrep -q "${jail}"; then
jaildk_jail stop $jail
fi
jaildk_uninstall $jail
sleep 0.2
sync
jaildk_install $jail start
jaildk_jail start $jail
sleep 0.2
jaildk_jail status $jail
}
jaildk_setup() {
j=$1
if test -z "$j"; then
2020-11-29 18:46:50 +01:00
fin "Usage: $0 setup <base dir for jail environment>"
2020-11-06 20:37:13 +01:00
fi
bold "preparing directories"
ex mkdir -p $j
2020-11-26 22:08:19 +01:00
for subdir in etc bin appl base data home log run ports; do
2020-11-06 20:37:13 +01:00
ex mkdir -p $j/$subdir
done
version=`date +%Y%m%d`
2020-11-27 23:21:34 +01:00
for subdir in appl/default-$version/db/ports appl/default-$version/etc etc/.template/etc-$version etc/.template/local-etc-$version home/.template/root-$version log/.template-$version; do
2020-11-06 20:37:13 +01:00
ex mkdir -p $j/$subdir
done
bold "building jail template"
2020-11-26 12:36:36 +01:00
ex cpdup /etc $j/etc/.template/etc-$version
2020-11-06 20:37:13 +01:00
echo "creating $j/etc/.template/etc-$version/rc.conf"
2020-11-27 23:21:34 +01:00
rm -f $j/etc/.template/etc-$version/rc.conf
2020-11-06 20:37:13 +01:00
echo 'rc_conf_files="/etc/rc.conf /etc/rc.conf.local /usr/local/etc/rc.conf"' > $j/etc/.template/etc-$version/rc.conf
echo "creating $j/etc/.template/local-etc-$version/rc.conf"
echo 'hostname="TEMPLATE"
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"' > $j/etc/.template/local-etc-$version/rc.conf
bold "creating template config $j/etc/.template/jail.conf"
os=`uname -r`
(echo "base=$os"; echo "version=$version"; name=template) > $j/etc/.template/jail.conf
bold "creating template config $j/etc/.template/mount.conf"
echo 'base/$base $name nullfs ro
md $name/tmp mfs rw,nosuid,async 128m 1777
dev $name/dev devfs
log/$name-$version $name/var/log nullfs rw
appl/default-$version $name/usr/local nullfs ro
etc/$name/etc-$version $name/etc nullfs ro
etc/$name/local-etc-$version $name/usr/local/etc nullfs ro
home/$name/root-$version $name/root nullfs rw' > $j/etc/.template/mount.conf
bold "creating template config $j/etc/.template/ports.conf"
(echo bash; echo ca_root_nss) > $j/etc/.template/ports.conf
bold "creating template config $j/etc/.template/mtree.conf"
2020-11-27 23:21:34 +01:00
# touch $j/etc/.template/mtree.conf
echo '/set type=dir uid=0 gid=0 mode=01777
. type=dir mode=0755
tmp
var
cache
pkg
..
..
run
..
tmp' > $j/etc/.template/mtree.conf
2020-11-06 20:37:13 +01:00
bold "installing jaildk"
realj=`cd $j; pwd`
sed "s|^JAILDIR=.*|JAILDIR=$realj|" $0 > $j/bin/jaildk
ex chmod 755 $j/bin/jaildk
2020-11-25 10:42:52 +01:00
bold "configuring root shell template"
echo "# root shell inside jail
alias h history 25
alias j jobs -l
alias la ls -a
alias lf ls -FA
alias ll ls -lA
alias l ls -laF
alias .. cd ..
alias ... cd ../..
alias .... cd ../../../
umask 22
set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin)
setenv EDITOR vi
setenv PAGER less
setenv BLOCKSIZE K
if (\$?prompt) then
2020-11-27 23:21:34 +01:00
set chroot=`ps axu|grep /sbin/init | grep -v grep | awk '{print $1}'`
2020-11-25 10:45:13 +01:00
if("\$chroot" == \"\") then
set prompt = \"(jail) %N@%m:%~ %# \"
2020-11-25 10:42:52 +01:00
else
2020-11-25 10:45:13 +01:00
set prompt = \"(build chroot) %N@%m:%~ %# \"
2020-11-25 10:42:52 +01:00
endif
set promptchars = \"%#\"
set filec
set history = 1000
set savehist = (1000 merge)
set autolist = ambiguous
# Use history to aid expansion
set autoexpand
set autorehash
endif
" > $j/home/.template/root-$version/.cshrc
2020-11-06 20:37:13 +01:00
bold "building base"
echo -n "Do you want to build a base directory [Yn]? "
read yesno
case $yesno in
y|Y|yes|YES)
2020-11-29 16:22:36 +01:00
jaildk_base -b $j/base/$os
2020-11-06 20:37:13 +01:00
;;
esac
}
2020-11-27 19:08:57 +01:00
jaildk_fetch() {
2020-11-26 22:08:19 +01:00
version=`date +%Y%m%d`
2020-11-27 19:08:57 +01:00
if test -d "$j/ports/$version"; then
echo -n "Ports dir $version already exist. Do you want to recreate it [y/N]? "
2020-11-26 22:08:19 +01:00
read yesno
case $yesno in
y|Y|yes|YES)
2020-11-27 19:08:57 +01:00
ex rm -rf $j/ports/$version
jaildk_fetch_ports
2020-11-26 22:08:19 +01:00
;;
esac
else
2020-11-27 19:08:57 +01:00
jaildk_fetch_ports
2020-11-26 22:08:19 +01:00
fi
}
2020-11-27 19:08:57 +01:00
jaildk_fetch_ports() {
ex mkdir -p $j/ports/tmp
ex fetch -o $j/ports/tmp/ports.tar.gz http://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz
2020-11-27 23:21:34 +01:00
ex tar xzfC $j/ports/tmp/ports.tar.gz $j/ports/tmp
2020-11-27 19:08:57 +01:00
ex mv $j/ports/tmp/ports $j/ports/$version
ex rm -rf $j/ports/tmp/ports*
2020-11-26 22:08:19 +01:00
}
2020-11-06 20:37:13 +01:00
2020-11-29 16:22:36 +01:00
usage_freeze() {
2020-11-28 20:41:05 +01:00
echo "Usage: $0 freeze <jail> [options]
Options:
-v <version> freeze <version> of <jail>
-b include the base layer (default: no)
-a include the application layer (default: no)"
exit 1
}
freeze_dir() {
dstdir=$1
src=$2
srcdir=$(echo $src | cut -d/ -f1)
layer=$(echo $src | sed "s|$srcdir/||")
layerfile=$(echo $layer | sed 's|/|-|g')
ex tar -C $j/$srcdir -cpf $dstdir/$srcdir-$layerfile.tar $layer
}
2020-11-28 15:16:40 +01:00
jaildk_freeze() {
jail=$1
2020-11-28 20:41:05 +01:00
shift
VERSION=""
ADDBASE=""
ADDAPPL=""
while getopts "abv:" arg; do
case $arg in
a) ADDAPPL=1;;
b) ADDBASE=1;;
v) VERSION=${OPTARG};;
2020-11-29 16:22:36 +01:00
*) usage_freeze;;
2020-11-28 20:41:05 +01:00
esac
done
if test -z "$jail"; then
2020-11-29 16:22:36 +01:00
usage_freeze
2020-11-28 20:41:05 +01:00
fi
die_if_not_exist $jail "Jail to freeze" $VERSION
if jls | egrep -q "${jail}"; then
echo "The jail $jail is actually running. It's recommended"
echo -n "to stop it before freezing. Stop the jail now [Ny]? "
read yesno
case $yesno in
y|Y|yes|YES|Yes)
service jail stop $jail
;;
esac
fi
load-jail-config $jail
if test -n "$VERSION"; then
version=$VERSION
fi
bold "Freezing jail $jail $version"
host=$(hostname | cut -d\. -f1)
freeze=$j/images/$host-$jail-$version.tgz
tmp=$j/images/tmp/$jail-$version
ex mkdir -p $tmp
mountconf=$j/etc/$jail/mount.conf
if ! test -e "$mountconf"; then
die "$mountconf doesn't exist!"
fi
# create sub tarballs from every layer
grep -v "#" $mountconf | while read LINE; do
# this is a copy of the code in jaildk_rc_mount()
# FIXME: put this into a function somehow
set -- $(eval echo \""$LINE"\")
# Skip empty lines:
case "$1" in
"") continue ;;
esac
src=$1
dest=$2
fs=$3
opts=$4
size=$5
perm=$6
case $fs in
nullfs)
if ! echo $src | egrep -q "^/"; then
# only freeze nullfs mounts relative to $j
if echo $src | egrep -q "^base/"; then
if test -n "$ADDBASE"; then
freeze_dir $tmp $src
fi
elif echo $src | egrep -q "^appl/"; then
if test -n "$ADDAPPL"; then
freeze_dir $tmp $src
fi
else
freeze_dir $tmp $src
fi
fi
;;
esac
done
# add the jail config
files=$(find $j/etc/$jail -type f -maxdepth 1)
for file in $files; do
cp -pP $file $tmp/
done
# build the final image file
ex tar -C $j/images/tmp -cpf $freeze $jail-$version
# cleaning up
ex rm -rf $j/images/tmp
bold "Done, jail $jail frozen to $freeze."
}
thaw_tarball() {
srcdir=$1
tarball=$2
# etc-test-local-etc-20201128.tar
layer=$(echo $tarball | cut -d\- -f1)
if ! test -d $j/$layer; then
ex mkdir -p $j/$layer
fi
ex tar -C $j/$layer -xf $srcdir/$tarball
ex rm -f $srcdir/$tarball
}
2020-11-29 16:22:36 +01:00
usage_thaw() {
2020-11-29 18:46:50 +01:00
fin "Usage: $0 thaw <image>"
2020-11-29 16:22:36 +01:00
}
2020-11-28 20:41:05 +01:00
jaildk_thaw() {
image=$1
if test -n "$J"; then
j=$J
fi
jail=$(echo $image | cut -d\- -f2)
version=$(echo $image | cut -d\- -f3 | cut -d\. -f1)
if ! test -n "$version" -o -n "$jail"; then
2020-11-29 16:22:36 +01:00
usage_thaw
2020-11-28 20:41:05 +01:00
fi
if test -d $j/etc/$jail/etc-$version; then
bold -n "Jail $jail $version already exists, overwrite [Ny]? "
read yesno
case $yesno in
y|Y|yes|YES|Yes)
:;;
*)
echo "abort.";;
esac
fi
bold "Thawing jail $image"
tmp=$j/images/tmp
ex mkdir -p $tmp
# too many things can go wrong from here, so better abort on error
set -e
ex tar -C $tmp -xf $image
if ! test -d $tmp/$jail-$version; then
die "Invalid image format!"
ex rm -rf $tmp
fi
for tarball in `cd $tmp/$jail-$version && ls *.tar`; do
thaw_tarball $tmp/$jail-$version $tarball
done
files=$(find $tmp -type f)
bak=""
if test -e $j/etc/$jail/jail.conf; then
bold -n "$j/etc/$jail/jail.conf already exist. Overwrite configs [Ny]? "
read yesno
case $yesno in
y|Y|yes|YES|Yes)
:;;
*)
bold "Copying configs with extension -$version"
bak="-$version"
;;
esac
fi
for file in $files; do
filename=$(basename $file)
ex cp -Pp $file $j/etc/$jail/$filename$bak
done
bold "Done. Thawed jail $jail $version from $image."
2020-11-28 15:16:40 +01:00
}
2020-11-28 20:41:05 +01:00
2020-11-06 20:37:13 +01:00
##########################
#
# main()
# will be modified during installation
JAILDIR=/jail
2020-11-27 08:52:58 +01:00
# install modules
2020-11-28 11:51:38 +01:00
RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree"
2020-11-28 12:26:24 +01:00
RCSCRIPTS_STOP="jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports"
2020-11-27 08:52:58 +01:00
2020-11-06 20:37:13 +01:00
# globals
j=$JAILDIR
rcdir=$j/bin
runner=$1
shift
2020-11-27 19:08:57 +01:00
if test -z "$runner"; then
usage_jaildk
fi
2020-11-06 20:37:13 +01:00
case $runner in
start|stop|status|restart)
jaildk_jail $runner $*
;;
2020-11-28 20:41:05 +01:00
setup|reinstall|install|uninstall|build|blogin|login|clone|create|remove|rc|base|fetch|freeze|thaw)
2020-11-06 20:37:13 +01:00
jaildk_$runner $*
;;
2020-11-29 18:46:50 +01:00
help)
usage_help $*
;;
2020-11-06 20:37:13 +01:00
*)
usage_jaildk $*
;;
esac