From 961731b063ddcbae35a6ab138858363326777fad Mon Sep 17 00:00:00 2001 From: JRGTH Date: Wed, 7 Jul 2021 05:05:38 -0400 Subject: [PATCH] New features and improvements revised and re-added --- usr/local/etc/bastille/bastille.conf.sample | 2 + usr/local/share/bastille/create.sh | 16 +- usr/local/share/bastille/export.sh | 232 +++++++++++++++----- usr/local/share/bastille/import.sh | 93 +++++++- 4 files changed, 268 insertions(+), 75 deletions(-) diff --git a/usr/local/etc/bastille/bastille.conf.sample b/usr/local/etc/bastille/bastille.conf.sample index 08bbfb0..c618ef3 100644 --- a/usr/local/etc/bastille/bastille.conf.sample +++ b/usr/local/etc/bastille/bastille.conf.sample @@ -44,6 +44,8 @@ bastille_zfs_options="-o compress=lz4 -o atime=off" ## default ## Export/Import options bastille_compress_xz_options="-0 -v" ## default "-0 -v" bastille_decompress_xz_options="-c -d -v" ## default "-c -d -v" +bastille_compress_gz_options="-1 -v" ## default "-1 -v" +bastille_decompress_gz_options="-k -d -c -v" ## default "-k -d -c -v" ## Networking bastille_network_loopback="bastille0" ## default: "bastille0" diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index fdd3951..2f56c09 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -259,25 +259,17 @@ create_jail() { echo if [ -z "${THICK_JAIL}" ]; then - LINK_LIST="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/sbin usr/share" + LINK_LIST="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/sbin usr/share usr/src" for _link in ${LINK_LIST}; do ln -sf /.bastille/${_link} ${_link} done - # Copy optional distfiles if they exist on the base release. + # Properly link shared ports on thin jails in read-write. if [ -d "${bastille_releasesdir}/${RELEASE}/usr/ports" ]; then if [ ! -d "${bastille_jail_path}/usr/ports" ]; then - info "Copying ports tree..." - cp -a ${bastille_releasesdir}/${RELEASE}/usr/ports ${bastille_jail_path}/usr + mkdir ${bastille_jail_path}/usr/ports fi + echo -e "${bastille_releasesdir}/${RELEASE}/usr/ports ${bastille_jail_path}/usr/ports nullfs rw 0 0" >> "${bastille_jail_fstab}" fi - if [ -d "${bastille_releasesdir}/${RELEASE}/usr/src" ]; then - if [ ! -d "${bastille_jail_path}/usr/src" ]; then - info "Copying source tree..." - ln -sf usr/src sys - cp -a ${bastille_releasesdir}/${RELEASE}/usr/src ${bastille_jail_path}/usr - fi - fi - echo fi if [ -z "${THICK_JAIL}" ]; then diff --git a/usr/local/share/bastille/export.sh b/usr/local/share/bastille/export.sh index 1a0a1d5..3e1bd77 100644 --- a/usr/local/share/bastille/export.sh +++ b/usr/local/share/bastille/export.sh @@ -32,7 +32,23 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille export TARGET [safe|tarball] | PATH" + # Build an independent usage for the export command + # Valid compress/options for ZFS systems are raw, .gz, .tgz, .txz and .xz(default) + # Valid compress/options for non ZFS configured systems are .tgz and .txz(default) + echo -e "${COLOR_RED}Usage: bastille export TARGET | option(s) | PATH${COLOR_RESET}" + + cat << EOF + Options: + + gz | --gz -- Export a ZFS jail using GZIP(.gz) compressed image. + -r | raw | --raw -- Export a ZFS jail to an uncompressed RAW image. + -s | safe | --safe -- Safely stop and start a ZFS jail before the exporting process. + tgz | --tgz -- Export a jail using simple .tgz compressed archive instead. + txz | --txz -- Export a jail using simple .txz compressed archive instead. + -v | verbose | --verbose -- Be more verbose during the ZFS send operation. + +EOF + exit 1 } # Handle special-case commands first @@ -47,81 +63,193 @@ if [ "${TARGET}" = "ALL" ]; then error_exit "Batch export is unsupported." fi -if [ $# -gt 2 ] || [ $# -lt 0 ]; then +if [ $# -gt 4 ] || [ $# -lt 0 ]; then usage fi -OPTION="${1}" -EXPATH="${2}" -SAFE_EXPORT= +zfs_enable_check() { + # Temporarily disable ZFS so we can create a standard backup archive + if [ "${bastille_zfs_enable}" = "YES" ]; then + bastille_zfs_enable="NO" + fi +} -# Handle some options -if [ -n "${OPTION}" ]; then - if [ "${OPTION}" = "-t" -o "${OPTION}" = "--txz" -o ${OPTION} = "tarball" ]; then - if [ "${bastille_zfs_enable}" = "YES" ]; then - # Temporarily disable ZFS so we can create a standard backup archive - bastille_zfs_enable="NO" - fi - elif [ "${OPTION}" = "-s" -o "${OPTION}" = "--safe" -o ${OPTION} = "safe" ]; then - SAFE_EXPORT="1" - elif echo "${OPTION}" | grep -q "\/"; then - if [ -d "${OPTION}" ]; then - EXPATH="${OPTION}" - else - error_exit "Error: Path not found." - fi - else - error_notify "Invalid option!" - usage +GZIP_EXPORT= +SAFE_EXPORT= +RAW_EXPORT= +DIR_EXPORT= +TXZ_EXPORT= +TGZ_EXPORT= +OPT_ZSEND="-R" + +# Handle and parse option args +while [ $# -gt 0 ]; do + case "${1}" in + gz|--gz) + GZIP_EXPORT="1" + shift + ;; + tgz|--tgz) + TGZ_EXPORT="1" + zfs_enable_check + shift + ;; + txz|--txz) + TXZ_EXPORT="1" + zfs_enable_check + shift + ;; + -s|safe|--safe) + SAFE_EXPORT="1" + shift + ;; + -r|raw|--raw) + RAW_EXPORT="1" + shift + ;; + -v|verbose|--verbose) + OPT_ZSEND="-Rv" + shift + ;; + *) + if echo "${1}" | grep -q "\/"; then + DIR_EXPORT="${1}" + else + usage + fi + shift + ;; + esac +done + +# Validate for combined options +if [ -n "${TXZ_EXPORT}" -o -n "${TGZ_EXPORT}" ] && [ -n "${SAFE_EXPORT}" ]; then + error_exit "Error: Simple archive modes with safe ZFS export can't be used together." +fi +if [ -z "${bastille_zfs_enable}" ]; then + if [ -n "${GZIP_EXPORT}" -o -n "${RAW_EXPORT}" -o "${SAFE_EXPORT}" ]; then + error_exit "Options --gz, --raw, --safe are valid for ZFS configured systems only." + fi +fi +if [ -n "${SAFE_EXPORT}" ]; then + # Check if container is running, otherwise just ignore + if [ -z "$(jls name | awk "/^${TARGET}$/")" ]; then + SAFE_EXPORT= fi fi # Export directory check -if [ -n "${EXPATH}" ]; then - if [ -d "${EXPATH}" ]; then +if [ -n "${DIR_EXPORT}" ]; then + if [ -d "${DIR_EXPORT}" ]; then # Set the user defined export directory - bastille_backupsdir="${EXPATH}" + bastille_backupsdir="${DIR_EXPORT}" else error_exit "Error: Path not found." fi fi -create_zfs_snap(){ +# Fallback to default if missing config parameters +if [ -z "${bastille_compress_xz_options}" ]; then + bastille_compress_xz_options="-0 -v" +fi +if [ -z "${bastille_compress_gz_options}" ]; then + bastille_compress_gz_options="-1 -v" +fi + +create_zfs_snap() { # Take a recursive temporary snapshot info "Creating temporary ZFS snapshot for export..." zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" } -jail_export() -{ +export_check() { + # Inform the user about the exporting method + if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then + if [ -n "${SAFE_EXPORT}" ]; then + EXPORT_AS="Safely exporting" + else + EXPORT_AS="Hot exporting" + fi + else + EXPORT_AS="Exporting" + fi + + if [ "${FILE_EXT}" = ".xz" -o "${FILE_EXT}" = ".gz" -o "${FILE_EXT}" = "" ]; then + EXPORT_TYPE="image" + else + EXPORT_TYPE="archive" + fi + + if [ -n "${RAW_EXPORT}" ]; then + EXPORT_INFO="to a raw ${EXPORT_TYPE}" + else + EXPORT_INFO="to a compressed ${FILE_EXT} ${EXPORT_TYPE}" + fi + + info "${EXPORT_AS} '${TARGET}' ${EXPORT_INFO}..." + + # Safely stop and snapshot the jail + if [ -n "${SAFE_EXPORT}" ]; then + bastille stop ${TARGET} + create_zfs_snap + bastille start ${TARGET} + else + create_zfs_snap + fi + + if [ "${bastille_zfs_enable}" = "YES" ]; then + info "Sending ZFS data stream..." + fi +} + +jail_export() { # Attempt to export the container DATE=$(date +%F-%H%M%S) if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ]; then - FILE_EXT="xz" + if [ -n "${RAW_EXPORT}" ]; then + FILE_EXT="" + export_check - if [ -n "${SAFE_EXPORT}" ]; then - info "Safely exporting '${TARGET}' to a compressed .${FILE_EXT} archive." - bastille stop ${TARGET} - create_zfs_snap - bastille start ${TARGET} + # Export the raw container recursively and cleanup temporary snapshots + zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" \ + > "${bastille_backupsdir}/${TARGET}_${DATE}" + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}/root@bastille_export_${DATE}" + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" + elif [ -n "${GZIP_EXPORT}" ]; then + FILE_EXT=".gz" + export_check + + # Export the raw container recursively and cleanup temporary snapshots + zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" | \ + gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}/root@bastille_export_${DATE}" + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" else - info "Hot exporting '${TARGET}' to a compressed .${FILE_EXT} archive." - create_zfs_snap - fi + FILE_EXT=".xz" + export_check - info "Sending ZFS data stream..." - # Export the container recursively and cleanup temporary snapshots - zfs send -R "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" | \ - xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" - zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}/root@bastille_export_${DATE}" - zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" + # Export the container recursively and cleanup temporary snapshots(default) + zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" | \ + xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}/root@bastille_export_${DATE}" + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" + fi fi else - # Create standard backup archive - FILE_EXT="txz" - info "Exporting '${TARGET}' to a compressed .${FILE_EXT} archive..." - cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" + if [ -n "${TGZ_EXPORT}" ]; then + FILE_EXT=".tgz" + + # Create standard tgz backup archive + info "Exporting '${TARGET}' to a compressed ${FILE_EXT} archive..." + cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + else + FILE_EXT=".txz" + + # Create standard txz backup archive(default) + info "Exporting '${TARGET}' to a compressed ${FILE_EXT} archive..." + cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + fi fi if [ "$?" -ne 0 ]; then @@ -129,8 +257,8 @@ jail_export() else # Generate container checksum file cd "${bastille_backupsdir}" - sha256 -q "${TARGET}_${DATE}.${FILE_EXT}" > "${TARGET}_${DATE}.sha256" - info "Exported '${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}' successfully." + sha256 -q "${TARGET}_${DATE}${FILE_EXT}" > "${TARGET}_${DATE}.sha256" + info "Exported '${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}' successfully." exit 0 fi } @@ -148,4 +276,6 @@ if [ "${bastille_zfs_enable}" != "YES" ]; then fi fi -jail_export +if [ -n "${TARGET}" ]; then + jail_export +fi diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index fa542ba..1c815b7 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -32,7 +32,17 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille import file [force]" + # Build an independent usage for the import command + echo -e "${COLOR_RED}Usage: bastille import FILE [option]${COLOR_RESET}" + + cat << EOF + Options: + + -f | force | --force -- Force an archive import regardless if the checksum file does not match or missing. + -v | verbose | --verbose -- Be more verbose during the ZFS receive operation. + +EOF + exit 1 } # Handle special-case commands first @@ -42,13 +52,39 @@ help|-h|--help) ;; esac -if [ $# -gt 2 ] || [ $# -lt 1 ]; then +if [ $# -gt 3 ] || [ $# -lt 1 ]; then usage fi TARGET="${1}" -OPTION="${2}" shift +OPT_FORCE= +OPT_ZRECV="-u" + +# Handle and parse option args +while [ $# -gt 0 ]; do + case "${1}" in + -f|force|--force) + OPT_FORCE="1" + shift + ;; + -v|verbose|--verbose) + OPT_ZRECV="-u -v" + shift + ;; + *) + usage + ;; + esac +done + +# Fallback to default if missing config parameters +if [ -z "${bastille_decompress_xz_options}" ]; then + bastille_decompress_xz_options="-c -d -v" +fi +if [ -z "${bastille_decompress_gz_options}" ]; then + bastille_decompress_gz_options="-k -d -c -v" +fi validate_archive() { # Compare checksums on the target archive @@ -66,7 +102,7 @@ validate_archive() { fi else # Check if user opt to force import - if [ "${OPTION}" = "-f" -o "${OPTION}" = "force" ]; then + if [ -n "${OPT_FORCE}" ]; then warn "Warning: Skipping archive validation!" else error_exit "Checksum file not found. See 'bastille import TARGET -f'." @@ -313,7 +349,7 @@ remove_zfs_datasets() { jail_import() { # Attempt to import container from file - FILE_TRIM=$(echo "${TARGET}" | sed 's/\.xz//g;s/\.txz//g;s/\.zip//g;s/\.tar\.gz//g;s/\.tar//g') + FILE_TRIM=$(echo "${TARGET}" | sed 's/\.xz//g;s/\.gz//g;s/\.tgz//g;s/\.txz//g;s/\.zip//g;s/\.tar\.gz//g;s/\.tar//g') FILE_EXT=$(echo "${TARGET}" | sed "s/${FILE_TRIM}//g") validate_archive if [ -d "${bastille_jailsdir}" ]; then @@ -321,10 +357,19 @@ jail_import() { if [ -n "${bastille_zfs_zpool}" ]; then if [ "${FILE_EXT}" = ".xz" ]; then # Import from compressed xz on ZFS systems - info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} archive." + info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} image." info "Receiving ZFS data stream..." xz ${bastille_decompress_xz_options} "${bastille_backupsdir}/${TARGET}" | \ - zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" + zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" + + # Update ZFS mountpoint property if required + update_zfsmount + elif [ "${FILE_EXT}" = ".gz" ]; then + # Import from compressed xz on ZFS systems + info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} image." + info "Receiving ZFS data stream..." + gzip ${bastille_decompress_gz_options} "${bastille_backupsdir}/${TARGET}" | \ + zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" # Update ZFS mountpoint property if required update_zfsmount @@ -340,6 +385,17 @@ jail_import() { if [ "$?" -ne 0 ]; then remove_zfs_datasets fi + elif [ "${FILE_EXT}" = ".tgz" ]; then + # Prepare the ZFS environment and restore from existing .tgz file + create_zfs_datasets + + # Extract required files to the new datasets + info "Extracting files from '${TARGET}' archive..." + tar --exclude='root' -xf "${bastille_backupsdir}/${TARGET}" --strip-components 1 -C "${bastille_jailsdir}/${TARGET_TRIM}" + tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components 2 -C "${bastille_jailsdir}/${TARGET_TRIM}/root" "${TARGET_TRIM}/root" + if [ "$?" -ne 0 ]; then + remove_zfs_datasets + fi elif [ "${FILE_EXT}" = ".zip" ]; then # Attempt to import a foreign/iocage container info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." @@ -353,9 +409,9 @@ jail_import() { rm -f "${FILE_TRIM}" "${FILE_TRIM}_root" fi info "Receiving ZFS data stream..." - zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${FILE_TRIM}" + zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${FILE_TRIM}" zfs set ${ZFS_OPTIONS} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" - zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root" + zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root" # Update ZFS mountpoint property if required update_zfsmount @@ -403,6 +459,17 @@ jail_import() { else update_config fi + elif [ -z "${FILE_EXT}" ]; then + if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$'; then + # Based on the file name, looks like we are importing a raw bastille image + # Import from uncompressed image file + info "Importing '${TARGET_TRIM}' from uncompressed image archive." + info "Receiving ZFS data stream..." + zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${bastille_backupsdir}/${TARGET}" + + # Update ZFS mountpoint property if required + update_zfsmount + fi else error_exit "Unknown archive format." fi @@ -465,9 +532,9 @@ fi # Check if archive exist then trim archive name if [ -f "${bastille_backupsdir}/${TARGET}" ]; then # Filter unsupported/unknown archives - if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.xz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.txz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.zip$\|-[0-9]\{12\}.[0-9]\{2\}.tar.gz$\|@[0-9]\{12\}.[0-9]\{2\}.tar$'; then + if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.xz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.gz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.tgz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.txz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.zip$\|-[0-9]\{12\}.[0-9]\{2\}.tar.gz$\|@[0-9]\{12\}.[0-9]\{2\}.tar$'; then if ls "${bastille_backupsdir}" | awk "/^${TARGET}$/" >/dev/null; then - TARGET_TRIM=$(echo "${TARGET}" | sed "s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.xz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.txz//;s/_[0-9]*-[0-9]*-[0-9]*.zip//;s/-[0-9]\{12\}.[0-9]\{2\}.tar.gz//;s/@[0-9]\{12\}.[0-9]\{2\}.tar//") + TARGET_TRIM=$(echo "${TARGET}" | sed "s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.xz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.gz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.tgz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.txz//;s/_[0-9]*-[0-9]*-[0-9]*.zip//;s/-[0-9]\{12\}.[0-9]\{2\}.tar.gz//;s/@[0-9]\{12\}.[0-9]\{2\}.tar//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*//") fi else error_exit "Unrecognized archive name." @@ -483,4 +550,6 @@ elif [ -d "${bastille_jailsdir}/${TARGET_TRIM}" ]; then error_exit "Container: ${TARGET_TRIM} already exists." fi -jail_import +if [ -n "${TARGET}" ]; then + jail_import +fi