gen2stage4/mkstage4.sh

298 lines
8 KiB
Bash
Raw Normal View History

2022-12-15 17:41:36 -05:00
#!/usr/bin/env bash
# get available compression types
2024-08-02 21:50:53 -04:00
declare -A compressTypes
compressTypes=(
["bz2"]="bzip2 pbzip2 lbzip2"
["gz"]="gzip pigz"
["lrz"]="lrzip"
["lz"]="lzip plzip"
["lz4"]="lz4"
["lzo"]="lzop"
["xz"]="xz pixz"
["zst"]="zstd"
2024-08-02 21:50:53 -04:00
)
declare -A compressAvail
for ext in "${!compressTypes[@]}"; do
2024-08-03 14:24:57 -04:00
for exechk in ${compressTypes[${ext}]}; do
binchk=$(command -v "${exechk}")
if [[ -n "$binchk" ]]; then
compressAvail+=(["${ext}"]="$binchk")
fi
done
done
# set flag variables to null/default
2024-08-02 21:50:53 -04:00
optExcludeBoot=false
optExcludeConfidential=false
2024-08-03 14:24:57 -04:00
optExcludeLost=true
2024-08-02 21:50:53 -04:00
optQuiet=false
optUserExclude=()
optUserInclude=()
optCompressType="bz2"
optSeperateKernel=false
2024-08-02 21:50:53 -04:00
function showHelp() {
echo "Usage:"
2024-08-03 15:31:13 -04:00
echo "$(basename "$0") [-b -c -k -l -q] [-C <type>] [-s || -t <target>] [-e <exclude>...] [-i <include>...] <archive> [-- [tar-opts]]"
echo "Position Arguments:"
echo " <archive> archive name to create with optional path"
echo " [tar-opts] additional options to pass to tar command"
2024-08-02 21:50:53 -04:00
echo
2024-08-03 15:31:13 -04:00
echo "Options:"
echo " -b excludes boot directory"
echo " -c excludes some confidential files (currently only .bash_history and connman network lists)"
echo " -k separately save current kernel modules and src (creates smaller targetArchives and saves decompression time)"
echo " -l includes lost+found directory"
echo " -q activates quiet mode (no confirmation)"
echo " -C <type> specify tar compression (default: ${optCompressType}, available: ${!compressAvail[*]})"
echo " -s makes archive of current system"
echo " -t <path> makes archive of system located at the <path>"
echo " -e <exclude> an additional exclude directory (one dir one -e, do not use it with *)"
echo " -i <include> an additional include. This has higher precedence than -e, -t, and -s"
echo " -h display this help message."
2024-08-02 21:50:53 -04:00
if [[ "$1" -ge 0 ]]; then
exit "$1"
else
exit 0
fi
}
function errorMsg() {
local rc=0
if [[ "$1" -gt 0 ]]; then
rc="$1"
shift
fi
echo "$*" >&2
if [[ "$rc" -gt 0 ]]; then
exit "$rc"
fi
}
2024-08-03 02:22:34 -04:00
2014-05-18 17:52:33 -04:00
# reads options:
2024-08-02 21:50:53 -04:00
tarArgs=()
while [[ $# -gt 0 ]]; do
while getopts ":t:C:e:i:skqcblh" flag; do
case "$flag" in
t) targetPath="$OPTARG";;
s) targetPath="/";;
C) optCompressType="$OPTARG";;
q) optQuiet=true;;
k) optSeperateKernel=true;;
c) optExcludeConfidential=true;;
b) optExcludeBoot=true;;
2024-08-03 14:24:57 -04:00
l) optExcludeLost=false;;
2024-08-03 02:22:34 -04:00
e) optUserExclude+=("${OPTARG}");;
2024-08-02 21:50:53 -04:00
i) optUserInclude+=("$OPTARG");;
h) showHelp 0;;
\?) errorMsg 1 "Invalid option: -$OPTARG";;
:) errorMsg 1 "Option -$OPTARG requires an argument.";;
esac
done || exit 1
[[ $OPTIND -gt $# ]] && break # reached the end of parameters
shift $((OPTIND - 1)) # Free processed options so far
OPTIND=1 # we must reset OPTIND
if [[ -z "$targetArchive" ]]; then
targetArchive=$1
else
tarArgs[${#tarArgs[*]}]=$1
fi
#args[${#args[*]}]=$1 # save first non-option argument (a.k.a. positional argument)
shift # remove saved arg
2014-05-18 17:52:33 -04:00
done
2024-08-03 15:31:13 -04:00
2024-08-02 21:50:53 -04:00
# checks if run as root:
if [[ "$(id -u)" -ne 0 ]]; then
echo "$(basename "$0"): must run as root"
exit 250
fi
2024-08-02 21:50:53 -04:00
if [[ -z "$targetPath" ]]; then
echo "$(basename "$0"): no system path specified"
2019-11-03 15:13:54 -05:00
exit 1
2016-02-11 01:45:57 -05:00
fi
2024-08-02 21:50:53 -04:00
# make sure targetPath path ends with slash
if [[ "$targetPath" != */ ]]; then
targetPath="${targetPath}/"
2017-03-22 12:17:24 -04:00
fi
2014-05-18 17:52:33 -04:00
# checks for correct output file specification
2024-08-02 21:50:53 -04:00
if [[ -z "$targetArchive" ]]; then
echo "$(basename "$0"): no archive file name specified"
2019-11-03 15:13:54 -05:00
exit 1
2014-05-18 17:52:33 -04:00
fi
# determines if filename was given with relative or absolute path
2024-08-02 21:50:53 -04:00
#if (($(grep -c '^/' <<< "$targetArchive") > 0)); then
if [[ "$targetArchive" =~ ^\/.* ]]; then
2024-08-03 02:22:34 -04:00
stage4Filename="${targetArchive}"
2014-05-18 17:52:33 -04:00
else
2024-08-03 02:22:34 -04:00
stage4Filename="$(pwd)/${targetArchive}"
2014-05-18 17:52:33 -04:00
fi
# Check if compression in option and filename
2024-08-02 21:50:53 -04:00
if [[ -z "$optCompressType" ]]; then
echo "$(basename "$0"): no archive compression type specified"
exit 1
else
2024-08-03 02:22:34 -04:00
#stage4Filename="${stage4Filename}.${optCompressType}"
stage4Ext="tar.${optCompressType}"
fi
# Check if specified type is available
2024-08-02 21:50:53 -04:00
if [[ -z "${compressAvail[$optCompressType]}" ]]; then
2024-08-03 14:24:57 -04:00
echo "$(basename "$0"): specified archive compression type not supported."
2024-08-02 21:50:53 -04:00
echo "Supported: ${compressAvail[*]}"
exit 1
fi
2024-08-03 14:33:30 -04:00
# Check if using seperate kernel archive option
2024-08-03 02:22:34 -04:00
if $optSeperateKernel; then
optUserExclude+=("${targetPath}usr/src/*")
optUserExclude+=("${targetPath}lib*/modules/*")
fi
2024-08-02 21:50:53 -04:00
# tarExcludes:
tarExcludes=(
2024-08-03 02:22:34 -04:00
"dev/*"
"var/tmp/*"
"media/*"
"mnt/*/*"
"proc/*"
"run/*"
"sys/*"
"tmp/*"
"var/lock/*"
"var/log/*"
"var/run/*"
"var/lib/docker/*"
"var/lib/containers/*"
"var/lib/machines/*"
"var/lib/libvirt/*"
"var/lib/lxd/*"
2024-08-03 14:24:57 -04:00
"home/*/*"
)
2024-08-02 21:50:53 -04:00
tarExcludesPortage=(
2024-08-03 02:22:34 -04:00
"var/db/repos/*/*"
"var/cache/distfiles/*"
"var/cache/binpkgs/*"
"usr/portage/*"
)
2014-05-18 17:52:33 -04:00
2024-08-03 02:22:34 -04:00
tarIncludes=(
"dev/console"
"dev/null"
"var/db/pkg/*"
)
2024-08-03 02:22:34 -04:00
tarExcludes=("${tarExcludes[@]/#/"$targetPath"}")
tarIncludes=("${tarIncludes[@]/#/"$targetPath"}")
2024-08-02 21:50:53 -04:00
if [[ "$targetPath" == '/' ]]; then
2024-08-03 14:24:57 -04:00
tarExcludes+=("$(realpath "${stage4Filename}")*")
#if $optSeperateKernel; then
# tarExcludes+=("$(realpath "${stage4Filename}.ksrc.${stage4Ext}")")
# tarExcludes+=("$(realpath "${stage4Filename}.kmod.${stage4Ext}")")
#fi
2024-08-03 02:22:34 -04:00
if command -v portageq &>/dev/null; then
2024-08-02 21:50:53 -04:00
portageRepos=$(portageq get_repos /)
for i in ${portageRepos}; do
2024-08-03 02:22:34 -04:00
repoPath=$(portageq get_repo_path / "${i}")
tarExcludes+=("${repoPath}/*")
done
2024-08-03 02:22:34 -04:00
tarExcludes+=("$(portageq distdir)/*")
tarExcludes+=("$(portageq pkgdir)/*")
2019-11-03 15:13:54 -05:00
else
2024-08-03 02:22:34 -04:00
tarExcludes+=("${tarExcludesPortage[@]/#/"/"}")
2019-11-03 15:13:54 -05:00
fi
else
2024-08-03 02:22:34 -04:00
tarExcludes+=("${tarExcludesPortage[@]/#/"$targetPath"}")
2014-05-18 17:52:33 -04:00
fi
2024-08-02 21:50:53 -04:00
if $optExcludeConfidential; then
2024-08-03 02:22:34 -04:00
tarExcludes+=("${targetPath}home/*/.bash_history")
tarExcludes+=("${targetPath}root/.bash_history")
tarExcludes+=("${targetPath}var/lib/connman/*")
2014-05-18 17:52:33 -04:00
fi
2024-08-02 21:50:53 -04:00
if $optExcludeBoot; then
2024-08-03 02:22:34 -04:00
tarExcludes+=("${targetPath}boot/*")
2014-05-18 17:52:33 -04:00
fi
2024-08-02 21:50:53 -04:00
if $optExcludeLost; then
2024-08-03 02:22:34 -04:00
tarExcludes+=("lost+found")
fi
2024-08-03 02:22:34 -04:00
tarExcludes+=("${optUserExclude[@]}")
tarIncludes+=("${optUserInclude[@]}")
# Compression options
2024-08-02 21:50:53 -04:00
compressOptions=("${compressAvail[$optCompressType]}")
if [[ "${compressAvail[$optCompressType]}" == *"/xz" ]]; then
compressOptions+=("-T0")
2022-09-12 12:11:20 -04:00
fi
2014-05-18 17:52:33 -04:00
# Generic tar options:
2024-08-02 21:50:53 -04:00
tarOptions=(
2024-08-03 02:22:34 -04:00
"-cpP"
"--ignore-failed-read"
2023-03-12 01:30:55 -05:00
"--xattrs-include=*.*"
2024-08-03 02:22:34 -04:00
"--numeric-owner"
2023-06-16 22:18:08 -04:00
"--checkpoint=.500"
2024-08-02 21:50:53 -04:00
"--use-compress-prog=${compressOptions[*]}"
)
tarOptions+=("${tarArgs[@]}")
2024-08-02 21:50:53 -04:00
2024-08-03 14:24:57 -04:00
2024-08-02 21:50:53 -04:00
# if not in optQuiet mode, this message will be displayed:
if ! $optQuiet; 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?"
2024-08-02 21:50:53 -04:00
echo "$targetPath"
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:"
2024-08-03 02:22:34 -04:00
#echo 'tar' "${tarOptions[@]}" "${tarIncludes[@]}" "${tarExcludes[@]}" -f "$stage4Filename" "${targetPath}"
echo 'tar' "${tarOptions[@]}" "${tarIncludes[@]/#/--include=}" "${tarExcludes[@]/#/--exclude=}" -f "${stage4Filename}.${stage4Ext}" "${targetPath}"
#${excludes[@]/#/--exclude=
2024-08-02 21:50:53 -04:00
if $optSeperateKernel; then
echo
2024-08-03 02:22:34 -04:00
echo 'tar' "${tarOptions[@]}" -f "${stage4Filename}.ksrc.${stage4Ext}" "${targetPath}usr/src/linux-$(uname -r)"
echo 'tar' "${tarOptions[@]}" -f "${stage4Filename}.kmod.${stage4Ext}" "${targetPath}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: '
2024-08-03 02:22:34 -04:00
read -r promptAgree
if [[ "${promptAgree,,}" == "yes" ]]; then
2024-08-02 21:50:53 -04:00
optQuiet=true
fi
2014-05-18 17:52:33 -04:00
fi
# start stage4 creation:
2024-08-02 21:50:53 -04:00
if $optQuiet; then
#echo "Would've worked"
tar "${tarOptions[@]}" "${tarIncludes[@]/#/--include=}" "${tarExcludes[@]/#/--exclude=}" -f "${stage4Filename}.${stage4Ext}" "${targetPath}"
if [[ "$optSeperateKernel" ]]
then
tar "${tarOptions[@]}" -f "${stage4Filename}.ksrc.${stage4Ext}" "${targetPath}usr/src/linux-$(uname -r)"
tar "${tarOptions[@]}" -f "${stage4Filename}.kmod.${stage4Ext}" "${targetPath}lib"*"/modules/$(uname -r)"
fi
2014-05-18 17:52:33 -04:00
fi