diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 715cadfe..c9f8d831 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -70,11 +70,12 @@ bastille_perms_check() { usage() { cat << EOF + Bastille is an open-source system for automating deployment and management of containerized applications on FreeBSD. Usage: - bastille command [option(s)] TARGET [args] + bastille command [option(s)] TARGET [option(s)] ARGS Available Commands: bootstrap Bootstrap a FreeBSD release for container base. @@ -266,7 +267,12 @@ esac # shellcheck disable=SC2154 SCRIPTPATH="${bastille_sharedir}/${CMD}.sh" + +# Start with blank line +echo + if [ -f "${SCRIPTPATH}" ]; then + : "${UMASK:=022}" umask "${UMASK}" @@ -279,5 +285,7 @@ if [ -f "${SCRIPTPATH}" ]; then fi else + error_exit "${SCRIPTPATH} not found." + fi diff --git a/usr/local/share/bastille/cmd.sh b/usr/local/share/bastille/cmd.sh index cc6eb4ba..0a3dc371 100644 --- a/usr/local/share/bastille/cmd.sh +++ b/usr/local/share/bastille/cmd.sh @@ -95,7 +95,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index afd0a2ad..60309845 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -64,10 +64,19 @@ if [ -z "${NO_COLOR}" ] && [ -t 1 ]; then enable_color fi -# Notify message on error, and continue to next jail +# Notify message on error +# Do not echo blank line error_continue() { error_notify "$@" - echo "" + # shellcheck disable=SC2104 + continue +} + +# Notify message on error, and continue to next jail +# Echo blank line +error_continue_next_jail() { + error_notify "$@" + echo # shellcheck disable=SC2104 continue } @@ -78,8 +87,10 @@ error_notify() { } # Notify message on error and exit +# Echo blank line error_exit() { error_notify "$@" + echo exit 1 } @@ -188,13 +199,13 @@ set_target() { if get_jail_name "${_jail}" > /dev/null; then _jail="$(get_jail_name ${_jail})" else - error_continue "Error: JID \"${_jail}\" not found. Is jail running?" + error_continue_next_jail "Error: JID \"${_jail}\" not found. Is jail running?" fi elif ! check_target_exists "${_jail}"; then if jail_autocomplete "${_jail}" > /dev/null; then _jail="$(jail_autocomplete ${_jail})" elif [ $? -eq 2 ]; then - error_continue "Jail not found \"${_jail}\"" + error_continue_next_jail "Jail not found \"${_jail}\"" else exit 1 fi diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 92f6e3c0..b727e62a 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -120,7 +120,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index c54e08b5..dd56bf04 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -94,7 +94,7 @@ for _jail in ${JAILS}; do jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${JAIL_PATH} | sed 's#//#/#g')" if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then - error_continue "CP failed: ${host_path} -> ${jail_path}" + error_continue_next_jail "CP failed: ${host_path} -> ${jail_path}" fi # Print blank line diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index a77d8495..4b7d5373 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -60,7 +60,7 @@ destroy_jail() { else info "[${_jail}]:" error_notify "Jail is running." - error_continue "Use [-a|--auto] to auto-stop the jail." + error_continue_next_jail "Use [-a|--auto] to auto-stop the jail." fi if [ -d "${bastille_jail_base}" ]; then @@ -68,7 +68,7 @@ destroy_jail() { mount_points="$(mount | cut -d ' ' -f 3 | grep ${bastille_jail_base}/root/)" if [ -n "${mount_points}" ]; then error_notify "Failed to destroy jail: ${_jail}" - error_continue "Jail has mounted filesystems:\n$mount_points" + error_continue_next_jail "Jail has mounted filesystems:\n$mount_points" fi info "Deleting Jail: ${_jail}." if checkyesno bastille_zfs_enable; then @@ -82,7 +82,7 @@ destroy_jail() { # This will deal with the common "cannot unmount 'XYZ': pool or dataset is busy" # unless the force option is defined by the user, otherwise will have a partially deleted jail. if ! zfs destroy "${OPTIONS}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"; then - error_continue "[ERROR]: Jail dataset(s) appears to be busy, exiting." + error_continue_next_jail "[ERROR]: Jail dataset(s) appears to be busy, exiting." fi fi fi diff --git a/usr/local/share/bastille/htop.sh b/usr/local/share/bastille/htop.sh index 54247674..6eae1b6e 100644 --- a/usr/local/share/bastille/htop.sh +++ b/usr/local/share/bastille/htop.sh @@ -84,15 +84,16 @@ TARGET="${1}" bastille_root_check set_target_single "${TARGET}" -info "[${TARGET}]:" - check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" -else +else + info "[${TARGET}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi +info "[${TARGET}]:" + if [ ! -x "${bastille_jailsdir}/${TARGET}/root/usr/local/bin/htop" ]; then error_notify "htop not found on ${TARGET}." elif [ -x "${bastille_jailsdir}/${TARGET}/root/usr/local/bin/htop" ]; then diff --git a/usr/local/share/bastille/jcp.sh b/usr/local/share/bastille/jcp.sh index 8620e899..e5ead98a 100644 --- a/usr/local/share/bastille/jcp.sh +++ b/usr/local/share/bastille/jcp.sh @@ -100,11 +100,11 @@ for _jail in ${DEST_TARGET}; do dest_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST_PATH} | sed 's#//#/#g')" if ! cp "${OPTION}" "${source_path}" "${dest_path}"; then - error_continue "JCP failed: ${source_path} -> ${dest_path}" + error_continue_next_jail "JCP failed: ${source_path} -> ${dest_path}" fi # Print blank line - echo "" + echo fi done \ No newline at end of file diff --git a/usr/local/share/bastille/limits.sh b/usr/local/share/bastille/limits.sh index 691183e1..bb5efe2b 100644 --- a/usr/local/share/bastille/limits.sh +++ b/usr/local/share/bastille/limits.sh @@ -107,7 +107,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -184,12 +184,12 @@ for _jail in ${JAILS}; do rm -f "${bastille_jailsdir}/${_jail}/rctl.conf" info "[${TARGET}]: rctl.conf removed." else - error_continue "[${TARGET}]: rctl.conf not found." + error_continue_next_jail "[${TARGET}]: rctl.conf not found." fi ;; esac - # Print blank line on last jail - [ "${_jail}" = "${_LAST_JAIL}" ] && echo "" + # Print blank line + echo done diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index ad8a8a16..fc9f989d 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -147,7 +147,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_exit "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -167,13 +167,13 @@ for _jail in ${JAILS}; do # Create mount point if it does not exist if [ -d "${_hostpath}" ] && [ ! -d "${_fullpath}" ]; then - mkdir -p "${_fullpath}" || error_continue "Failed to create mount point." + mkdir -p "${_fullpath}" || error_continue_next_jail "Failed to create mount point." elif [ -f "${_hostpath}" ] ; then _filename="$( basename ${_hostpath} )" if echo "${_fullpath}" 2>/dev/null | grep -qow "${_filename}"; then - mkdir -p "$( dirname "${_fullpath}" )" || error_continue "Failed to create mount point." + mkdir -p "$( dirname "${_fullpath}" )" || error_continue_next_jail "Failed to create mount point." if [ ! -f "${_fullpath}" ]; then - touch "${_fullpath}" || error_continue "Failed to create mount point." + touch "${_fullpath}" || error_continue_next_jail "Failed to create mount point." else error_notify "Failed. File exists at mount point." warn "${_fullpath}" @@ -183,9 +183,9 @@ for _jail in ${JAILS}; do _fullpath_fstab="$( echo "${bastille_jailsdir}/${_jail}/root/${_jailpath_fstab}/${_filename}" 2>/dev/null | sed 's#//#/#' )" _fullpath="$( echo "${bastille_jailsdir}/${_jail}/root/${_jailpath}/${_filename}" 2>/dev/null | sed 's#//#/#' )" _fstab_entry="${_hostpath_fstab} ${_fullpath_fstab} ${_type} ${_perms} ${_checks}" - mkdir -p "$( dirname "${_fullpath}" )" || error_continue "Failed to create mount point." + mkdir -p "$( dirname "${_fullpath}" )" || error_continue_next_jail "Failed to create mount point." if [ ! -f "${_fullpath}" ]; then - touch "${_fullpath}" || error_continue "Failed to create mount point." + touch "${_fullpath}" || error_continue_next_jail "Failed to create mount point." else error_notify "Failed. File exists at mount point." warn "${_fullpath}" @@ -195,11 +195,11 @@ for _jail in ${JAILS}; do fi # Add entry to fstab and mount - echo "${_fstab_entry}" >> "${bastille_jailsdir}/${_jail}/fstab" || error_continue "Failed to create fstab entry: ${_fstab_entry}" - mount -F "${bastille_jailsdir}/${_jail}/fstab" -a || error_continue "Failed to mount volume: ${_fullpath}" + echo "${_fstab_entry}" >> "${bastille_jailsdir}/${_jail}/fstab" || error_continue_next_jail "Failed to create fstab entry: ${_fstab_entry}" + mount -F "${bastille_jailsdir}/${_jail}/fstab" -a || error_continue_next_jail "Failed to mount volume: ${_fullpath}" echo "Added: ${_fstab_entry}" # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/network.sh b/usr/local/share/bastille/network.sh index e9d89243..25302a7d 100644 --- a/usr/local/share/bastille/network.sh +++ b/usr/local/share/bastille/network.sh @@ -448,13 +448,13 @@ remove_interface() { if [ -n "${_if_vnet}" ] && echo ${_if_vnet} 2>/dev/null | grep -Eoq 'vnet[0-9]+'; then sed -i '' "/.*${_if_vnet}.*/d" "${_jail_rc_config}" else - error_continue "Failed to remove interface from /etc/rc.conf" + error_exit "Failed to remove interface from /etc/rc.conf" fi elif [ "${_if_type}" = "passthrough" ]; then if [ -n "${_if_vnet}" ]; then sed -i '' "/.*${_if_vnet}.*/d" "${_jail_rc_config}" else - error_continue "Failed to remove interface from /etc/rc.conf" + error_exit "Failed to remove interface from /etc/rc.conf" fi fi diff --git a/usr/local/share/bastille/pkg.sh b/usr/local/share/bastille/pkg.sh index 963b3da0..b1624f85 100644 --- a/usr/local/share/bastille/pkg.sh +++ b/usr/local/share/bastille/pkg.sh @@ -101,7 +101,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -126,7 +126,7 @@ for _jail in ${JAILS}; do fi # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/service.sh b/usr/local/share/bastille/service.sh index 0da284b6..b4cb4dd6 100644 --- a/usr/local/share/bastille/service.sh +++ b/usr/local/share/bastille/service.sh @@ -92,7 +92,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -100,6 +100,6 @@ for _jail in ${JAILS}; do jexec -l "${_jail}" /usr/sbin/service "$@" # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 395b9a33..1b9e8c6a 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -111,10 +111,13 @@ for _jail in ${JAILS}; do fi fi + if check_target_is_running "${_jail}"; then + info "[${_jail}]:" + error_continue_next_jail "Jail is already running." + fi + info "[${_jail}]:" - check_target_is_stopped "${_jail}" || error_continue "Jail is already running." - # Validate interfaces and add IPs to firewall table if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then _ip4_interfaces="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" @@ -138,7 +141,7 @@ for _jail in ${JAILS}; do pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" fi else - error_continue "Error: ${_if} interface does not exist." + error_continue_next_jail "Error: ${_if} interface does not exist." fi done fi @@ -161,7 +164,7 @@ for _jail in ${JAILS}; do pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" fi else - error_continue "Error: ${_if} interface does not exist." + error_continue_next_jail "Error: ${_if} interface does not exist." fi done fi @@ -188,6 +191,6 @@ for _jail in ${JAILS}; do sleep "${DELAY_TIME}" # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index 730e59ab..512a2f6a 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -86,10 +86,13 @@ set_target "${TARGET}" "reverse" for _jail in ${JAILS}; do + if check_target_is_stopped "${_jail}"; then + info "[${_jail}]:" + error_continue_next_jail "Jail is already stopped." + fi + info "[${_jail}]:" - check_target_is_running "${_jail}" || error_continue "Jail is already stopped." - # Remove RDR rules if [ "$(bastille config ${_jail} get vnet)" != "enabled" ] && [ -f "${bastille_pf_conf}" ]; then _ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" @@ -134,6 +137,6 @@ for _jail in ${JAILS}; do fi # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/sysrc.sh b/usr/local/share/bastille/sysrc.sh index d766e10d..0ef8e950 100644 --- a/usr/local/share/bastille/sysrc.sh +++ b/usr/local/share/bastille/sysrc.sh @@ -92,7 +92,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -100,6 +100,6 @@ for _jail in ${JAILS}; do jexec -l "${_jail}" /usr/sbin/sysrc "$@" # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/tags.sh b/usr/local/share/bastille/tags.sh index e971dcc0..a6c7a978 100644 --- a/usr/local/share/bastille/tags.sh +++ b/usr/local/share/bastille/tags.sh @@ -118,7 +118,7 @@ for _jail in ${JAILS}; do esac # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 069d420e..12c7d6d5 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -275,7 +275,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -471,7 +471,7 @@ for _jail in ${JAILS}; do done # Print blank line - echo "" + echo info "Template applied: ${TEMPLATE}" diff --git a/usr/local/share/bastille/top.sh b/usr/local/share/bastille/top.sh index 238f7114..7fddb290 100644 --- a/usr/local/share/bastille/top.sh +++ b/usr/local/share/bastille/top.sh @@ -90,7 +90,7 @@ check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" else error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_exit "Use [-a|--auto] to auto-start the jail." fi jexec -l "${TARGET}" /usr/bin/top diff --git a/usr/local/share/bastille/umount.sh b/usr/local/share/bastille/umount.sh index 91ddb952..e7deb6cd 100644 --- a/usr/local/share/bastille/umount.sh +++ b/usr/local/share/bastille/umount.sh @@ -92,7 +92,7 @@ for _jail in ${JAILS}; do else info "[${_jail}]:" error_notify "Jail is not running." - error_exit "Use [-a|--auto] to auto-start the jail." + error_continue_next_jail "Use [-a|--auto] to auto-start the jail." fi info "[${_jail}]:" @@ -104,29 +104,29 @@ for _jail in ${JAILS}; do # Exit if mount point non-existent if [ -z "${_mount}" ] && [ -z "${_fstab_entry}" ]; then - error_continue "The specified mount point does not exist." + error_continue_next_jail "The specified mount point does not exist." fi # Unmount if [ -n "${_mount}" ]; then - umount "${_jailpath}" || error_continue "Failed to unmount volume: ${MOUNT_PATH}" + umount "${_jailpath}" || error_continue_next_jail "Failed to unmount volume: ${MOUNT_PATH}" fi # Remove entry from fstab if [ -n "${_fstab_entry}" ]; then if ! sed -E -i '' "\, +${_jailpath_fstab} +,d" "${bastille_jailsdir}/${_jail}/fstab"; then - error_continue "Failed to delete fstab entry: ${MOUNT_PATH}" + error_continue_next_jail "Failed to delete fstab entry: ${MOUNT_PATH}" fi fi # Delete if mount point was a file if [ -f "${_jailpath}" ]; then - rm -f "${_jailpath}" || error_continue "Failed to unmount volume: ${MOUNT_PATH}" + rm -f "${_jailpath}" || error_continue_next_jail "Failed to unmount volume: ${MOUNT_PATH}" fi echo "Unmounted: ${_jailpath}" # Print blank line - echo "" + echo done diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index ba3ea52f..13057860 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -111,11 +111,13 @@ jail_check() { set_target_single "${TARGET}" check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" - else + else + info "[${TARGET}]:" error_notify "Jail is not running." - error_continue "Use [-a|--auto] to auto-start the jail." + error_exit "Use [-a|--auto] to auto-start the jail." fi if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then + info "[${TARGET}]:" error_notify "${TARGET} is not a thick container." error_exit "See 'bastille update RELEASE' to update thin jails." fi diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index ca19ac90..97bc50e9 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -107,7 +107,8 @@ thick_jail_check() { # Check if the jail is thick and is running check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${_jail}" - else + else + info "[${TARGET}]:" error_notify "Jail is not running." error_exit "Use [-a|--auto] to auto-start the jail." fi @@ -118,7 +119,8 @@ thin_jail_check() { # Check if the jail is thick and is running check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then bastille stop "${_jail}" - else + else + info "[${TARGET}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi diff --git a/usr/local/share/bastille/zfs.sh b/usr/local/share/bastille/zfs.sh index 182f69ec..5b8eae75 100644 --- a/usr/local/share/bastille/zfs.sh +++ b/usr/local/share/bastille/zfs.sh @@ -46,14 +46,13 @@ EOF zfs_snapshot() { for _jail in ${JAILS}; do - echo "" info "[${_jail}]:" # shellcheck disable=SC2140 zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" - # Print blank line on last jail - [ "${_jail}" = "${_LAST_JAIL}" ] && echo "" + # Print blank line + echo done } @@ -61,14 +60,13 @@ done zfs_destroy_snapshot() { for _jail in ${JAILS}; do - echo "" info "[${_jail}]:" # shellcheck disable=SC2140 zfs destroy -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" - # Print blank line on last jail - [ "${_jail}" = "${_LAST_JAIL}" ] && echo "" + # Print blank line + echo done } @@ -76,13 +74,12 @@ done zfs_set_value() { for _jail in ${JAILS}; do - echo "" info "[${_jail}]:" zfs "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" - # Print blank line on last jail - [ "${_jail}" = "${_LAST_JAIL}" ] && echo "" + # Print blank line + echo done } @@ -90,12 +87,11 @@ done zfs_get_value() { for _jail in ${JAILS}; do - echo "" info "[${_jail}]:" zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" - # Print blank line on last jail - [ "${_jail}" = "${_LAST_JAIL}" ] && echo "" + # Print blank line + echo done } @@ -103,13 +99,12 @@ done zfs_disk_usage() { for _jail in ${JAILS}; do - echo "" info "[${_jail}]:" zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" - # Print blank line on last jail - [ "${_jail}" = "${_LAST_JAIL}" ] && echo "" + # Print blank line + echo done }