Update jlmkr.sh

This commit is contained in:
Jip-Hop 2023-01-29 17:19:12 +01:00
parent cba5d1f3b3
commit 6a747bb01d
1 changed files with 138 additions and 135 deletions

273
jlmkr.sh
View File

@ -31,21 +31,32 @@ Commands:
start Start jail NAME from the ${JAILS_DIR_PATH} dir start Start jail NAME from the ${JAILS_DIR_PATH} dir
" "
print() {
printf '%s\n' "${1-}"
}
error() { error() {
echo -e "${RED}${BOLD}${1}${NORMAL}" >&2 print "${RED}${BOLD}${1}${NORMAL}" >&2
} }
fail() { fail() {
error "${1}" && exit 1 error "${1}" && exit 1
} }
[[ -z "${BASH_VERSINFO+x}" ]] && fail "This script must run in bash..." stat_chmod() {
[[ $UID -ne 0 ]] && echo "${USAGE}" && fail "Run this script as root..." # Only run chmod if mode is different from current mode
if [[ "$(stat -c%a "${2}")" -ne "${1}" ]]; then chmod "${1}" "${2}"; fi
}
[[ -z "${BASH_VERSINFO+x}" ]] && fail 'This script must run in bash...'
[[ $UID -ne 0 ]] && print "${USAGE}" && fail 'Run this script as root...'
cd "${SCRIPT_DIR_PATH}" || fail "Could not change working directory to ${SCRIPT_DIR_PATH}..." cd "${SCRIPT_DIR_PATH}" || fail "Could not change working directory to ${SCRIPT_DIR_PATH}..."
# Set appropriate permissions (if not already set) for this file, since it's executed as root
stat_chmod 700 "${SCRIPT_NAME}"
trace() { trace() {
# https://unix.stackexchange.com/a/504829/477308 # https://unix.stackexchange.com/a/504829/477308
echo 'Error occurred:' print 'Error occurred:'
awk 'NR>L-4 && NR<L+4 { printf "%-5d%3s%s\n",NR,(NR==L?">>>":""),$0 }' L="${1}" "${ABSOLUTE_SCRIPT_PATH}" awk 'NR>L-4 && NR<L+4 { printf "%-5d%3s%s\n",NR,(NR==L?">>>":""),$0 }' L="${1}" "${ABSOLUTE_SCRIPT_PATH}"
} }
@ -57,14 +68,14 @@ trap 'trace $LINENO' ERR
##################### #####################
start_jail() { start_jail() {
[[ -z "${1}" ]] && fail "Please specify the name of the jail to start." [[ -z "${1}" ]] && fail 'Please specify the name of the jail to start.'
local jail_name="${1}" local jail_name="${1}"
local jail_path="${JAILS_DIR_PATH}/${jail_name}" local jail_path="${JAILS_DIR_PATH}/${jail_name}"
local jail_config_path="${jail_path}/${JAIL_CONFIG_NAME}" local jail_config_path="${jail_path}/${JAIL_CONFIG_NAME}"
! [[ -f "${jail_config_path}" ]] && fail "ERROR: Couldn't find: ${jail_config_path}." ! [[ -f "${jail_config_path}" ]] && fail "ERROR: Could not find: ${jail_config_path}."
echo 'Loading config...' print 'Loading config...'
local key value local key value
@ -82,14 +93,14 @@ start_jail() {
done <"${jail_config_path}" done <"${jail_config_path}"
echo 'Config loaded!' print 'Config loaded!'
local systemd_run_additional_args=("--unit=jlmkr-${jail_name}" "--working-directory=./${jail_path}" "--description=My nspawn jail ${jail_name} [created with jailmaker]") local systemd_run_additional_args=("--unit=jlmkr-${jail_name}" "--working-directory=./${jail_path}" "--description=My nspawn jail ${jail_name} [created with jailmaker]")
local systemd_nspawn_additional_args=("--machine=${jail_name}" "--directory=${JAIL_ROOTFS_NAME}") local systemd_nspawn_additional_args=("--machine=${jail_name}" "--directory=${JAIL_ROOTFS_NAME}")
if [[ "${docker_compatible}" -eq 1 ]]; then if [[ "${docker_compatible}" -eq 1 ]]; then
# Enable ip forwarding on the host (docker needs it) # Enable ip forwarding on the host (docker needs it)
echo 1 >/proc/sys/net/ipv4/ip_forward printf 1 >/proc/sys/net/ipv4/ip_forward
# To properly run docker inside the jail, we need to lift restrictions # To properly run docker inside the jail, we need to lift restrictions
# Without DevicePolicy=auto images with device nodes may not be pulled # Without DevicePolicy=auto images with device nodes may not be pulled
@ -121,7 +132,7 @@ start_jail() {
# while read -r arg; do # while read -r arg; do
# # TODO: does --network-macvlan also need this? # # TODO: does --network-macvlan also need this?
# if [[ "${arg}" == "--network-bridge=*" ]]; then # if [[ "${arg}" == "--network-bridge=*" ]]; then
# echo "Enable br_netfilter, docker requires it when jail is connected to bridge." # print 'Enable br_netfilter, docker requires it when jail is connected to bridge.'
# # TODO: figure out what the consequence is when not using br_netfilter # # TODO: figure out what the consequence is when not using br_netfilter
# # Can these warnings in `docker info` be safely ignored? # # Can these warnings in `docker info` be safely ignored?
# # WARNING: bridge-nf-call-iptables is disabled # # WARNING: bridge-nf-call-iptables is disabled
@ -166,51 +177,51 @@ start_jail() {
# Read each argument from a string with null character as delimiter # Read each argument from a string with null character as delimiter
# Append each argument, one at a time, to the array # Append each argument, one at a time, to the array
while IFS= read -rd '' arg; do args+=("${arg}"); done < <(xargs printf '%s\0' <<<"${systemd_run_default_args}")
while IFS= read -rd '' arg; do [[ -n "${arg}" ]] && args+=("${arg}"); done < <(printf %s "${systemd_run_default_args}" | xargs printf '%s\0')
# Append each element in systemd_run_additional_args to the args array # Append each element in systemd_run_additional_args to the args array
args+=("${systemd_run_additional_args[@]}") args+=("${systemd_run_additional_args[@]}")
# Add two more args to the array # Add two more args to the array
args+=(-- systemd-nspawn) args+=(-- systemd-nspawn)
# Append each argument, one at a time, to the array # Append each argument, one at a time, to the array
while IFS= read -rd '' arg; do args+=("${arg}"); done < <(xargs printf '%s\0' <<<"${systemd_nspawn_default_args}") while IFS= read -rd '' arg; do [[ -n "${arg}" ]] && args+=("${arg}"); done < <(printf %s "${systemd_nspawn_default_args}" | xargs printf '%s\0')
# Append each element in systemd_nspawn_additional_args to the args array # Append each element in systemd_nspawn_additional_args to the args array
args+=("${systemd_nspawn_additional_args[@]}") args+=("${systemd_nspawn_additional_args[@]}")
# Append each argument, one at a time, to the array # Append each argument, one at a time, to the array
while IFS= read -rd '' arg; do args+=("${arg}"); done < <(xargs printf '%s\0' <<<"${systemd_nspawn_user_args}") while IFS= read -rd '' arg; do [[ -n "${arg}" ]] && args+=("${arg}"); done < <(printf %s "${systemd_nspawn_user_args}" | xargs printf '%s\0')
# Concat all arguments in the array into a single space separated string, # Concat all arguments in the array into a single space separated string,
# but use %q to output each argument in a format that can be reused as shell input # but use %q to output each argument in a format that can be reused as shell input
# This escapes special characters for us, which were 'lost' when xargs read the input above # This escapes special characters for us, which were 'lost' when xargs read the input above
# https://ss64.com/bash/printf.html # https://ss64.com/bash/printf.html
args_string="$(printf '%q ' "${args[@]}")" args_string="$(printf '%q ' "${args[@]}")"
echo print
echo "All the arguments to pass to systemd-run:" print 'All the arguments to pass to systemd-run:'
printf '%s' "${args_string}" | xargs -n 1 printf '%s' "${args_string}" | xargs -n 1
echo print
echo "Starting jail with the following command:" print 'Starting jail with the following command:'
echo print
echo "systemd-run ${args_string}" print "systemd-run ${args_string}"
echo print
printf '%s' "${args_string}" | xargs systemd-run || { printf '%s' "${args_string}" | xargs systemd-run || {
echo print
error 'Failed to start the jail...' error 'Failed to start the jail...'
fail "Please check and fix the config file with \"nano ${jail_config_path}\"." fail 'Please check and fix the config file with "nano '"${jail_config_path}"'".'
} }
echo print
echo "Check logging:" print 'Check logging:'
echo "journalctl -u jlmkr-${jail_name}" print "journalctl -u jlmkr-${jail_name}"
echo print
echo "Check status:" print 'Check status:'
echo "systemctl status jlmkr-${jail_name}" print "systemctl status jlmkr-${jail_name}"
echo print
echo "Stop the jail:" print 'Stop the jail:'
echo "machinectl stop ${jail_name}" print "machinectl stop ${jail_name}"
echo print
echo "Get a shell:" print 'Get a shell:'
echo "machinectl shell ${jail_name}" print "machinectl shell ${jail_name}"
} }
###################### ######################
@ -220,21 +231,16 @@ start_jail() {
cleanup() { cleanup() {
# Remove the jail_path if it's a directory # Remove the jail_path if it's a directory
local jail_path="${1}" local jail_path="${1}"
[[ -d "${jail_path}" ]] && echo -e "\n\nCleaning up: ${jail_path}\n" && rm -rf "${jail_path}" [[ -d "${jail_path}" ]] && print && print "Cleaning up: ${jail_path}" && rm -rf "${jail_path}"
}
stat_chmod() {
# Only run chmod if mode is different from current mode
if [[ "$(stat -c%a "${2}")" -ne "${1}" ]]; then chmod "${1}" "${2}"; fi
} }
validate_download_script() { validate_download_script() {
echo "6cca2eda73c7358c232fecb4e750b3bf0afa9636efb5de6a9517b7df78be12a4 ${1}" | sha256sum --check >/dev/null print "6cca2eda73c7358c232fecb4e750b3bf0afa9636efb5de6a9517b7df78be12a4 ${1}" | sha256sum --check >/dev/null
} }
create_jail() { create_jail() {
echo -e "${DISCLAIMER}" print "${DISCLAIMER}"
echo print
local name_from_arg="${1}" local name_from_arg="${1}"
local arch local arch
@ -245,7 +251,7 @@ create_jail() {
[[ "$(basename "${SCRIPT_DIR_PATH}")" != 'jailmaker' ]] && { [[ "$(basename "${SCRIPT_DIR_PATH}")" != 'jailmaker' ]] && {
error "${SCRIPT_NAME} needs to create files." error "${SCRIPT_NAME} needs to create files."
error "Currently it can't decide if it's safe to create files in:" error 'Currently it can not decide if it is safe to create files in:'
error "${SCRIPT_DIR_PATH}" error "${SCRIPT_DIR_PATH}"
fail "Please create a dedicated directory called 'jailmaker', store ${SCRIPT_NAME} there and try again." fail "Please create a dedicated directory called 'jailmaker', store ${SCRIPT_NAME} there and try again."
} }
@ -253,21 +259,18 @@ create_jail() {
local reply local reply
if [[ $(findmnt --target . --output TARGET --noheadings --first-only) != /mnt/* ]]; then if [[ $(findmnt --target . --output TARGET --noheadings --first-only) != /mnt/* ]]; then
echo "${YELLOW}${BOLD}WARNING: BEWARE OF DATA LOSS${NORMAL}" print "${YELLOW}${BOLD}WARNING: BEWARE OF DATA LOSS${NORMAL}"
echo print
echo "${SCRIPT_NAME} should be on a dataset mounted under /mnt (it currently isn't)." print "${SCRIPT_NAME} should be on a dataset mounted under /mnt (it currently isn't)."
echo "Storing it on the boot-pool means losing all jails when updating TrueNAS." print 'Storing it on the boot-pool means losing all jails when updating TrueNAS.'
echo "If you continue, jails will be stored under:" print 'If you continue, jails will be stored under:'
echo "${SCRIPT_DIR_PATH}" print "${SCRIPT_DIR_PATH}"
echo print
read -p "Do you wish to ignore this warning and continue? [y/N] " -n 1 -r reply && echo read -p "Do you wish to ignore this warning and continue? [y/N] " -n 1 -r reply && print
# Enter accepts default (no) # Enter accepts default (no)
! [[ "${reply}" =~ ^[Yy]$ ]] && exit ! [[ "${reply}" =~ ^[Yy]$ ]] && exit
fi fi
# Set appropriate permissions (if not already set) for this file, since it's executed as root
stat_chmod 700 "${SCRIPT_NAME}"
# Create the lxc dirs if nonexistent # Create the lxc dirs if nonexistent
mkdir -p "${lxc_dir_path}" mkdir -p "${lxc_dir_path}"
stat_chmod 700 "${lxc_dir_path}" stat_chmod 700 "${lxc_dir_path}"
@ -289,32 +292,32 @@ create_jail() {
local distro='debian' release='bullseye' local distro='debian' release='bullseye'
read -p "Install the recommended distro (Debian 11)? [Y/n] " -n 1 -r reply && echo read -p "Install the recommended distro (Debian 11)? [Y/n] " -n 1 -r reply && print
if ! [[ "${reply}" =~ ^([Yy]|)$ ]]; then if ! [[ "${reply}" =~ ^([Yy]|)$ ]]; then
echo print
echo "${YELLOW}${BOLD}WARNING: ADVANCED USAGE${NORMAL}" print "${YELLOW}${BOLD}WARNING: ADVANCED USAGE${NORMAL}"
echo print
echo "You may now choose from a list which distro to install." print 'You may now choose from a list which distro to install.'
echo "But not all of them will work with ${SCRIPT_NAME} since these images are made for LXC." print "But not all of them will work with ${SCRIPT_NAME} since these images are made for LXC."
echo "Distros based on systemd probably work (e.g. Ubuntu, Arch Linux and Rocky Linux)." print 'Distros based on systemd probably work (e.g. Ubuntu, Arch Linux and Rocky Linux).'
echo "Others (Alpine, Devuan, Void Linux) probably won't." print 'Others (Alpine, Devuan, Void Linux) probably will not.'
echo print
read -p "Press any key to continue: " -n 1 -r reply && echo read -p "Press any key to continue: " -n 1 -r reply && print
echo print
lxc_cache_path=${lxc_cache_path} "${lxc_download_script_path}" --list --arch="${arch}" || : lxc_cache_path=${lxc_cache_path} "${lxc_download_script_path}" --list --arch="${arch}" || :
echo print
echo "Choose from the DIST column." print 'Choose from the DIST column.'
echo print
read -e -r -p "Distribution: " distro && echo read -e -r -p "Distribution: " distro && print
echo "Choose from the RELEASE column (or ARCH if RELEASE is empty)." print 'Choose from the RELEASE column (or ARCH if RELEASE is empty).'
echo print
read -e -r -p "Release: " release read -e -r -p "Release: " release
fi fi
echo print
local jail_name jail_path local jail_name jail_path
while true; do while true; do
read -e -r -p "Enter jail name: " -i "${name_from_arg}" jail_name && echo read -e -r -p "Enter jail name: " -i "${name_from_arg}" jail_name && print
if ! [[ "${jail_name}" =~ ^[.a-zA-Z0-9-]{1,64}$ && "${jail_name}" != '.'* && "${jail_name}" != *'.' && "${jail_name}" != *'..'* ]]; then if ! [[ "${jail_name}" =~ ^[.a-zA-Z0-9-]{1,64}$ && "${jail_name}" != '.'* && "${jail_name}" != *'.' && "${jail_name}" != *'..'* ]]; then
cat <<-EOF cat <<-EOF
${YELLOW}${BOLD}WARNING: INVALID NAME${NORMAL} ${YELLOW}${BOLD}WARNING: INVALID NAME${NORMAL}
@ -330,8 +333,8 @@ create_jail() {
jail_path="${JAILS_DIR_PATH}/${jail_name}" jail_path="${JAILS_DIR_PATH}/${jail_name}"
if [[ -e "${jail_path}" ]]; then if [[ -e "${jail_path}" ]]; then
echo "A jail with this name already exists." print 'A jail with this name already exists.'
echo print
else else
# Accept the name # Accept the name
break break
@ -345,33 +348,33 @@ create_jail() {
local docker_compatible gpu_passthrough systemd_nspawn_user_args local docker_compatible gpu_passthrough systemd_nspawn_user_args
echo "Docker won't be installed by ${SCRIPT_NAME}." print "Docker won't be installed by ${SCRIPT_NAME}."
echo "But it can setup the jail with the capabilities required to run docker." print 'But it can setup the jail with the capabilities required to run docker.'
echo "You can turn DOCKER_COMPATIBLE mode on/off post-install." print 'You can turn DOCKER_COMPATIBLE mode on/off post-install.'
echo print
read -p "Make jail docker compatible right now? [y/N] " -n 1 -r reply && echo read -p "Make jail docker compatible right now? [y/N] " -n 1 -r reply && print
# Enter accepts default (no) # Enter accepts default (no)
if ! [[ "${reply}" =~ ^[Yy]$ ]]; then docker_compatible=0; else docker_compatible=1; fi if ! [[ "${reply}" =~ ^[Yy]$ ]]; then docker_compatible=0; else docker_compatible=1; fi
echo print
read -p "Give access to the GPU inside the jail? [y/N] " -n 1 -r reply && echo read -p "Give access to the GPU inside the jail? [y/N] " -n 1 -r reply && print
# Enter accepts default (no) # Enter accepts default (no)
if ! [[ "${reply}" =~ ^[Yy]$ ]]; then gpu_passthrough=0; else gpu_passthrough=1; fi if ! [[ "${reply}" =~ ^[Yy]$ ]]; then gpu_passthrough=0; else gpu_passthrough=1; fi
echo print
echo "${YELLOW}${BOLD}WARNING: CHECK SYNTAX${NORMAL}" print "${YELLOW}${BOLD}WARNING: CHECK SYNTAX${NORMAL}"
echo print
echo "You may pass additional flags to systemd-nspawn." print 'You may pass additional flags to systemd-nspawn.'
echo "With incorrect flags the jail may not start." print 'With incorrect flags the jail may not start.'
echo "It's possible to correct/add/remove flags post-install." print 'It is possible to correct/add/remove flags post-install.'
echo print
read -p "Show the man page for systemd-nspawn? [y/N] " -n 1 -r reply && echo read -p "Show the man page for systemd-nspawn? [y/N] " -n 1 -r reply && print
# Enter accepts default (no) # Enter accepts default (no)
if [[ "${reply}" =~ ^[Yy]$ ]]; then if [[ "${reply}" =~ ^[Yy]$ ]]; then
man systemd-nspawn man systemd-nspawn
else else
echo print
echo "You may read the systemd-nspawn manual online:" print 'You may read the systemd-nspawn manual online:'
echo "https://manpages.debian.org/${distro}/systemd-container/systemd-nspawn.1.en.html" print "https://manpages.debian.org/${distro}/systemd-container/systemd-nspawn.1.en.html"
fi fi
# Backslashes and colons need to be escaped in bind mount options: # Backslashes and colons need to be escaped in bind mount options:
@ -380,11 +383,11 @@ create_jail() {
# the corresponding command would be: # the corresponding command would be:
# --bind-ro='/mnt/data/weird chars \:?\\"' # --bind-ro='/mnt/data/weird chars \:?\\"'
echo print
echo "For example to mount directories inside the jail you may add:" print 'For example to mount directories inside the jail you may add:'
echo "--bind=/mnt/a/readwrite/directory --bind-ro=/mnt/a/readonly/directory" print '--bind=/mnt/a/readwrite/directory --bind-ro=/mnt/a/readonly/directory'
echo print
read -e -r -p "Additional flags: " systemd_nspawn_user_args && echo read -e -r -p "Additional flags: " systemd_nspawn_user_args && print
# Create directory for rootfs # Create directory for rootfs
JAIL_ROOTFS_PATH="${jail_path}/${JAIL_ROOTFS_NAME}" JAIL_ROOTFS_PATH="${jail_path}/${JAIL_ROOTFS_NAME}"
@ -398,8 +401,8 @@ create_jail() {
LXC_CACHE_PATH=${lxc_cache_path} "${lxc_download_script_path}" \ LXC_CACHE_PATH=${lxc_cache_path} "${lxc_download_script_path}" \
--name="${jail_name}" --path="${jail_path}" --rootfs="${JAIL_ROOTFS_PATH}" \ --name="${jail_name}" --path="${jail_path}" --rootfs="${JAIL_ROOTFS_PATH}" \
--arch="${arch}" --dist="${distro}" --release="${release}" || --arch="${arch}" --dist="${distro}" --release="${release}" ||
fail "Aborted creating rootfs..." fail 'Aborted creating rootfs...'
echo print
# Assuming the name of your jail is "myjail" # Assuming the name of your jail is "myjail"
# and "machinectl shell myjail" doesn't work # and "machinectl shell myjail" doesn't work
@ -425,27 +428,27 @@ create_jail() {
# They don't shutdown cleanly via systemctl and machinectl... # They don't shutdown cleanly via systemctl and machinectl...
if [[ "$(basename "$(readlink -f "${JAIL_ROOTFS_PATH}/sbin/init")")" != systemd ]]; then if [[ "$(basename "$(readlink -f "${JAIL_ROOTFS_PATH}/sbin/init")")" != systemd ]]; then
echo "${YELLOW}${BOLD}WARNING: DISTRO NOT SUPPORTED${NORMAL}" print "${YELLOW}${BOLD}WARNING: DISTRO NOT SUPPORTED${NORMAL}"
echo print
echo "Chosen distro appears not to use systemd..." print 'Chosen distro appears not to use systemd...'
echo print
echo "You probably won't get a shell with:" print 'You probably will not get a shell with:'
echo "machinectl shell ${jail_name}" print "machinectl shell ${jail_name}"
echo print
echo "You may get a shell with this command:" print 'You may get a shell with this command:'
# About nsenter: # About nsenter:
# shellcheck disable=SC2016 # shellcheck disable=SC2016
echo 'nsenter -t $(machinectl show '"${jail_name}"' -p Leader --value) -a /bin/sh -l' print 'nsenter -t $(machinectl show '"${jail_name}"' -p Leader --value) -a /bin/sh -l'
echo print
echo 'Read about the downsides of nsenter:' print 'Read about the downsides of nsenter:'
echo 'https://github.com/systemd/systemd/issues/12785#issuecomment-503019081' print 'https://github.com/systemd/systemd/issues/12785#issuecomment-503019081'
echo print
echo "${BOLD}Using this distro with ${SCRIPT_NAME} is NOT recommended.${NORMAL}" print "${BOLD}Using this distro with ${SCRIPT_NAME} is NOT recommended.${NORMAL}"
echo print
read -p "Abort creating jail? [Y/n] " -n 1 -r reply && echo read -p "Abort creating jail? [Y/n] " -n 1 -r reply && print
# Enter accepts default (yes) # Enter accepts default (yes)
[[ "${reply}" =~ ^([Yy]|)$ ]] && exit [[ "${reply}" =~ ^([Yy]|)$ ]] && exit
echo print
fi fi
# Config which systemd handles for us # Config which systemd handles for us
@ -510,28 +513,28 @@ create_jail() {
local systemd_nspawn_default_args=(--keep-unit --quiet --boot) local systemd_nspawn_default_args=(--keep-unit --quiet --boot)
{ {
echo "DOCKER_COMPATIBLE=${docker_compatible}" print "DOCKER_COMPATIBLE=${docker_compatible}"
echo "GPU_PASSTHROUGH=${gpu_passthrough}" print "GPU_PASSTHROUGH=${gpu_passthrough}"
echo "SYSTEMD_NSPAWN_USER_ARGS=${systemd_nspawn_user_args}" print "SYSTEMD_NSPAWN_USER_ARGS=${systemd_nspawn_user_args}"
echo print
echo "# You generally won't need to change the options below" print '# You generally will not need to change the options below'
echo "SYSTEMD_RUN_DEFAULT_ARGS=${systemd_run_default_args[*]}" print "SYSTEMD_RUN_DEFAULT_ARGS=${systemd_run_default_args[*]}"
echo "SYSTEMD_NSPAWN_DEFAULT_ARGS=${systemd_nspawn_default_args[*]}" print "SYSTEMD_NSPAWN_DEFAULT_ARGS=${systemd_nspawn_default_args[*]}"
} >"${jail_config_path}" } >"${jail_config_path}"
chmod 600 "${jail_config_path}" chmod 600 "${jail_config_path}"
# Remove the cleanup trap on exit # Remove the cleanup trap on exit
trap - EXIT trap - EXIT
echo "Done creating the jail." print 'Done creating the jail.'
echo print
read -p "Start the jail now? [Y/n] " -n 1 -r reply && echo read -p "Start the jail now? [Y/n] " -n 1 -r reply && print
# Enter accepts default (yes) # Enter accepts default (yes)
if [[ "${reply}" =~ ^([Yy]|)$ ]]; then if [[ "${reply}" =~ ^([Yy]|)$ ]]; then
start_jail "${jail_name}" start_jail "${jail_name}"
else else
echo print
echo 'Skipped starting jail.' print 'Skipped starting jail.'
fi fi
} }
@ -542,15 +545,15 @@ create_jail() {
case "${1-""}" in case "${1-""}" in
'') '')
read -p "Create a new jail? [Y/n] " -n 1 -r reply && echo read -p "Create a new jail? [Y/n] " -n 1 -r reply && print
echo print
# Enter accepts default (yes) # Enter accepts default (yes)
# https://stackoverflow.com/a/1885534 # https://stackoverflow.com/a/1885534
if [[ "${reply}" =~ ^([Yy]|)$ ]]; then if [[ "${reply}" =~ ^([Yy]|)$ ]]; then
create_jail "" create_jail ""
else else
echo "${USAGE}" print "${USAGE}"
fi fi
;; ;;
@ -563,6 +566,6 @@ start)
;; ;;
*) *)
echo "${USAGE}" print "${USAGE}"
;; ;;
esac esac