gen2stage4/mkstage4.sh

293 lines
6.8 KiB
Bash
Raw Normal View History

2014-05-18 17:52:33 -04:00
#!/bin/bash
# checks if run as root:
if [ "$(whoami)" != 'root' ]
2014-05-18 17:52:33 -04:00
then
2019-11-03 15:13:54 -05:00
echo "$(basename "$0"): must be root."
exit 1
2014-05-18 17:52:33 -04:00
fi
# get available compression types
declare -A COMPRESS_TYPES
COMPRESS_TYPES=(
["bz2"]="bzip2 pbzip2 lbzip2"
["gz"]="gzip pigz"
["lrz"]="lrzip"
["lz"]="lzip plzip"
["lz4"]="lz4"
["lzo"]="lzop"
["xz"]="xz pixz"
["zst"]="zstd"
)
declare -A COMPRESS_AVAILABLE
for ext in "${!COMPRESS_TYPES[@]}"; do
for exe in ${COMPRESS_TYPES[${ext}]}; do
BIN=$(command -v "${exe}")
if [ "${BIN}" != "" ]; then
COMPRESS_AVAILABLE+=(["${ext}"]="${BIN}")
fi
done
done
# set flag variables to null/default
EXCLUDE_BOOT=0
EXCLUDE_CONFIDENTIAL=0
2016-02-19 15:15:25 -05:00
EXCLUDE_LOST=0
QUIET=0
USER_EXCL=()
USER_INCL=()
S_KERNEL=0
HAS_PORTAGEQ=0
COMPRESS_TYPE="bz2"
if command -v portageq &>/dev/null
then
2019-11-03 15:13:54 -05:00
HAS_PORTAGEQ=1
fi
2016-02-11 01:51:15 -05:00
USAGE="usage:\n\
$(basename "$0") [-q -c -b -l -k -p] [-s || -t <target-mountpoint>] [-e <additional excludes dir*>] [-i <additional include target>] <archive-filename> [custom-tar-options]\n\
2019-11-03 15:13:54 -05:00
-q: activates quiet mode (no confirmation).\n\
-c: excludes some confidential files (currently only .bash_history and connman network lists).\n\
2019-11-03 15:13:54 -05:00
-b: excludes boot directory.\n\
-l: excludes lost+found directory.\n\
-e: an additional excludes directory (one dir one -e, donot use it with *).\n\
-i: an additional target to include. This has higher precedence than -e, -t, and -s.\n\
2019-11-03 15:13:54 -05:00
-s: makes tarball of current system.\n\
2020-08-31 19:46:24 -04:00
-k: separately save current kernel modules and src (creates smaller archives and saves decompression time).\n\
2019-11-03 15:13:54 -05:00
-t: makes tarball of system located at the <target-mountpoint>.\n\
-C: specify tar compression (available: ${!COMPRESS_AVAILABLE[*]}).\n\
2019-11-03 15:13:54 -05:00
-h: displays help message."
2014-05-18 17:52:33 -04:00
# reads options:
while getopts ":t:C:e:i:skqcblh" flag
do
2019-11-03 15:13:54 -05:00
case "$flag" in
t)
TARGET="$OPTARG"
;;
s)
TARGET="/"
;;
C)
COMPRESS_TYPE="$OPTARG"
;;
2019-11-03 15:13:54 -05:00
q)
QUIET=1
;;
k)
S_KERNEL=1
;;
c)
EXCLUDE_CONFIDENTIAL=1
2019-11-03 15:13:54 -05:00
;;
b)
EXCLUDE_BOOT=1
;;
l)
EXCLUDE_LOST=1
;;
e)
USER_EXCL+=("--exclude=${OPTARG}")
;;
i)
USER_INCL+=("${OPTARG}")
;;
2019-11-03 15:13:54 -05:00
h)
echo -e "$USAGE"
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
2014-05-18 17:52:33 -04:00
done
if [ -z "$TARGET" ]
2016-02-11 01:45:57 -05:00
then
2019-11-03 15:13:54 -05:00
echo "$(basename "$0"): no target specified."
echo -e "$USAGE"
exit 1
2016-02-11 01:45:57 -05:00
fi
2017-03-22 12:17:24 -04:00
# make sure TARGET path ends with slash
if [[ "$TARGET" != */ ]]
2017-03-22 12:17:24 -04:00
then
2019-11-03 15:13:54 -05:00
TARGET="${TARGET}/"
2017-03-22 12:17:24 -04:00
fi
2014-05-18 17:52:33 -04:00
# shifts pointer to read mandatory output file specification
shift $((OPTIND - 1))
2014-05-18 17:52:33 -04:00
ARCHIVE=$1
# checks for correct output file specification
if [ -z "$ARCHIVE" ]
2014-05-18 17:52:33 -04:00
then
2019-11-03 15:13:54 -05:00
echo "$(basename "$0"): no archive file name specified."
echo -e "$USAGE"
exit 1
2014-05-18 17:52:33 -04:00
fi
# checks for quiet mode (no confirmation)
if ((QUIET))
2014-05-18 17:52:33 -04:00
then
2019-11-03 15:13:54 -05:00
AGREE="yes"
2014-05-18 17:52:33 -04:00
fi
# determines if filename was given with relative or absolute path
if (($(grep -c '^/' <<< "$ARCHIVE") > 0))
2014-05-18 17:52:33 -04:00
then
STAGE4_FILENAME="${ARCHIVE}.tar"
2014-05-18 17:52:33 -04:00
else
STAGE4_FILENAME="$(pwd)/${ARCHIVE}.tar"
2014-05-18 17:52:33 -04:00
fi
# Check if compression in option and filename
if [ -z "$COMPRESS_TYPE" ]
then
echo "$(basename "$0"): no archive compression type specified."
echo -e "$USAGE"
exit 1
else
STAGE4_FILENAME="${STAGE4_FILENAME}.${COMPRESS_TYPE}"
fi
# Check if specified type is available
if [ -z "${COMPRESS_AVAILABLE[$COMPRESS_TYPE]}" ]
then
echo "$(basename "$0"): specified archive compression type not supported."
echo "Supported: ${COMPRESS_AVAILABLE[*]}"
exit 1
fi
# Shifts pointer to read custom tar options
shift
mapfile -t OPTIONS <<< "$@"
# Handle when no options are passed
((${#OPTIONS[@]} == 1)) && [ -z "${OPTIONS[0]}" ] && unset OPTIONS
2014-05-18 17:52:33 -04:00
if ((S_KERNEL))
then
2019-11-03 15:13:54 -05:00
USER_EXCL+=("--exclude=${TARGET}usr/src/*")
USER_EXCL+=("--exclude=${TARGET}lib*/modules/*")
fi
2014-05-18 17:52:33 -04:00
# Excludes:
EXCLUDES=(
"--exclude=${TARGET}dev/*"
"--exclude=${TARGET}var/tmp/*"
"--exclude=${TARGET}media/*"
"--exclude=${TARGET}mnt/*/*"
"--exclude=${TARGET}proc/*"
"--exclude=${TARGET}run/*"
"--exclude=${TARGET}sys/*"
"--exclude=${TARGET}tmp/*"
"--exclude=${TARGET}var/lock/*"
"--exclude=${TARGET}var/log/*"
"--exclude=${TARGET}var/run/*"
"--exclude=${TARGET}var/lib/docker/*"
)
EXCLUDES_DEFAULT_PORTAGE=(
"--exclude=${TARGET}var/db/repos/gentoo/*"
"--exclude=${TARGET}var/cache/distfiles/*"
"--exclude=${TARGET}usr/portage/*"
)
2014-05-18 17:52:33 -04:00
EXCLUDES+=("${USER_EXCL[@]}")
INCLUDES=(
)
INCLUDES+=("${USER_INCL[@]}")
if [ "$TARGET" == '/' ]
2014-05-18 17:52:33 -04:00
then
EXCLUDES+=("--exclude=$(realpath "$STAGE4_FILENAME")")
if ((HAS_PORTAGEQ))
2019-11-03 15:13:54 -05:00
then
EXCLUDES+=("--exclude=$(portageq get_repo_path / gentoo)/*")
EXCLUDES+=("--exclude=$(portageq distdir)/*")
else
EXCLUDES+=("${EXCLUDES_DEFAULT_PORTAGE[@]}")
fi
else
EXCLUDES+=("${EXCLUDES_DEFAULT_PORTAGE[@]}")
2014-05-18 17:52:33 -04:00
fi
if ((EXCLUDE_CONFIDENTIAL))
2014-05-18 17:52:33 -04:00
then
EXCLUDES+=("--exclude=${TARGET}home/*/.bash_history")
EXCLUDES+=("--exclude=${TARGET}root/.bash_history")
2019-11-03 15:13:54 -05:00
EXCLUDES+=("--exclude=${TARGET}var/lib/connman/*")
2014-05-18 17:52:33 -04:00
fi
if ((EXCLUDE_BOOT))
2014-05-18 17:52:33 -04:00
then
2019-11-03 15:13:54 -05:00
EXCLUDES+=("--exclude=${TARGET}boot/*")
2014-05-18 17:52:33 -04:00
fi
if ((EXCLUDE_LOST))
then
2019-11-03 15:13:54 -05:00
EXCLUDES+=("--exclude=lost+found")
fi
# Compression options
COMP_OPTIONS=("${COMPRESS_AVAILABLE[$COMPRESS_TYPE]}")
2022-09-12 09:11:35 -04:00
# This currently breaks the command, and is temporarily disables, see:
# https://github.com/TheChymera/mkstage4/issues/46
#if [[ "${COMPRESS_AVAILABLE[$COMPRESS_TYPE]}" == *"/xz" ]]
#then
# COMP_OPTIONS+=("-T0")
#fi
2014-05-18 17:52:33 -04:00
# Generic tar options:
TAR_OPTIONS=(
-cpP
--ignore-failed-read
"--xattrs-include='*.*'"
--numeric-owner
2022-09-12 09:11:35 -04:00
"--use-compress-prog=\"${COMP_OPTIONS[@]}\""
)
2014-05-18 17:52:33 -04:00
# if not in quiet mode, this message will be displayed:
if [[ "$AGREE" != 'yes' ]]
2014-05-18 17:52:33 -04:00
then
2019-11-03 15:13:54 -05:00
echo "Are you sure that you want to make a stage 4 tarball of the system"
echo "located under the following directory?"
echo "$TARGET"
echo
2019-11-03 15:13:54 -05:00
echo "WARNING: since all data is saved by default the user should exclude all"
echo "security- or privacy-related files and directories, which are not"
echo "already excluded by mkstage4 options (such as -c), manually per cmdline."
echo "example: \$ $(basename "$0") -s /my-backup --exclude=/etc/ssh/ssh_host*"
echo
2019-11-03 15:13:54 -05:00
echo "COMMAND LINE PREVIEW:"
echo 'tar' "${TAR_OPTIONS[@]}" "${INCLUDES[@]}" "${EXCLUDES[@]}" "${OPTIONS[@]}" -f "$STAGE4_FILENAME" "${TARGET}"
if ((S_KERNEL))
2019-11-03 15:13:54 -05:00
then
echo
echo 'tar' "${TAR_OPTIONS[@]}" -f "$STAGE4_FILENAME.ksrc" "${TARGET}usr/src/linux-$(uname -r)"
echo 'tar' "${TAR_OPTIONS[@]}" -f "$STAGE4_FILENAME.kmod" "${TARGET}lib"*"/modules/$(uname -r)"
2019-11-03 15:13:54 -05:00
fi
echo
echo -n 'Type "yes" to continue or anything else to quit: '
2019-11-03 15:13:54 -05:00
read -r AGREE
2014-05-18 17:52:33 -04:00
fi
# start stage4 creation:
if [ "$AGREE" == 'yes' ]
2014-05-18 17:52:33 -04:00
then
tar "${TAR_OPTIONS[@]}" "${INCLUDES[@]}" "${EXCLUDES[@]}" "${OPTIONS[@]}" -f "$STAGE4_FILENAME" "${TARGET}"
if ((S_KERNEL))
2019-11-03 15:13:54 -05:00
then
tar "${TAR_OPTIONS[@]}" -f "$STAGE4_FILENAME.ksrc" "${TARGET}usr/src/linux-$(uname -r)"
tar "${TAR_OPTIONS[@]}" -f "$STAGE4_FILENAME.kmod" "${TARGET}lib"*"/modules/$(uname -r)"
2019-11-03 15:13:54 -05:00
fi
2014-05-18 17:52:33 -04:00
fi