#!/bin/bash # # Control program for bespoke arbitrary services through unshared sub-hosts # # $1 = the command: start or stop # $2 = the sub-host to start or stop # $3... = the optional chroot-ed command (/startup by default) SCRIPT=$0 CMD=$1 NAME=$2 shift 2 usage() { echo "$SCRIPT (start|stop) " >&2 exit 1 } [ -z "$NAME" ] && usage : ${ATTIC=/opt/srv} : ${BRIDGE=srv_br} : ${TARGET=/srv/$NAME} : ${LOWER=$ATTIC/daedalus.fs} : ${IMAGE=$ATTIC/$NAME/$NAME.img} : ${UPPER=$ATTIC/$NAME/root} : ${WORK=$ATTIC/$NAME/work} : ${MOUNT=$ATTIC/$NAME/mnt} : ${NSNAME=$NAME} : ${NETH=1} create_subhost() { mkdir -p $TARGET $MOUNT $UPPER $WORK } setup_network() { if [ -n "$BRIDGE" ] ; then brctl show $BRIDGE >& /dev/null || brctl addbr $BRIDGE fi E=0 ip netns add $NSNAME for I in $(eval echo "{1..$NETH}") ; do IF=$NAME$E ip link add $IF type veth peer name eth$E netns $NSNAME ip link set $IF up [ -n "$BRIDGE" ] && brctl addif $BRIDGE $IF E=$((E+1)) done } setup_rootfs() { if [ -e "$IMAGE" ] ; then mount $IMAGE $MOUNT || exit 1 LOWER=$MOUNT/root WORK=$MOUNT/work fi mount -t overlay $NAME -olowerdir=$LOWER,upperdir=$UPPER,workdir=$WORK \ $TARGET } case "$CMD" in start) cd "$ATTIC" || exit 1 [ -e "/run/netns/$NSNAME" ] || setup_network [ -d "$MOUNT" ] || create_subhost grep -q "^$NAME $TARGET overlay" /proc/mounts || setup_rootfs START=/bin/bash [ -x $TARGET/startup ] && START=/startup exec ip netns exec $NSNAME unshare \ --fork --pid --mount-proc --kill-child \ --uts --ipc --mount --cgroup \ "--root=$TARGET" $START ;; stop) umount $TARGET [ -e $IMAGE ] && umount $MOUNT ip netns del $NSNAME ;; *) usage ;; esac