2022-12-15 17:41:36 -05:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
2020-04-17 04:43:11 -04:00
|
|
|
# get available compression types
|
2024-08-02 21:50:53 -04:00
|
|
|
declare -A compressTypes
|
|
|
|
compressTypes=(
|
2020-04-17 04:43:11 -04:00
|
|
|
["bz2"]="bzip2 pbzip2 lbzip2"
|
|
|
|
["gz"]="gzip pigz"
|
|
|
|
["lrz"]="lrzip"
|
|
|
|
["lz"]="lzip plzip"
|
|
|
|
["lz4"]="lz4"
|
|
|
|
["lzo"]="lzop"
|
|
|
|
["xz"]="xz pixz"
|
2020-11-29 17:12:29 -05:00
|
|
|
["zst"]="zstd"
|
2024-08-02 21:50:53 -04:00
|
|
|
)
|
|
|
|
declare -A compressAvail
|
|
|
|
for ext in "${!compressTypes[@]}"; do
|
|
|
|
for exe in ${compressTypes[${ext}]}; do
|
2020-04-17 04:43:11 -04:00
|
|
|
BIN=$(command -v "${exe}")
|
2024-08-02 21:50:53 -04:00
|
|
|
if [[ -n "$BIN" ]]; then
|
|
|
|
compressAvail+=(["${ext}"]="$BIN")
|
2020-04-17 04:43:11 -04:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
|
|
|
# set flag variables to null/default
|
2024-08-02 21:50:53 -04:00
|
|
|
optExcludeBoot=false
|
|
|
|
optExcludeConfidential=false
|
|
|
|
optExcludeLost=false
|
|
|
|
optQuiet=false
|
|
|
|
optUserExclude=()
|
|
|
|
optUserInclude=()
|
|
|
|
optCompressType="bz2"
|
|
|
|
optSeperateKernel=false
|
|
|
|
hasPortageQ=false
|
|
|
|
|
|
|
|
if command -v portageq &>/dev/null; then
|
|
|
|
hasPortageQ=true
|
2019-08-05 08:18:24 -04:00
|
|
|
fi
|
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
function showHelp() {
|
|
|
|
echo "Usage:"
|
|
|
|
echo "$(basename "$0") [-b -c -k -l -q] [-C <type>] [-s || -t <target>] [-e <exclude*>] [-i <include>] <archivename> [additional-tar-options]"
|
|
|
|
echo
|
|
|
|
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 excludes lost+found directory"
|
|
|
|
echo "-q activates quiet mode (no confirmation)"
|
|
|
|
echo "-C <type> specify tar compression (default: ${optCompressType}, available: ${!compressAvail[*]})"
|
|
|
|
echo "-s makes tarball of current system"
|
|
|
|
echo "-t <path> makes tarball of system located at the <targetPath-mountpoint>"
|
|
|
|
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."
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2014-05-20 03:07:01 -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;;
|
|
|
|
l) optExcludeLost=true;;
|
|
|
|
e) optUserExclude+=("--exclude=${OPTARG}");;
|
|
|
|
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-02 21:50:53 -04:00
|
|
|
# checks if run as root:
|
|
|
|
#if [[ "$(whoami)" != 'root' ]]
|
|
|
|
#then
|
|
|
|
# echo "$(basename "$0"): must be root."
|
|
|
|
# exit 1
|
|
|
|
#fi
|
|
|
|
|
|
|
|
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
|
|
|
# shifts pointer to read mandatory output file specification
|
2024-08-02 21:50:53 -04:00
|
|
|
#shift $((OPTIND - 1))
|
|
|
|
#targetArchive=${args[0]}
|
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
|
|
|
|
stage4Filename="${targetArchive}.tar"
|
2014-05-18 17:52:33 -04:00
|
|
|
else
|
2024-08-02 21:50:53 -04:00
|
|
|
stage4Filename="$(pwd)/${targetArchive}.tar"
|
2014-05-18 17:52:33 -04:00
|
|
|
fi
|
|
|
|
|
2020-04-17 04:43:11 -04:00
|
|
|
# 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"
|
2020-04-17 04:43:11 -04:00
|
|
|
exit 1
|
|
|
|
else
|
2024-08-02 21:50:53 -04:00
|
|
|
stage4Filename="${stage4Filename}.${optCompressType}"
|
2020-04-17 04:43:11 -04:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Check if specified type is available
|
2024-08-02 21:50:53 -04:00
|
|
|
if [[ -z "${compressAvail[$optCompressType]}" ]]; then
|
|
|
|
echo "$(basename "$0"): specified targetArchive compression type not supported."
|
|
|
|
echo "Supported: ${compressAvail[*]}"
|
2020-04-17 04:43:11 -04:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Shifts pointer to read custom tar options
|
2024-08-02 21:50:53 -04:00
|
|
|
#shift
|
|
|
|
#mapfile -t OPTIONS <<< "$@"
|
2019-11-07 01:11:16 -05:00
|
|
|
# Handle when no options are passed
|
2024-08-02 21:50:53 -04:00
|
|
|
#((${#OPTIONS[@]} == 1)) && [ -z "${OPTIONS[0]}" ] && unset OPTIONS
|
2014-05-18 17:52:33 -04:00
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
if ((optSeperateKernel)); then
|
|
|
|
optUserExclude+=("--exclude=\"${targetPath}usr/src/*\"")
|
|
|
|
optUserExclude+=("--exclude=\"${targetPath}lib*/modules/*\"")
|
2018-05-10 23:13:12 -04:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
# tarExcludes:
|
|
|
|
tarExcludes=(
|
|
|
|
"--exclude=\"${targetPath}dev/*\""
|
|
|
|
"--exclude=\"${targetPath}var/tmp/*\""
|
|
|
|
"--exclude=\"${targetPath}media/*\""
|
|
|
|
"--exclude=\"${targetPath}mnt/*/*\""
|
|
|
|
"--exclude=\"${targetPath}proc/*\""
|
|
|
|
"--exclude=\"${targetPath}run/*\""
|
|
|
|
"--exclude=\"${targetPath}sys/*\""
|
|
|
|
"--exclude=\"${targetPath}tmp/*\""
|
|
|
|
"--exclude=\"${targetPath}var/lock/*\""
|
|
|
|
"--exclude=\"${targetPath}var/log/*\""
|
|
|
|
"--exclude=\"${targetPath}var/run/*\""
|
|
|
|
"--exclude=\"${targetPath}var/lib/docker/*\""
|
|
|
|
"--exclude=\"${targetPath}var/lib/containers/*\""
|
|
|
|
"--exclude=\"${targetPath}var/lib/machines/*\""
|
|
|
|
"--exclude=\"${targetPath}var/lib/libvirt/*\""
|
2019-11-03 12:25:01 -05:00
|
|
|
)
|
2018-07-10 09:36:10 -04:00
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
tarExcludesPortage=(
|
|
|
|
"--exclude=\"${targetPath}var/db/repos/*/*\""
|
|
|
|
"--exclude=\"${targetPath}var/cache/distfiles/*\""
|
|
|
|
"--exclude=\"${targetPath}usr/portage/*\""
|
2019-11-03 12:25:01 -05:00
|
|
|
)
|
2014-05-18 17:52:33 -04:00
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
tarExcludes+=("${optUserExclude[@]}")
|
2018-05-10 23:13:12 -04:00
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
tarIncludes=()
|
2020-04-02 22:10:09 -04:00
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
tarIncludes+=("${optUserInclude[@]}")
|
|
|
|
|
|
|
|
if [[ "$targetPath" == '/' ]]; then
|
|
|
|
tarExcludes+=("--exclude=\"$(realpath "$stage4Filename")\"")
|
|
|
|
if $hasPortageQ; then
|
|
|
|
portageRepos=$(portageq get_repos /)
|
|
|
|
for i in ${portageRepos}; do
|
|
|
|
repoPath=$(portageq get_repoPath / "${i}")
|
|
|
|
tarExcludes+=("--exclude=\"${repoPath}/*\"")
|
2023-05-23 18:06:00 -04:00
|
|
|
done
|
2024-08-02 21:50:53 -04:00
|
|
|
tarExcludes+=("--exclude=\"$(portageq distdir)/*\"")
|
2019-11-03 15:13:54 -05:00
|
|
|
else
|
2024-08-02 21:50:53 -04:00
|
|
|
tarExcludes+=("${tarExcludesPortage[@]}")
|
2019-11-03 15:13:54 -05:00
|
|
|
fi
|
2019-08-05 08:18:24 -04:00
|
|
|
else
|
2024-08-02 21:50:53 -04:00
|
|
|
tarExcludes+=("${tarExcludesPortage[@]}")
|
2014-05-18 17:52:33 -04:00
|
|
|
fi
|
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
if $optExcludeConfidential; then
|
|
|
|
tarExcludes+=("--exclude=\"${targetPath}home/*/.bash_history\"")
|
|
|
|
tarExcludes+=("--exclude=\"${targetPath}root/.bash_history\"")
|
|
|
|
tarExcludes+=("--exclude=\"${targetPath}var/lib/connman/*\"")
|
2014-05-18 17:52:33 -04:00
|
|
|
fi
|
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
if $optExcludeBoot; then
|
|
|
|
tarExcludes+=("--exclude=\"${targetPath}boot/*\"")
|
2014-05-18 17:52:33 -04:00
|
|
|
fi
|
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
if $optExcludeLost; then
|
|
|
|
tarExcludes+=("--exclude=\"lost+found\"")
|
2016-02-18 00:45:51 -05:00
|
|
|
fi
|
|
|
|
|
2020-04-17 04:43:11 -04:00
|
|
|
# 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
|
|
|
|
2020-04-17 04:43:11 -04:00
|
|
|
# Generic tar options:
|
2024-08-02 21:50:53 -04:00
|
|
|
tarOptions=(
|
2020-04-17 04:43:11 -04:00
|
|
|
-cpP
|
|
|
|
--ignore-failed-read
|
2023-03-12 01:30:55 -05:00
|
|
|
"--xattrs-include=*.*"
|
2020-04-17 04:43:11 -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[*]}"
|
|
|
|
)
|
2020-04-17 04:43:11 -04:00
|
|
|
|
2024-08-02 21:50:53 -04:00
|
|
|
tarOptions+=(${tarArgs[@]})
|
|
|
|
|
|
|
|
# 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"
|
2019-11-07 01:11:16 -05:00
|
|
|
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*"
|
2019-11-07 01:11:16 -05:00
|
|
|
echo
|
2019-11-03 15:13:54 -05:00
|
|
|
echo "COMMAND LINE PREVIEW:"
|
2024-08-02 21:50:53 -04:00
|
|
|
echo 'tar' "${tarOptions[@]}" "${tarIncludes[@]}" "${tarExcludes[@]}" "${OPTIONS[@]}" -f "$stage4Filename" "${targetPath}"
|
|
|
|
if $optSeperateKernel; then
|
2019-11-07 01:11:16 -05:00
|
|
|
echo
|
2024-08-02 21:50:53 -04:00
|
|
|
echo 'tar' "${tarOptions[@]}" -f "$stage4Filename.ksrc" "${targetPath}usr/src/linux-$(uname -r)"
|
|
|
|
echo 'tar' "${tarOptions[@]}" -f "$stage4Filename.kmod" "${targetPath}lib"*"/modules/$(uname -r)"
|
2019-11-03 15:13:54 -05:00
|
|
|
fi
|
2019-11-07 01:11:16 -05:00
|
|
|
echo
|
|
|
|
echo -n 'Type "yes" to continue or anything else to quit: '
|
2019-11-03 15:13:54 -05:00
|
|
|
read -r AGREE
|
2024-08-02 21:50:53 -04:00
|
|
|
if [[ "${AGREE,,}" == "yes" ]]; then
|
|
|
|
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[@]}" "${tarExcludes[@]}" "${OPTIONS[@]}" -f "$stage4Filename" "${targetPath}"
|
|
|
|
#if [[ "$optSeperateKernel" ]]
|
|
|
|
#then
|
|
|
|
# tar "${tarOptions[@]}" -f "$stage4Filename.ksrc" "${targetPath}usr/src/linux-$(uname -r)"
|
|
|
|
# tar "${tarOptions[@]}" -f "$stage4Filename.kmod" "${targetPath}lib"*"/modules/$(uname -r)"
|
|
|
|
#fi
|
2014-05-18 17:52:33 -04:00
|
|
|
fi
|