mirror of
https://github.com/erenfro/systemrescue-backup.git
synced 2024-11-13 21:58:58 -05:00
Initial fork from resticprofile-base, welcome to systemrescue-backup
This commit is contained in:
commit
1409d033d1
33 changed files with 2744 additions and 0 deletions
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
config/*
|
||||||
|
!config/.keep
|
||||||
|
!config/sysrescue/
|
||||||
|
!config/sysrescue/.keep
|
||||||
|
config/sysrescue/build_into_srm/usr/*
|
||||||
|
config/sysrescue/build_into_srm/root/*
|
||||||
|
!config/sysrescue/build_into_srm/.squashfs-pseudo
|
||||||
|
!config/sysrescue/iso_add/*
|
||||||
|
profiles.toml
|
||||||
|
key
|
||||||
|
excludes
|
0
config/.keep
Normal file
0
config/.keep
Normal file
0
config/sysrescue/.keep
Normal file
0
config/sysrescue/.keep
Normal file
10
config/sysrescue/build_into_srm/.squashfs-pseudo
Normal file
10
config/sysrescue/build_into_srm/.squashfs-pseudo
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/root m 700 root root
|
||||||
|
/root/.ssh m 700 root root
|
||||||
|
/root/.ssh/authorized_keys m 600 root root
|
||||||
|
/root/.config m 755 root root
|
||||||
|
/root/.config/resticprofile m 700 root root
|
||||||
|
/root/.config/resticprofile/key m 600 root root
|
||||||
|
/root/.config/resticprofile/profiles.toml m 500 root root
|
||||||
|
/root/.config/resticprofile/excludes m 600 root root
|
||||||
|
/root/.config/resticprofile/root-excludes m 600 root root-excludes
|
||||||
|
|
15
config/sysrescue/iso_add/sysrescue.d/500-settings.yaml
Normal file
15
config/sysrescue/iso_add/sysrescue.d/500-settings.yaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
global:
|
||||||
|
copytoram: true
|
||||||
|
checksum: true
|
||||||
|
loadsrm: true
|
||||||
|
dostartx: true
|
||||||
|
setkmap: us
|
||||||
|
|
||||||
|
autorun:
|
||||||
|
ar_disable: false
|
||||||
|
ar_nowait: false
|
||||||
|
ar_nodel: false
|
||||||
|
ar_attempts: 3
|
||||||
|
ar_ignorefail: false
|
||||||
|
ar_suffixes: 1,2,3
|
||||||
|
|
14
init.sh
Executable file
14
init.sh
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
scriptPath="$(dirname "$(readlink -f "$0")")"
|
||||||
|
|
||||||
|
if [[ ! -f "${scriptPath}/profiles.toml" ]]; then
|
||||||
|
cp "${scriptPath}/templates/profiles.toml" "${scriptPath}/profiles.toml"
|
||||||
|
fi
|
||||||
|
if [[ ! -f "${scriptPath}/excludes" ]]; then
|
||||||
|
cp "${scriptPath}/templates/excludes" "${scriptPath}/excludes"
|
||||||
|
fi
|
||||||
|
if [[ ! -f "${scriptPath}/key" ]]; then
|
||||||
|
resticprofile generate --random-key > "${scriptPath}/key"
|
||||||
|
fi
|
||||||
|
chmod go-rwx "${scriptPath}/key" "${scriptPath}/profiles.toml" "${scriptPath}/excludes"
|
18
install.sh
Executable file
18
install.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
resticVersion="0.16.4"
|
||||||
|
resticprofileVersion="0.27.0"
|
||||||
|
|
||||||
|
mkdir /tmp/restic-install || exit 1
|
||||||
|
pushd /tmp/restic-install &>/dev/null || exit 1
|
||||||
|
wget "https://github.com/restic/restic/releases/download/v${resticVersion}/restic_${resticVersion}_linux_amd64.bz2"
|
||||||
|
bunzip2 "restic_${resticVersion}_linux_amd64.bz2"
|
||||||
|
wget "https://github.com/creativeprojects/resticprofile/releases/download/v${resticprofileVersion}/resticprofile_${resticprofileVersion}_linux_amd64.tar.gz"
|
||||||
|
tar xvfz "resticprofile_${resticprofileVersion}_linux_amd64.tar.gz"
|
||||||
|
rm LICENSE README.md "resticprofile_${resticprofileVersion}.tar.gz"
|
||||||
|
chown root:root restic*
|
||||||
|
chmod 755 restic*
|
||||||
|
mv "restic_${resticVersion}_linux_amd64" /usr/local/bin/restic
|
||||||
|
mv resticprofile /usr/local/bin/resticprofile
|
||||||
|
popd &>/dev/null
|
||||||
|
rm -rf /tmp/restic-install
|
66
scripts/consul
Executable file
66
scripts/consul
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir=/etc/restore
|
||||||
|
consulDir="/var/backups/consul"
|
||||||
|
scriptDir="$(dirname "$0")"
|
||||||
|
|
||||||
|
readConfig() {
|
||||||
|
if [[ -r "${scriptDir}/../config/consul_backup.cfg" ]]; then
|
||||||
|
source "${scriptDir}/../config/consul_backup.cfg"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
if [[ -d "$consulDir" ]]; then
|
||||||
|
echo "Cleaning out old Consul backups..."
|
||||||
|
rm -f "$consulDir"/* || return 1
|
||||||
|
else
|
||||||
|
mkdir -p "$consulDir" | return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$CONSUL_PATH" ]]; then
|
||||||
|
if [[ -x "${CONSUL_PATH}/consul" ]]; then
|
||||||
|
echo "Found Consul in $CONSUL_PATH"
|
||||||
|
else
|
||||||
|
echo "FATAL: Cannot execute Consul in $CONSUL_PATH"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! which consul &>/dev/null; then
|
||||||
|
echo "Cannot find Consul in PATH"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
if [[ -x "$(which consul)" ]]; then
|
||||||
|
CONSUL_PATH="$(dirname "$(which consul)")"
|
||||||
|
echo "Found Consul in $CONSUL_PATH"
|
||||||
|
else
|
||||||
|
echo "FATAL: Cannot execute Consul"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
readConfig
|
||||||
|
check || exit $?
|
||||||
|
${CONSUL_PATH}/consul snapshot save "$consulDir/consul.snap"
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
80
scripts/flatpak
Executable file
80
scripts/flatpak
Executable file
|
@ -0,0 +1,80 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
which flatpak || exit 0
|
||||||
|
|
||||||
|
flatpak list --columns=application --app > flatpaks.lst
|
||||||
|
|
||||||
|
cat > restore-flatpak.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ ! -f "flatpaks.lst" ]]; then
|
||||||
|
echo "This needs to be run inside the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Removal uninstalled packages:
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL FLATPAK PACKAGES"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
echo "The following flatpak packages are listed to be installed:"
|
||||||
|
cat flatpaks.lst
|
||||||
|
echo
|
||||||
|
read -p "Do you want to proceed? [Y/n] " -n 1 -sr promptFlatpak
|
||||||
|
if [[ "\$promptFlatpak" =~ ^[Yy]$ ]]; then
|
||||||
|
# Do the thing
|
||||||
|
echo "Yes"
|
||||||
|
|
||||||
|
read -p "Do you want to omit any packages or cancel? [N, y, c] " -n 1 -sr promptFlatpakVerify
|
||||||
|
if [[ "\$promptFlatpakVerify" =~ ^[Yy]$ ]]; then
|
||||||
|
echo
|
||||||
|
read -p "What do you want to omit, seperated by spaces? " -r promptFlatpakOmit
|
||||||
|
omitfp="\$(echo "\$promptFlatpakOmit" | tr ' ' '|')"
|
||||||
|
echo
|
||||||
|
elif [[ "\$promptFlatpakVerify" =~ ^[Cc]$ ]]; then
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
omitfp="CANCEL"
|
||||||
|
else
|
||||||
|
omitfp=""
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "\$omitfp" != "CANCEL" ]]; then
|
||||||
|
egrep -v "(\$omitfp)" flatpaks.lst | xargs flatpak install -y
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
#which flatpak || exit 0
|
||||||
|
#xargs flatpak install -y < flatpaks.lst
|
||||||
|
#EOF
|
||||||
|
chmod ug+rx restore-flatpak.sh
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
84
scripts/functions.sh
Normal file
84
scripts/functions.sh
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
###########################################################
|
||||||
|
### Utility & Common Functions
|
||||||
|
###########################################################
|
||||||
|
|
||||||
|
function is_bin_in_path {
|
||||||
|
builtin type -P "$1" &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
###########################################################
|
||||||
|
### BACKUP and RESTORE FUNCTIONS
|
||||||
|
###########################################################
|
||||||
|
|
||||||
|
#dumpPartitions() {
|
||||||
|
backup_partitions() {
|
||||||
|
local rootPart rootDisk
|
||||||
|
|
||||||
|
rootPart="$(findmnt -no SOURCE / | sed -E 's/\[.*\]$//')"
|
||||||
|
rootDisk="/dev/$(lsblk -no pkname "$rootPart" | head -n1)"
|
||||||
|
|
||||||
|
sfdisk --dump "$rootDisk" > "${restoreDir}/sfdisk.dump"
|
||||||
|
blkid -o export "$rootPart" > "${restoreDir}/blkid.dump"
|
||||||
|
btrfs subvolume list -p / > "${restoreDir}/btrfs.dump"
|
||||||
|
mount | grep "$rootPart" > "${restoreDir}/mounts.dump"
|
||||||
|
}
|
||||||
|
|
||||||
|
#restorePartitions() {
|
||||||
|
restore_partitions() {
|
||||||
|
local rootPart rootDisk
|
||||||
|
|
||||||
|
rootPart="$1"
|
||||||
|
rootDisk="$2"
|
||||||
|
|
||||||
|
if [[ -z "$rootDisk" || -z "$rootPart" ]]; then
|
||||||
|
echo "ERROR, restorePartitions not supplied with rootDisk and/or rootPartition"
|
||||||
|
exit 200
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore Partition Table (without modification)
|
||||||
|
sfdisk "$rootDisk" < "${restoreDir}/sfdisk.dump"
|
||||||
|
|
||||||
|
# Restore UUIDs
|
||||||
|
while read -r line; do
|
||||||
|
if [[ $line == UUID=* ]]; then
|
||||||
|
eval "$line"
|
||||||
|
tune2fs "$rootPart" -U "$UUID"
|
||||||
|
fi
|
||||||
|
done < "${restoreDir}/blkid.dump"
|
||||||
|
|
||||||
|
echo "Partition table and UUID information have been restored."
|
||||||
|
}
|
||||||
|
|
||||||
|
#restoreBtrFSSubvolumes() {
|
||||||
|
restore_btrfs_subvolumes() {
|
||||||
|
local rootBase subvolID subvolPath
|
||||||
|
|
||||||
|
rootBase="$1"
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
# Extract the subvolume ID and Path
|
||||||
|
subvolID="$(echo "$line" | awk '{print $2}')"
|
||||||
|
subvolPath="$(echo "$line" | awk '{print $NF}')"
|
||||||
|
|
||||||
|
# Restore the subvolume
|
||||||
|
btrfs subvolume create "${rootBase}/${subvolPath}"
|
||||||
|
done < "${restoreDir}/btrfs.dump"
|
||||||
|
}
|
||||||
|
|
||||||
|
#restoreBtrFSMounts() {
|
||||||
|
restore_btfs_mounts() {
|
||||||
|
local rootBase mountSource mountDest
|
||||||
|
|
||||||
|
rootBase="$1"
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
# Extract mount source and destination
|
||||||
|
mountSource="$(echo "$line" | awk '{print $1}')"
|
||||||
|
mountDest="$(echo "$line" | awk '{print $3}')"
|
||||||
|
|
||||||
|
# Mount the subvolume
|
||||||
|
mount "$mountSource" "${rootBase}/${mountDest}"
|
||||||
|
done < "$restoreDir/mounts.dump"
|
||||||
|
}
|
93
scripts/gitea
Executable file
93
scripts/gitea
Executable file
|
@ -0,0 +1,93 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir=/etc/restore
|
||||||
|
giteaDir="/var/backups/gitea"
|
||||||
|
scriptDir="$(dirname "$0")"
|
||||||
|
|
||||||
|
readConfig() {
|
||||||
|
if [[ -r "${scriptDir}/../config/gitea_backup.cfg" ]]; then
|
||||||
|
source "${scriptDir}/../config/gitea_backup.cfg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
GITEA_CONFIG=${GITEA_CONFIG:-/etc/gitea/app.ini}
|
||||||
|
if [[ ! -r "$GITEA_CONFIG" ]]; then
|
||||||
|
echo "ERROR: Cannot read gitea app.ini in $GITEA_CONFIG"
|
||||||
|
return 4
|
||||||
|
fi
|
||||||
|
|
||||||
|
GITEA_USER=${GITEA_USER:-git}
|
||||||
|
GITEA_GROUP=${GITEA_GROUP:-git}
|
||||||
|
GITEA_HOME=${GITEA_HOME:-$(getent passwd ${GITEA_USER} | cut -f6 -d:)}
|
||||||
|
if [[ ! -d "$GITEA_HOME" ]]; then
|
||||||
|
echo "ERROR: Cannot find Gitea home directory"
|
||||||
|
return 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$GITEA_BIN" ]]; then
|
||||||
|
if [[ -x "${GITEA_BIN}" ]]; then
|
||||||
|
echo "Found Gitea in $GITEA_BIN"
|
||||||
|
else
|
||||||
|
echo "FATAL: Cannot execute Gitea"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! which gitea &>/dev/null; then
|
||||||
|
echo "Cannot find Gitea in PATH"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
if [[ -x "$(which gitea)" ]]; then
|
||||||
|
GITEA_BIN="$(which gitea)"
|
||||||
|
echo "Found Gitea in $GITEA_BIN"
|
||||||
|
else
|
||||||
|
echo "FATAL: Cannot execute Gitea"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d "$giteaDir" ]]; then
|
||||||
|
echo "Cleaning out old Gitea backups..."
|
||||||
|
rm -f "$giteaDir"/* || return 1
|
||||||
|
else
|
||||||
|
mkdir -p "$giteaDir" | return 1
|
||||||
|
chgrp "$GITEA_GROUP" "$giteaDir"
|
||||||
|
chmod g+wx "$giteaDir"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
runBackups() {
|
||||||
|
local backupDate
|
||||||
|
|
||||||
|
backupDate=$(date +"%Y-%m-%d")
|
||||||
|
giteaHome=$(getent passwd git | cut -f6 -d:)
|
||||||
|
pushd "${giteaDir}" &>/dev/null
|
||||||
|
sudo -u "$GITEA_USER" "${GITEA_BIN}" dump --config "${GITEA_CONFIG}" --type tar.xz --file - > "${giteaDir}/gitea-dump-${backupDate}.tar.xz"
|
||||||
|
popd &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
check || exit $?
|
||||||
|
runBackups || exit $?
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
58
scripts/mysql_backup
Executable file
58
scripts/mysql_backup
Executable file
|
@ -0,0 +1,58 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir=/etc/restore
|
||||||
|
mysqlDir="$restoreDir/mysql"
|
||||||
|
scriptDir="$(dirname "$0")"
|
||||||
|
|
||||||
|
function readConfig() {
|
||||||
|
if [[ -r "${scriptDir}/../config/mysql_backup.cfg" ]]; then
|
||||||
|
source "${scriptDir}/../config/mysql_backup.cfg"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function runBackups() {
|
||||||
|
local dbname
|
||||||
|
|
||||||
|
readConfig
|
||||||
|
|
||||||
|
if [[ ! -d "/var/backups/mysql" ]]; then
|
||||||
|
mkdir -p "/var/backups/mysql" || return 1
|
||||||
|
fi
|
||||||
|
echo "Clearing out old MySQL backups..."
|
||||||
|
rm -f /var/backups/mysql/*
|
||||||
|
|
||||||
|
while read dbname
|
||||||
|
do
|
||||||
|
case "$dbname" in
|
||||||
|
sys) continue;;
|
||||||
|
information_schema) continue;;
|
||||||
|
performance_schema) continue;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "Backing up database: $dbname"
|
||||||
|
mysqldump --complete-insert --routines --triggers --single-transaction "$dbname" > /var/backups/mysql/"$dbname".sql
|
||||||
|
done < <(mysql -N -e 'show databases')
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
runBackups || exit $?
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
rm -rf "$mysqlDir" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $? ;;
|
||||||
|
after) hook_after || exit $? ;;
|
||||||
|
fail) hook_fail || exit $? ;;
|
||||||
|
finally) hook_final || exit $? ;;
|
||||||
|
esac
|
74
scripts/openldap
Executable file
74
scripts/openldap
Executable file
|
@ -0,0 +1,74 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir=/etc/restore
|
||||||
|
ldapDir="$restoreDir/openldap"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
if [[ -d "$ldapDir" ]]; then
|
||||||
|
rm -rf "$ldapDir" || exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$ldapDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
slapcat -n 0 -l "$ldapDir/config.ldif"
|
||||||
|
slapcat -n 1 -l "$ldapDir/data.ldif"
|
||||||
|
|
||||||
|
cat > ldaprestore.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ ! -d openldap ]]; then
|
||||||
|
echo "This needs to be run in the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f openldap/config.ldif ]]; then
|
||||||
|
echo "This needs to be run in the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
currDate="\$(date '+%Y-%m-%d')"
|
||||||
|
|
||||||
|
systemctl stop slapd
|
||||||
|
sleep 5
|
||||||
|
pkill slapd
|
||||||
|
|
||||||
|
if [[ -d /etc/ldap/slapd.d ]]; then
|
||||||
|
mv /etc/ldap/slapd.d "/etc/ldap/slapd.d.\$currDate"
|
||||||
|
mkdir -p /etc/ldap/slapd.d
|
||||||
|
slapadd -n 0 -F /etc/ldap/slapd.d -l openldap/config.ldif
|
||||||
|
chown -R ldap:ldap /etc/ldap/slapd.d
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d /var/lib/ldab ]]; then
|
||||||
|
mv /var/lib/ldap "/var/lib/ldap.\$currDate"
|
||||||
|
mkdir -p /var/lib/ldap
|
||||||
|
|
||||||
|
if [[ -d /etc/ldap/slapd.d ]]; then
|
||||||
|
slapadd -n 1 -F /etc/ldap/slapd.d -l openldap/data.ldif -w
|
||||||
|
fi
|
||||||
|
chown -R ldap:ldap /var/lib/ldap
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Backups have been restored. If you see no errors above, then you can start your server back up."
|
||||||
|
EOF
|
||||||
|
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
rm -rf "$ldapDir" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
100
scripts/os
Executable file
100
scripts/os
Executable file
|
@ -0,0 +1,100 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
kernel="$(uname -s)"
|
||||||
|
scriptPath="$(dirname "$(readlink -f "$0")")"
|
||||||
|
|
||||||
|
source "${scriptPath}/functions.sh"
|
||||||
|
|
||||||
|
if [[ "$kernel" == "Darwin" ]]; then
|
||||||
|
restoreDir="${HOME}/restore"
|
||||||
|
fi
|
||||||
|
|
||||||
|
createRestoreDir() {
|
||||||
|
if [[ -d "${restoreDir}" ]]; then
|
||||||
|
rm -rf "${restoreDir:?}/*" || exit 2
|
||||||
|
else
|
||||||
|
mkdir -p "${restoreDir}" || exit 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
checkOS() {
|
||||||
|
if [[ "$kernel" == "Darwin" ]]; then
|
||||||
|
return 0
|
||||||
|
elif [[ "$kernel" == "Linux" ]]; then
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
source /etc/os-release
|
||||||
|
DISTRO="$ID"
|
||||||
|
DISTRO_CURRENT="$DISTRO"
|
||||||
|
if [[ -n "$ID_LIKE" ]]; then
|
||||||
|
DISTRO="${ID_LIKE%% *}"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "Unknown Linux Distribution"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
runOsHook() {
|
||||||
|
local hook="$1"
|
||||||
|
|
||||||
|
if [[ "$kernel" == "Darwin" ]]; then
|
||||||
|
"${scriptPath}/os_macos" "$hook"
|
||||||
|
elif [[ "$kernel" == "Linux" ]]; then
|
||||||
|
case "$DISTRO" in
|
||||||
|
debian|ubuntu) "${scriptPath}/os_debian" "$hook";;
|
||||||
|
fedora) "${scriptPath}/os_fedora" "$hook";;
|
||||||
|
arch) "${scriptPath}/os_arch" "$hook";;
|
||||||
|
solus) "${scriptPath}/os_solus" "$hook";;
|
||||||
|
opensuse-leap) "${scriptPath}/os_suse" "$hook";;
|
||||||
|
opensuse-tumbleweed) "${scriptPath}/os_suse" "$hook";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if command -v flatpak &>/dev/null; then
|
||||||
|
"${scriptPath}/flatpak" "$hook"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
checkOS || exit 200
|
||||||
|
pushd "$scriptPath" &>/dev/null || exit 201
|
||||||
|
git checkout -- .
|
||||||
|
git pull
|
||||||
|
popd &>/dev/null || exit 201
|
||||||
|
|
||||||
|
createRestoreDir || exit $?
|
||||||
|
runOsHook before
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
checkOS || exit 200
|
||||||
|
runOsHook fail
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
checkOS || exit 200
|
||||||
|
backup_partitions || exit 200
|
||||||
|
runOsHook after
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
checkOS || exit 200
|
||||||
|
if [[ ! -f "${restoreDir}/.do-not-delete" ]]; then
|
||||||
|
rm -rf "$restoreDir"
|
||||||
|
fi
|
||||||
|
runOsHook final
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_final || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
46
scripts/os_arch
Executable file
46
scripts/os_arch
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
pacman -Qqe > "pkglist.txt"
|
||||||
|
comm -13 <(pacman -Qqdt | sort) <(pacman -Qqdtt | sort) > optdeplist.txt
|
||||||
|
pacman -Qqem > foreignpkglist.txt
|
||||||
|
|
||||||
|
cat > restore.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Install non-foreign packages from pgklist:
|
||||||
|
pacman -S --needed \$(comm -12 <(pacman -Slq | sort) <(sort pkglist.txt))
|
||||||
|
|
||||||
|
# Remove packages not listed.
|
||||||
|
#pacman -Rsu \$(comm -23 <(pacman -Qq | sort) <(sort pkglist.txt))
|
||||||
|
|
||||||
|
# Install AUR packages
|
||||||
|
paru -Sa --fm thunar - <foreign-pkglist.txt
|
||||||
|
|
||||||
|
EOF
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
150
scripts/os_debian
Executable file
150
scripts/os_debian
Executable file
|
@ -0,0 +1,150 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
function is_bin_in_path {
|
||||||
|
builtin type -P "$1" &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
if ! is_bin_in_path rsync; then
|
||||||
|
echo "rsync needs to be installed for backups to work properly."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
dpkg --get-selections | sort > Package.list
|
||||||
|
apt-mark showmanual | sort > InstallOnly.list
|
||||||
|
cp -a /etc/apt/sources.list "$restoreDir/"
|
||||||
|
rsync -avhHi /etc/apt/sources.list.d "$restoreDir/"
|
||||||
|
rsync -avhHi /etc/apt/trusted.gpg.d "$restoreDir/"
|
||||||
|
[[ -d /etc/apt/keyrings ]] && rsync -avhHi /etc/apt/keyrings "$restoreDir/"
|
||||||
|
|
||||||
|
cat > restore.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ ! -f "InstallOnly.list" ]]; then
|
||||||
|
echo "This needs to be run inside the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -d "trusted.gpg.d" ]]; then
|
||||||
|
echo "This needs to be run inside the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMPDIR="\$(mktemp -d -t restore-XXXX)"
|
||||||
|
bold="$(tput bold)"
|
||||||
|
normal="$(tput sgr0)"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
[[ -n "\$TMPDIR" && -d "\$TMPDIR" ]] && rm -rf "\$TMPDIR"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
#apt-key add /etc/restore/Repo.keys
|
||||||
|
#dpkg --set-selections < /etc/restore/Package.list
|
||||||
|
#apt-get dselect-upgrade
|
||||||
|
|
||||||
|
install=""
|
||||||
|
|
||||||
|
echo "\${bold} * Installing required packages\${normal}"
|
||||||
|
dpkg-query -s 'rsync' &>/dev/null || install+=" rsync"
|
||||||
|
#dpkg-query -s 'borgbackup' &>/dev/null || install+=" borgbackup"
|
||||||
|
#dpkg-query -s 'borgmatic' &>/dev/null || install+=" borgmatic"
|
||||||
|
dpkg-query -s 'apt-transport-https' &>/dev/null || install+=" apt-transport-https"
|
||||||
|
|
||||||
|
if [[ -n "\$install" ]]; then
|
||||||
|
apt -y install \$install
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "\${bold} * Enabling 32-bit packages\${normal}"
|
||||||
|
grep ':i386' InstallOnly.list &>/dev/null && dpkg --add-architecture i386
|
||||||
|
|
||||||
|
echo "\${bold} * Checking for flatpak\${normal}"
|
||||||
|
flatpak=0
|
||||||
|
grep 'flatpak' InstallOnly.list &>/dev/null && flatpak=1
|
||||||
|
if [[ "\$flatpak" -eq 1 ]]; then
|
||||||
|
echo " * Adding flatpak repo: Flathub"
|
||||||
|
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -r "sources.list" ]]; then
|
||||||
|
echo "\${bold}"
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL REPOS"
|
||||||
|
echo "=============================="
|
||||||
|
echo "\${normal}"
|
||||||
|
|
||||||
|
read -p "\${bold}Do you want to continue to install backup repositories? [Y/n]\${normal} " -n 1 -sr promptRepos
|
||||||
|
if [[ "\$promptRepos" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
cp -a sources.list /etc/apt/sources.list
|
||||||
|
rsync --ignore-existing -raz sources.list.d/ /etc/apt/sources.list.d/
|
||||||
|
rsync --ignore-existing -raz trusted.gpg.d/ /etc/apt/trusted.gpg.d/
|
||||||
|
[[ -d keyrings ]] && rsync --ignore-existing -raz keyrings/ /etc/apt/keyrings/
|
||||||
|
apt update
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "\${bold}"
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL PACKAGES"
|
||||||
|
echo "=============================="
|
||||||
|
echo "\${normal}"
|
||||||
|
|
||||||
|
read -p "\${bold}About to install the system packages per the backup. Do you want to continue? [Y/n]\${normal} " -n 1 -sr promptPkgs
|
||||||
|
if [[ "\$promptPkgs" =~ ^[Yy] ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
comm --nocheck-order -23 InstallOnly.list <(apt-mark showmanual|sort) | grep -Ev 'linux-image|linux-headers' > "\${TMPDIR}/diff.list"
|
||||||
|
apt-get --simulate install \$(cat "\${TMPDIR}/diff.list") |& awk '/^E: Unable to locate package / {print \$NF}' | sort > "\${TMPDIR}/diff.fail"
|
||||||
|
comm --nocheck-order -23 "\${TMPDIR}/diff.list" "\${TMPDIR}/diff.fail" | xargs apt-get install
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Packages that were omitted because they could not be found:"
|
||||||
|
cat "\${TMPDIR}/diff.fail" | tr '\n' ' ' | fold -s
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
|
||||||
|
read -p "\${bold}Did everything above look okay and do you want to proceed? [Y/n]\${normal} " -n 1 -sr promptPkgsDo
|
||||||
|
if [[ "\$promptPkgsDo" =~ ^[Yy] ]]; then
|
||||||
|
comm --nocheck-order -23 "\${TMPDIR}/diff.list" "\${TMPDIR}/diff.fail" | xargs apt-get install
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "\${bold}Packages that failed to schedule for install:\${normal}"
|
||||||
|
cat "\${TMPDIR}/diff.fail" | tr '\n' ' ' | fold -s
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
chmod ug+rx restore.sh
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_final || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
45
scripts/os_fedora
Executable file
45
scripts/os_fedora
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
rpm -qa | sort > Package.versions.list
|
||||||
|
rpm -qa --queryformat '%{NAME}.%{ARCH}\n' | sort > Package.list
|
||||||
|
#FIXME Need to put this to use for explicitely installed packages.
|
||||||
|
dnf repoquery --userinstalled > Package.userinstalled.list
|
||||||
|
|
||||||
|
cat > restore.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ ! -f "Package.list" ]]; then
|
||||||
|
echo "This needs to be run inside the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnf install \$(cat Package.list)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
43
scripts/os_macos
Executable file
43
scripts/os_macos
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="$HOME/.borgmatic/restore"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
brew bundle dump || exit 3
|
||||||
|
|
||||||
|
cat > restore.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if which brew; then
|
||||||
|
echo "Installing Homebrew Bundle"
|
||||||
|
brew bundle
|
||||||
|
else
|
||||||
|
echo "Install Homebrew first using the following:"
|
||||||
|
echo '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'
|
||||||
|
echo "Re-run restore.sh after installing Homebrew to install Homebrew Bundle"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
31
scripts/os_solus
Executable file
31
scripts/os_solus
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
eopkg li > Packages.list
|
||||||
|
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
172
scripts/os_suse
Executable file
172
scripts/os_suse
Executable file
|
@ -0,0 +1,172 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
mkdir -p "$restoreDir" || exit 1
|
||||||
|
pushd "$restoreDir" || exit 2
|
||||||
|
|
||||||
|
rpm -qa | sort > Package.versions.list
|
||||||
|
rpm -qa --queryformat '%{NAME}.%{ARCH}\n' | sort > Package.all.list
|
||||||
|
zypper se -i -t pattern | awk '/^i\+/ { print $3 }' | sort > Pattern.list
|
||||||
|
zypper se -i -t package | awk '/^i\+/ { print $3 }' | sort > Package.list
|
||||||
|
zypper lr -e Backup.repos
|
||||||
|
zypper ll | awk '/.*\| package.*/ { print $3 }' > Package.lock
|
||||||
|
|
||||||
|
cat > restore.sh <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ ! -f "Package.list" ]]; then
|
||||||
|
echo "This needs to be run inside the restore directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -r "Backup.repos" ]]; then
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL REPOS"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
read -p "Do you want to continue to install backup repositories? [Y/n] " -n 1 -sr promptRepos
|
||||||
|
if [[ "\$promptRepos" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
zypper ar Backup.repos
|
||||||
|
zypper --gpg-auto-import-keys refresh
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -r "opi.conf" ]]; then
|
||||||
|
source "opi.conf"
|
||||||
|
|
||||||
|
if [[ -n "\$opimodules" ]]; then
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL OPI"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
echo "About to install the following OPI modules:"
|
||||||
|
echo "\$opimodules"
|
||||||
|
echo
|
||||||
|
read -p "Do you want to continue to install these? [Y/n] " -n 1 -sr promptOPI
|
||||||
|
if [[ "\$promptOPI" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
zypper install -y opi
|
||||||
|
opi -nm \$opimodules
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#zypper dist-upgrade --from packman --allow-vendor-change
|
||||||
|
#zypper install --from packman ffmpeg gstreamer-plugins-{good,bad,ugly,libav} libavcodec vlc-codecs
|
||||||
|
|
||||||
|
if [[ -r "Pattern.list" && "\$(wc -l --total=only Pattern.list)" -gt 0 ]]; then
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL PATTERNS"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
echo "The following patterns are listed to be installed:"
|
||||||
|
cat Pattern.list
|
||||||
|
echo
|
||||||
|
read -p "Do you want to continue to install these? [Y/n] " -n 1 -sr promptPattern
|
||||||
|
if [[ "\$promptPattern" =~ ^[Yy] ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
cat Pattern.list | xargs zypper install -t pattern
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "INSTALL PACKAGES"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
read -p "About to install the system packages per the backup. Do you want to continue? [Y/n] " -n 1 -sr promptPkgs
|
||||||
|
if [[ "\$promptPkgs" =~ ^[Yy] ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
cat Package.list | xargs zypper install
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Removal uninstalled packages:
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "REMOVE PACKAGES"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
read -p "!!WARNING!! The next step is to remove packages that may not be desired. Do you want to continue? [Y/n] " -n 1 -sr promptRm
|
||||||
|
if [[ "\$promptRm" =~ ^[Yy]$ ]]; then
|
||||||
|
# Do the thing
|
||||||
|
echo "Yes"
|
||||||
|
rpm -qa --queryformat '%{NAME}.%{ARCH}\n' | sort > /tmp/Package.new.list
|
||||||
|
echo "Here's a list of packages that would be removed:"
|
||||||
|
comm -13 Package.all.list /tmp/Package.new.list
|
||||||
|
|
||||||
|
read -p "Do you want to omit any removals or cancel? [N, y, c] " -n 1 -sr promptRmVerify
|
||||||
|
if [[ "\$promptRmVerify" =~ ^[Yy]$ ]]; then
|
||||||
|
echo
|
||||||
|
read -p "What do you want to omit, seperated by spaces? " -r promptOmit
|
||||||
|
omitrm="\$(echo "\$promptOmit" | tr ' ' '|')"
|
||||||
|
echo
|
||||||
|
elif [[ "\$promptRmVerify" =~ ^[Cc]$ ]]; then
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
omitrm="CANCEL"
|
||||||
|
else
|
||||||
|
omitrm=""
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "\$omitrm" != "CANCEL" ]]; then
|
||||||
|
comm -13 Package.all.list /tmp/Package.new.list | egrep -v "(\$omitrm)" | xargs zypper remove
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Package Locks
|
||||||
|
if [[ -r "Package.lock" && "\$(wc -l --total=only Package.list)" -gt 0 ]]; then
|
||||||
|
echo
|
||||||
|
echo "=============================="
|
||||||
|
echo "PACKAGE LOCKS"
|
||||||
|
echo "=============================="
|
||||||
|
echo
|
||||||
|
echo "The following packages are found to be locked:"
|
||||||
|
cat Package.lock
|
||||||
|
echo
|
||||||
|
read -p "Do you want to lock these packages per the backup? [Y/n] " -n 1 -sr promptLock
|
||||||
|
if [[ "\$promptLock" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Yes"
|
||||||
|
cat Package.lock | xargs zypper addlock
|
||||||
|
else
|
||||||
|
echo -e "Cancelled\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
popd || exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
0
scripts/partbackup
Normal file
0
scripts/partbackup
Normal file
0
scripts/partbackup2
Normal file
0
scripts/partbackup2
Normal file
339
scripts/partbackup3
Normal file
339
scripts/partbackup3
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Global variables for restore directory
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
backupDir="${restoreDir}/data"
|
||||||
|
|
||||||
|
# Function to create backup directory
|
||||||
|
create_backup_dir() {
|
||||||
|
echo "Creating backup directory at ${backupDir}..."
|
||||||
|
mkdir -p "$backupDir"
|
||||||
|
echo "Backup directory created."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup a partition table
|
||||||
|
backup_partition() {
|
||||||
|
local device="$1"
|
||||||
|
|
||||||
|
echo "Backing up partition table for $device..."
|
||||||
|
sfdisk --dump "$device" > "${backupDir}/partition_table_$(basename "$device").backup"
|
||||||
|
echo "Partition table backed up to ${backupDir}/partition_table_$(basename "$device").backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup filesystem UUID
|
||||||
|
backup_uuid() {
|
||||||
|
local partition="$1"
|
||||||
|
|
||||||
|
echo "Backing up UUID for $partition..."
|
||||||
|
blkid "$partition" | awk '{print $2}' > "${backupDir}/uuid_$(basename "$partition").backup"
|
||||||
|
echo "UUID backed up to ${backupDir}/uuid_$(basename "$partition").backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup Btrfs subvolumes, excluding snapshots and nested subvolumes
|
||||||
|
backup_btrfs_subvolumes() {
|
||||||
|
local mount_point="$1"
|
||||||
|
local subvol_path
|
||||||
|
local subvol_name
|
||||||
|
|
||||||
|
echo "Backing up Btrfs subvolumes from $mount_point to ${backupDir}..."
|
||||||
|
mkdir -p "${backupDir}/btrfs_subvolumes"
|
||||||
|
btrfs subvolume list -p "$mount_point" | while read -r line; do
|
||||||
|
subvol_path=$(echo "$line" | awk '{print $NF}')
|
||||||
|
subvol_name=$(basename "$subvol_path")
|
||||||
|
|
||||||
|
# Skip snapshots and subvolumes under .snapshots
|
||||||
|
if [[ "$subvol_path" == *.snapshots/* || "$subvol_path" == ".snapshots" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Backing up subvolume $subvol_name"
|
||||||
|
btrfs subvolume snapshot "$mount_point/$subvol_path" "${backupDir}/btrfs_subvolumes/$subvol_name"
|
||||||
|
done
|
||||||
|
echo "Btrfs subvolumes backed up to ${backupDir}/btrfs_subvolumes"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup current mount points and options
|
||||||
|
backup_mount_points() {
|
||||||
|
echo "Backing up current mount points and options..."
|
||||||
|
mount | grep "^/dev" > "${backupDir}/mount_points.backup"
|
||||||
|
echo "Mount points backed up to ${backupDir}/mount_points.backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore Btrfs subvolumes to /mnt/restore, excluding snapshots and nested subvolumes
|
||||||
|
restore_btrfs_subvolumes() {
|
||||||
|
local mount_point="$1"
|
||||||
|
local subvol_snapshot
|
||||||
|
local subvol_name
|
||||||
|
|
||||||
|
echo "Restoring Btrfs subvolumes from ${backupDir}/btrfs_subvolumes to /mnt/restore/$mount_point..."
|
||||||
|
mkdir -p "/mnt/restore$mount_point"
|
||||||
|
for subvol_snapshot in "${backupDir}/btrfs_subvolumes"/*; do
|
||||||
|
if [[ -d "$subvol_snapshot" ]]; then
|
||||||
|
subvol_name=$(basename "$subvol_snapshot")
|
||||||
|
|
||||||
|
# Restore subvolume to the mount point
|
||||||
|
echo "Restoring subvolume $subvol_name"
|
||||||
|
btrfs subvolume snapshot "$subvol_snapshot" "/mnt/restore$mount_point/$subvol_name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "Btrfs subvolumes restored to /mnt/restore$mount_point"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore mount points to /mnt/restore, supporting Btrfs subvolumes
|
||||||
|
restore_mount_points() {
|
||||||
|
local original_device
|
||||||
|
local device
|
||||||
|
local mount_point
|
||||||
|
local mount_opts
|
||||||
|
local subvol
|
||||||
|
local fs_type
|
||||||
|
|
||||||
|
if [[ -f "${backupDir}/mount_points.backup" ]]; then
|
||||||
|
echo "Restoring mount points from ${backupDir}/mount_points.backup to /mnt/restore..."
|
||||||
|
mkdir -p /mnt/restore
|
||||||
|
while IFS= read -r line; do
|
||||||
|
original_device=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
mount_opts=$(echo "$line" | awk -F' ' '{for(i=4;i<=NF;i++){print $i}}' | tr -d '()')
|
||||||
|
|
||||||
|
# Extract and remove subvol and subvolid from mount options
|
||||||
|
subvol=$(echo "$mount_opts" | grep -oP 'subvol=\K[^,]*')
|
||||||
|
mount_opts=$(echo "$mount_opts" | sed -e 's/subvol=[^,]*,//g' -e 's/subvolid=[^,]*,//g')
|
||||||
|
|
||||||
|
# Rename device if specified
|
||||||
|
device="$original_device"
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "/mnt/restore$mount_point"
|
||||||
|
fs_type=$(blkid -o value -s TYPE "$device")
|
||||||
|
|
||||||
|
if [[ "$fs_type" == "btrfs" ]]; then
|
||||||
|
if [[ -n "$subvol" ]]; then
|
||||||
|
echo "Mounting Btrfs subvolume $subvol on /mnt/restore$mount_point"
|
||||||
|
mount -t btrfs -o subvol="$subvol,$mount_opts" "$device" "/mnt/restore$mount_point"
|
||||||
|
else
|
||||||
|
echo "Mounting Btrfs volume $device on /mnt/restore$mount_point"
|
||||||
|
mount -t btrfs -o "$mount_opts" "$device" "/mnt/restore$mount_point"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Mounting $device on /mnt/restore$mount_point with options $mount_opts"
|
||||||
|
mount -o "$mount_opts" "$device" "/mnt/restore$mount_point"
|
||||||
|
fi
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
echo "Mount points restored to /mnt/restore."
|
||||||
|
else
|
||||||
|
echo "Backup file ${backupDir}/mount_points.backup not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore a partition table with optional device renaming
|
||||||
|
restore_partition() {
|
||||||
|
local device="$1"
|
||||||
|
local original_device="$device"
|
||||||
|
local backup_file
|
||||||
|
local temp_file
|
||||||
|
|
||||||
|
# Check if the device should be renamed
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
echo "Renaming device $device to ${rename_map[$device]}"
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_file="${backupDir}/partition_table_$(basename "$original_device").backup"
|
||||||
|
if [[ ! -f "$backup_file" ]]; then
|
||||||
|
echo "Backup file $backup_file not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a temporary file for the modified backup
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
trap 'rm -f "$temp_file"' EXIT
|
||||||
|
|
||||||
|
# Modify the backup file to use the new device name
|
||||||
|
sed "s|$original_device|$device|g" "$backup_file" > "$temp_file"
|
||||||
|
|
||||||
|
echo "Restoring partition table for $device..."
|
||||||
|
sfdisk "$device" < "$temp_file"
|
||||||
|
echo "Partition table restored from $temp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore filesystem UUID with optional device renaming
|
||||||
|
restore_uuid() {
|
||||||
|
local partition="$1"
|
||||||
|
local original_partition="$partition"
|
||||||
|
local uuid
|
||||||
|
|
||||||
|
# Check if the partition should be renamed
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${backupDir}/uuid_$(basename "$original_partition").backup" ]]; then
|
||||||
|
uuid=$(cut -d'=' -f2 < "${backupDir}/uuid_$(basename "$original_partition").backup" | tr -d '"')
|
||||||
|
echo "Restoring UUID $uuid to $partition..."
|
||||||
|
|
||||||
|
case "$(blkid -o value -s TYPE "$partition")" in
|
||||||
|
ext4)
|
||||||
|
tune2fs -U "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
xfs)
|
||||||
|
xfs_admin -U "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
btrfs)
|
||||||
|
btrfstune -u "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported filesystem type."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "UUID restored."
|
||||||
|
else
|
||||||
|
echo "Backup file ${backupDir}/uuid_$(basename "$original_partition").backup not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to handle all backup operations
|
||||||
|
backup_all_partitions() {
|
||||||
|
echo "Backing up all partitions..."
|
||||||
|
backup_mount_points
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local device
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
backup_partition "$device"
|
||||||
|
backup_uuid "$device"
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
|
||||||
|
backup_btrfs_subvolumes "/mnt"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore all partitions and filesystems from backup files
|
||||||
|
restore_all() {
|
||||||
|
echo "Restoring all partitions and filesystems from backup..."
|
||||||
|
|
||||||
|
# Restore partition tables
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local device
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
# Rename device if specified
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
restore_partition "$device"
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
|
||||||
|
if [[ "$restore_uuid" == true ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local partition
|
||||||
|
partition=$(echo "$line" | awk '{print $1}')
|
||||||
|
# Rename partition if specified
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
fi
|
||||||
|
restore_uuid "$partition"
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
restore_btrfs_subvolumes "/mnt/restore"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function to handle command-line arguments and invoke appropriate functions
|
||||||
|
main() {
|
||||||
|
local exclude_opts=()
|
||||||
|
local exclude_file
|
||||||
|
local rename_map=()
|
||||||
|
local restore_uuid=true
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
backup)
|
||||||
|
shift
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--exclude)
|
||||||
|
shift
|
||||||
|
exclude_opts+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude-file)
|
||||||
|
shift
|
||||||
|
exclude_file="$1"
|
||||||
|
if [[ -f "$exclude_file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
exclude_opts+=("$line")
|
||||||
|
done < "$exclude_file"
|
||||||
|
else
|
||||||
|
echo "Exclude file $exclude_file does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 backup [--exclude <pattern>]... [--exclude-file <file>]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
create_backup_dir
|
||||||
|
backup_all_partitions
|
||||||
|
;;
|
||||||
|
|
||||||
|
restore)
|
||||||
|
shift
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--no-uuid)
|
||||||
|
restore_uuid=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude)
|
||||||
|
shift
|
||||||
|
exclude_opts+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude-file)
|
||||||
|
shift
|
||||||
|
exclude_file="$1"
|
||||||
|
if [[ -f "$exclude_file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
exclude_opts+=("$line")
|
||||||
|
done < "$exclude_file"
|
||||||
|
else
|
||||||
|
echo "Exclude file $exclude_file does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--rename)
|
||||||
|
shift
|
||||||
|
local old_device="$1"
|
||||||
|
shift
|
||||||
|
local new_device="$1"
|
||||||
|
rename_map["$old_device"]="$new_device"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 restore [--no-uuid] [--exclude <pattern>]... [--exclude-file <file>] [--rename <old_device> <new_device>]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
restore_all
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {backup|restore} [options]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the main function with all arguments
|
||||||
|
main "$@"
|
388
scripts/partbackup4
Normal file
388
scripts/partbackup4
Normal file
|
@ -0,0 +1,388 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Global variables for restore directory
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
backupDir="${restoreDir}/data"
|
||||||
|
|
||||||
|
# Internal Variables used globally
|
||||||
|
declare -a exclude_opts
|
||||||
|
declare -A rename_map
|
||||||
|
declare restore_uuid=true
|
||||||
|
|
||||||
|
# Function to create backup directory
|
||||||
|
create_backup_dir() {
|
||||||
|
echo "Creating backup directory at ${backupDir}..."
|
||||||
|
mkdir -p "$backupDir"
|
||||||
|
echo "Backup directory created."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup a partition table
|
||||||
|
backup_partition() {
|
||||||
|
local device="$1"
|
||||||
|
|
||||||
|
echo "Backing up partition table for $device..."
|
||||||
|
sfdisk --dump "$device" > "${backupDir}/partition_table_$(basename "$device").backup"
|
||||||
|
echo "Partition table backed up to ${backupDir}/partition_table_$(basename "$device").backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup filesystem UUID
|
||||||
|
backup_uuid() {
|
||||||
|
local partition="$1"
|
||||||
|
|
||||||
|
echo "Backing up UUID for $partition..."
|
||||||
|
blkid "$partition" | awk '{print $2}' > "${backupDir}/uuid_$(basename "$partition").backup"
|
||||||
|
echo "UUID backed up to ${backupDir}/uuid_$(basename "$partition").backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup Btrfs subvolumes, excluding snapshots and nested subvolumes
|
||||||
|
backup_btrfs_subvolumes() {
|
||||||
|
local mount_point="$1"
|
||||||
|
local subvol_path
|
||||||
|
local subvol_name
|
||||||
|
|
||||||
|
echo "Backing up Btrfs subvolumes from $mount_point to ${backupDir}..."
|
||||||
|
mkdir -p "${backupDir}/btrfs_subvolumes"
|
||||||
|
btrfs subvolume list -p "$mount_point" | while read -r line; do
|
||||||
|
subvol_path=$(echo "$line" | awk '{print $NF}')
|
||||||
|
subvol_name=$(basename "$subvol_path")
|
||||||
|
|
||||||
|
# Skip snapshots and subvolumes under .snapshots
|
||||||
|
if [[ "$subvol_path" == *.snapshots/* || "$subvol_path" == ".snapshots" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Backing up subvolume $subvol_name"
|
||||||
|
btrfs subvolume snapshot "$mount_point/$subvol_path" "${backupDir}/btrfs_subvolumes/$subvol_name"
|
||||||
|
done
|
||||||
|
echo "Btrfs subvolumes backed up to ${backupDir}/btrfs_subvolumes"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup current mount points and options
|
||||||
|
backup_mount_points() {
|
||||||
|
local line
|
||||||
|
local device
|
||||||
|
|
||||||
|
echo "Backing up current mount points and options..."
|
||||||
|
while IFS= read -r line; do
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
# Skip excluded devices
|
||||||
|
if is_excluded "$device"; then
|
||||||
|
echo "Skipping excluded device $device"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
backup_partition "$device"
|
||||||
|
backup_uuid "$device"
|
||||||
|
done < <(mount | grep "^/dev")
|
||||||
|
#mount | grep "^/dev" > "${backupDir}/mount_points.backup"
|
||||||
|
echo "Mount points backed up to ${backupDir}/mount_points.backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore Btrfs subvolumes to /mnt/restore, excluding snapshots and nested subvolumes
|
||||||
|
restore_btrfs_subvolumes() {
|
||||||
|
local mount_point="$1"
|
||||||
|
local subvol_snapshot
|
||||||
|
local subvol_name
|
||||||
|
|
||||||
|
echo "Restoring Btrfs subvolumes from ${backupDir}/btrfs_subvolumes to /mnt/restore/$mount_point..."
|
||||||
|
mkdir -p "/mnt/restore$mount_point"
|
||||||
|
for subvol_snapshot in "${backupDir}/btrfs_subvolumes"/*; do
|
||||||
|
if [[ -d "$subvol_snapshot" ]]; then
|
||||||
|
subvol_name=$(basename "$subvol_snapshot")
|
||||||
|
|
||||||
|
# Restore subvolume to the mount point
|
||||||
|
echo "Restoring subvolume $subvol_name"
|
||||||
|
btrfs subvolume snapshot "$subvol_snapshot" "/mnt/restore$mount_point/$subvol_name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "Btrfs subvolumes restored to /mnt/restore$mount_point"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore mount points to /mnt/restore, supporting Btrfs subvolumes
|
||||||
|
restore_mount_points() {
|
||||||
|
local original_device
|
||||||
|
local device
|
||||||
|
local mount_point
|
||||||
|
local mount_opts
|
||||||
|
local subvol
|
||||||
|
local fs_type
|
||||||
|
|
||||||
|
if [[ -f "${backupDir}/mount_points.backup" ]]; then
|
||||||
|
echo "Restoring mount points from ${backupDir}/mount_points.backup to /mnt/restore..."
|
||||||
|
mkdir -p /mnt/restore
|
||||||
|
while IFS= read -r line; do
|
||||||
|
original_device=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
mount_opts=$(echo "$line" | awk -F' ' '{for(i=4;i<=NF;i++){print $i}}' | tr -d '()')
|
||||||
|
|
||||||
|
# Extract and remove subvol and subvolid from mount options
|
||||||
|
subvol=$(echo "$mount_opts" | grep -oP 'subvol=\K[^,]*')
|
||||||
|
mount_opts=$(echo "$mount_opts" | sed -e 's/subvol=[^,]*,//g' -e 's/subvolid=[^,]*,//g')
|
||||||
|
|
||||||
|
# Rename device if specified
|
||||||
|
device="$original_device"
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "/mnt/restore$mount_point"
|
||||||
|
fs_type=$(blkid -o value -s TYPE "$device")
|
||||||
|
|
||||||
|
if [[ "$fs_type" == "btrfs" ]]; then
|
||||||
|
if [[ -n "$subvol" ]]; then
|
||||||
|
echo "Mounting Btrfs subvolume $subvol on /mnt/restore$mount_point"
|
||||||
|
mount -t btrfs -o subvol="$subvol,$mount_opts" "$device" "/mnt/restore$mount_point"
|
||||||
|
else
|
||||||
|
echo "Mounting Btrfs volume $device on /mnt/restore$mount_point"
|
||||||
|
mount -t btrfs -o "$mount_opts" "$device" "/mnt/restore$mount_point"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Mounting $device on /mnt/restore$mount_point with options $mount_opts"
|
||||||
|
mount -o "$mount_opts" "$device" "/mnt/restore$mount_point"
|
||||||
|
fi
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
echo "Mount points restored to /mnt/restore."
|
||||||
|
else
|
||||||
|
echo "Backup file ${backupDir}/mount_points.backup not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore a partition table with optional device renaming
|
||||||
|
restore_partition() {
|
||||||
|
local device="$1"
|
||||||
|
local original_device="$device"
|
||||||
|
local backup_file
|
||||||
|
local temp_file
|
||||||
|
|
||||||
|
# Check if the device should be renamed
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
echo "Renaming device $device to ${rename_map[$device]}"
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_file="${backupDir}/partition_table_$(basename "$original_device").backup"
|
||||||
|
if [[ ! -f "$backup_file" ]]; then
|
||||||
|
echo "Backup file $backup_file not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a temporary file for the modified backup
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
trap 'rm -f "$temp_file"' EXIT
|
||||||
|
|
||||||
|
# Modify the backup file to use the new device name
|
||||||
|
sed "s|$original_device|$device|g" "$backup_file" > "$temp_file"
|
||||||
|
|
||||||
|
echo "Restoring partition table for $device..."
|
||||||
|
sfdisk "$device" < "$temp_file"
|
||||||
|
echo "Partition table restored from $temp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore filesystem UUID with optional device renaming
|
||||||
|
restore_uuid() {
|
||||||
|
local partition="$1"
|
||||||
|
local original_partition="$partition"
|
||||||
|
local uuid
|
||||||
|
|
||||||
|
# Check if the partition should be renamed
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${backupDir}/uuid_$(basename "$original_partition").backup" ]]; then
|
||||||
|
uuid=$(cut -d'=' -f2 < "${backupDir}/uuid_$(basename "$original_partition").backup" | tr -d '"')
|
||||||
|
echo "Restoring UUID $uuid to $partition..."
|
||||||
|
|
||||||
|
case "$(blkid -o value -s TYPE "$partition")" in
|
||||||
|
ext4)
|
||||||
|
tune2fs -U "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
xfs)
|
||||||
|
xfs_admin -U "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
btrfs)
|
||||||
|
btrfstune -u "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported filesystem type."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "UUID restored."
|
||||||
|
else
|
||||||
|
echo "Backup file ${backupDir}/uuid_$(basename "$original_partition").backup not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to handle exclusion list with wildcard and reverse matching
|
||||||
|
is_excluded() {
|
||||||
|
local pattern="$1"
|
||||||
|
local device="$2"
|
||||||
|
|
||||||
|
for exclude in "${exclude_opts[@]}"; do
|
||||||
|
if [[ "$exclude" == !* ]]; then
|
||||||
|
pattern="${exclude#!}"
|
||||||
|
if [[ "$device" == $pattern ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pattern="$exclude"
|
||||||
|
if [[ "$device" == $pattern ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Function to handle all backup operations
|
||||||
|
backup_all_partitions() {
|
||||||
|
local device
|
||||||
|
local mount_point
|
||||||
|
local fs_type
|
||||||
|
|
||||||
|
echo "Backing up all partitions..."
|
||||||
|
backup_mount_points
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local device
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
fs_type=$(echo "$line" | awk '{print $5}')
|
||||||
|
# Skip excluded devices
|
||||||
|
if is_excluded "$device"; then
|
||||||
|
echo "Skipping excluded device $device"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
backup_partition "$device"
|
||||||
|
backup_uuid "$device"
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
|
||||||
|
backup_btrfs_subvolumes "/mnt"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore all partitions and filesystems from backup files
|
||||||
|
restore_all() {
|
||||||
|
echo "Restoring all partitions and filesystems from backup..."
|
||||||
|
|
||||||
|
# Restore partition tables
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local device
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
# Rename device if specified
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
restore_partition "$device"
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
|
||||||
|
if [[ "$restore_uuid" == true ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local partition
|
||||||
|
partition=$(echo "$line" | awk '{print $1}')
|
||||||
|
# Rename partition if specified
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
fi
|
||||||
|
restore_uuid "$partition"
|
||||||
|
done < "${backupDir}/mount_points.backup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
restore_btrfs_subvolumes "/mnt/restore"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function to handle command-line arguments and invoke appropriate functions
|
||||||
|
main() {
|
||||||
|
local exclude_file
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
backup)
|
||||||
|
shift
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--exclude)
|
||||||
|
shift
|
||||||
|
exclude_opts+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude-file)
|
||||||
|
shift
|
||||||
|
exclude_file="$1"
|
||||||
|
if [[ -f "$exclude_file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
exclude_opts+=("$line")
|
||||||
|
done < "$exclude_file"
|
||||||
|
else
|
||||||
|
echo "Exclude file $exclude_file does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 backup [--exclude <pattern>]... [--exclude-file <file>]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
create_backup_dir
|
||||||
|
backup_all_partitions
|
||||||
|
;;
|
||||||
|
|
||||||
|
restore)
|
||||||
|
shift
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--no-uuid)
|
||||||
|
restore_uuid=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude)
|
||||||
|
shift
|
||||||
|
exclude_opts+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude-file)
|
||||||
|
shift
|
||||||
|
exclude_file="$1"
|
||||||
|
if [[ -f "$exclude_file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
exclude_opts+=("$line")
|
||||||
|
done < "$exclude_file"
|
||||||
|
else
|
||||||
|
echo "Exclude file $exclude_file does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--rename)
|
||||||
|
shift
|
||||||
|
local old_device="$1"
|
||||||
|
shift
|
||||||
|
local new_device="$1"
|
||||||
|
rename_map["$old_device"]="$new_device"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 restore [--no-uuid] [--exclude <pattern>]... [--exclude-file <file>] [--rename <old_device> <new_device>]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
restore_all
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {backup|restore} [options]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the main function with all arguments
|
||||||
|
main "$@"
|
651
scripts/partbackup5
Executable file
651
scripts/partbackup5
Executable file
|
@ -0,0 +1,651 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Global variables for restore directory
|
||||||
|
restoreDir="/etc/restore"
|
||||||
|
backupDir="${restoreDir}/data"
|
||||||
|
|
||||||
|
# Internal Variables used globally
|
||||||
|
declare -a exclude_opts
|
||||||
|
declare -A rename_map
|
||||||
|
declare -A btrfs_roots
|
||||||
|
declare restore_uuid=true
|
||||||
|
#declare dry_run=false
|
||||||
|
|
||||||
|
# Function to create backup directory
|
||||||
|
create_backup_dir() {
|
||||||
|
echo "Creating backup directory at ${backupDir}..."
|
||||||
|
mkdir -p "$backupDir" || exit_fail 200 "FATAL: Failed to create '$backupDir'"
|
||||||
|
echo "Backup directory created."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to show command-line help
|
||||||
|
showHelp() {
|
||||||
|
echo "Usage: $0 {backup|restore} [options]"
|
||||||
|
echo
|
||||||
|
echo "Options:"
|
||||||
|
echo " --exclude <pattern> Exclude devices matching the pattern from backup or restore."
|
||||||
|
echo " --exclude-file <file> Exclude devices listed in the specified file from backup or restore."
|
||||||
|
echo " --rename <old> <new> Rename a device during the restore process."
|
||||||
|
echo " --no-uuid Disable restoring of UUIDs during restore."
|
||||||
|
echo " --help Show this help message and exit."
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo " backup Perform backup of all partitions, UUIDs, and Btrfs subvolumes."
|
||||||
|
echo " restore Restore all partitions, UUIDs, and Btrfs subvolumes from backup."
|
||||||
|
echo
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 backup --exclude /dev/sda1"
|
||||||
|
echo " $0 restore --rename /dev/sda /dev/sdb"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to run commands based on dry-run mode
|
||||||
|
#run_command() {
|
||||||
|
# if [[ "$dry_run" == true ]]; then
|
||||||
|
# echo "[DRY-RUN] $@"
|
||||||
|
# else
|
||||||
|
# "$@"
|
||||||
|
# fi
|
||||||
|
#}
|
||||||
|
|
||||||
|
echoerr() {
|
||||||
|
echo "$*" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_fail() {
|
||||||
|
local rc=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
echoerr "$*"
|
||||||
|
exit "$rc"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_base_device() {
|
||||||
|
local partition=$1
|
||||||
|
local devnode basenode
|
||||||
|
|
||||||
|
if [[ -b "$partition" ]]; then
|
||||||
|
# Remove partition suffix (p2, 2, etc.) but keep the rest of the device name
|
||||||
|
devnode=$(basename "$partition")
|
||||||
|
if [[ -s "/sys/class/block/$devnode" ]]; then
|
||||||
|
basenode=$(basename "$(readlink -f "/sys/class/block/$devnode/..")")
|
||||||
|
echo "/dev/$basenode"
|
||||||
|
else
|
||||||
|
echo "$partition" | sed -E 's/(p[0-9]+|[0-9]+)$//'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_in_array() {
|
||||||
|
local e match="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
for e; do
|
||||||
|
[[ "$e" == "$match" ]] && return 0
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup a partition table
|
||||||
|
backup_partition() {
|
||||||
|
local device="$1"
|
||||||
|
local rc=0
|
||||||
|
|
||||||
|
echo "Backing up partition table for $device..."
|
||||||
|
sfdisk --dump "$device" > "${backupDir}/partitions_$(basename "$device").backup" || rc=$?
|
||||||
|
echo "Partition table backed up to ${backupDir}/partitions_$(basename "$device").backup"
|
||||||
|
|
||||||
|
return "$rc"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup filesystem UUID
|
||||||
|
backup_uuid() {
|
||||||
|
local partition="$1"
|
||||||
|
|
||||||
|
echo "Backing up UUID for $partition..."
|
||||||
|
blkid -o value -s UUID "$partition" > "${backupDir}/uuid_$(basename "$partition").backup"
|
||||||
|
echo "UUID backed up to ${backupDir}/uuid_$(basename "$partition").backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup Btrfs subvolumes, excluding snapshots and nested subvolumes
|
||||||
|
backup_btrfs_subvolumes() {
|
||||||
|
local partition="$1"
|
||||||
|
local mount_point="$2"
|
||||||
|
local subvol_path
|
||||||
|
#local parent_id
|
||||||
|
local backup_file
|
||||||
|
local results
|
||||||
|
|
||||||
|
echo "Backing up list of Btrfs subvolumes from $mount_point..."
|
||||||
|
backup_file="${backupDir}/btrfs_$(basename "$partition").backup"
|
||||||
|
mkdir -p "${backupDir}"
|
||||||
|
|
||||||
|
# Initialize results variable
|
||||||
|
results=""
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
subvol_path=$(echo "$line" | awk '{print $NF}')
|
||||||
|
#parent_id=$(echo "$line" | awk '{print $6}')
|
||||||
|
|
||||||
|
# Skip subvolumes that do not have parent ID 5
|
||||||
|
#if [[ "$parent_id" -ne 5 ]]; then
|
||||||
|
# continue
|
||||||
|
#fi
|
||||||
|
|
||||||
|
# Skip .snapshots and subvolumes under .snapshots
|
||||||
|
if [[ "$subvol_path" == ".snapshots" || "$subvol_path" == .snapshots/* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip @snapshots and subvolumes under @snapshots
|
||||||
|
if [[ "$subvol_path" == "@snapshots" || "$subvol_path" == @snapshots/* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip .veeam_snapshots
|
||||||
|
if [[ "$subvol_path" == ".veeam_snapshots" || "$subvol_path" == .veeam_snapshots/* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append valid subvolume path to results
|
||||||
|
results+="$subvol_path"$'\n'
|
||||||
|
done < <(btrfs subvolume list -p "$mount_point" | grep "parent 5")
|
||||||
|
|
||||||
|
# Write results to the backup file
|
||||||
|
echo "$results" > "$backup_file"
|
||||||
|
|
||||||
|
echo "List of Btrfs subvolumes backed up to $backup_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup current mount points and options
|
||||||
|
backup_mounts() {
|
||||||
|
local line
|
||||||
|
local device
|
||||||
|
local mount_point
|
||||||
|
local fs_type
|
||||||
|
local results
|
||||||
|
|
||||||
|
# Initialize results variable
|
||||||
|
results=""
|
||||||
|
|
||||||
|
echo "Backing up current mount points and options..."
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ -z "$line" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
fs_type=$(echo "$line" | awk '{print $5}')
|
||||||
|
|
||||||
|
# Skip excluded devices
|
||||||
|
if is_excluded "$device"; then
|
||||||
|
echo "Skipping excluded device $device"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${btrfs_roots["$device"]}" ]]; then
|
||||||
|
if [[ "$fs_type" == "btrfs" ]]; then
|
||||||
|
# Keep track of initial unique btrfs mounts per device
|
||||||
|
btrfs_roots["$device"]="$mount_point"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update backups accordingly for the rest
|
||||||
|
#results+="$line"$'\n'
|
||||||
|
#backup_partition "$device"
|
||||||
|
#backup_uuid "$device"
|
||||||
|
fi
|
||||||
|
results+="$line"$'\n'
|
||||||
|
done < <(mount | grep "^/dev")
|
||||||
|
#mount | grep "^/dev" > "${backupDir}/mounts.backup"
|
||||||
|
|
||||||
|
# Write results to the backup file
|
||||||
|
echo "$results" > "${backupDir}/mounts.backup"
|
||||||
|
|
||||||
|
echo "Mount points backed up to ${backupDir}/mounts.backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore mount points to /mnt/restore, supporting Btrfs subvolumes
|
||||||
|
restore_mount_points() {
|
||||||
|
local original_partition
|
||||||
|
local partition
|
||||||
|
local mount_point
|
||||||
|
local mount_opts
|
||||||
|
local subvol
|
||||||
|
local fs_type
|
||||||
|
|
||||||
|
if [[ -f "${backupDir}/mounts.backup" ]]; then
|
||||||
|
echo "Restoring mount points from ${backupDir}/mounts.backup to /mnt/restore..."
|
||||||
|
mkdir -p /mnt/restore
|
||||||
|
while IFS= read -r line; do
|
||||||
|
original_partition=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
mount_opts=$(echo "$line" | awk -F' ' '{for(i=4;i<=NF;i++){print $i}}' | tr -d '()')
|
||||||
|
|
||||||
|
# Extract and remove subvol and subvolid from mount options
|
||||||
|
subvol=$(echo "$mount_opts" | grep -oP 'subvol=\K[^,]*')
|
||||||
|
mount_opts=$(echo "$mount_opts" | sed -e 's/subvol=[^,]*,//g' -e 's/subvolid=[^,]*,//g')
|
||||||
|
|
||||||
|
# Rename partition if specified
|
||||||
|
partition="$original_partition"
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
echo "Renaming '$original_partition' to '$partition'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "/mnt/restore$mount_point"
|
||||||
|
fs_type=$(blkid -o value -s TYPE "$partition")
|
||||||
|
|
||||||
|
if [[ "$fs_type" == "btrfs" ]]; then
|
||||||
|
if [[ -n "$subvol" ]]; then
|
||||||
|
echo "Mounting Btrfs subvolume $subvol on /mnt/restore$mount_point"
|
||||||
|
mount -t btrfs -o subvol="$subvol,$mount_opts" "$partition" "/mnt/restore$mount_point"
|
||||||
|
else
|
||||||
|
echo "Mounting Btrfs volume $partition on /mnt/restore$mount_point"
|
||||||
|
mount -t btrfs -o "$mount_opts" "$partition" "/mnt/restore$mount_point"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Mounting $partition on /mnt/restore$mount_point with options $mount_opts"
|
||||||
|
mount -o "$mount_opts" "$partition" "/mnt/restore$mount_point"
|
||||||
|
fi
|
||||||
|
done < "${backupDir}/mounts.backup"
|
||||||
|
echo "Mount points restored to /mnt/restore."
|
||||||
|
else
|
||||||
|
echo "Backup file ${backupDir}/mounts.backup not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore a partition table with optional device renaming
|
||||||
|
restore_partition() {
|
||||||
|
local device="$1"
|
||||||
|
local original_device="$device"
|
||||||
|
local backup_file
|
||||||
|
local temp_file
|
||||||
|
#local mount_point
|
||||||
|
|
||||||
|
# Check if the device should be renamed
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
echo "Renaming device $device to ${rename_map[$device]}"
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_file="${backupDir}/partitions_$(basename "$original_device").backup"
|
||||||
|
if [[ ! -f "$backup_file" ]]; then
|
||||||
|
echo "Backup file $backup_file not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a temporary file for the modified backup
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
trap 'rm -f "$temp_file"' EXIT
|
||||||
|
|
||||||
|
# Modify the backup file to use the new device name
|
||||||
|
sed "s|$original_device|$device|g" "$backup_file" > "$temp_file"
|
||||||
|
|
||||||
|
echo "Restoring partition table for $device..."
|
||||||
|
sfdisk "$device" < "$temp_file"
|
||||||
|
echo "Partition table restored from $backup_file"
|
||||||
|
|
||||||
|
# Check if the filesystem is Btrfs
|
||||||
|
#if blkid -o value -s TYPE "$device" | grep -q "btrfs"; then
|
||||||
|
# mount_point="/mnt/restore$(blkid -o value -s UUID "$device")"
|
||||||
|
# mkdir -p "$mount_point"
|
||||||
|
# mount -t btrfs "$device" "$mount_point"
|
||||||
|
#
|
||||||
|
# # Restore Btrfs subvolumes for the device
|
||||||
|
# restore_btrfs_subvolumes "$device" "$mount_point"
|
||||||
|
#
|
||||||
|
# umount "$mount_point"
|
||||||
|
# rmdir "$mount_point"
|
||||||
|
#fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore filesystem UUID with optional device renaming
|
||||||
|
restore_uuid() {
|
||||||
|
local partition="$1"
|
||||||
|
local original_partition="$partition"
|
||||||
|
local uuid
|
||||||
|
|
||||||
|
# Check if the partition should be renamed
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${backupDir}/uuid_$(basename "$original_partition").backup" ]]; then
|
||||||
|
uuid=$(<"${backupDir}/uuid_$(basename "$original_partition").backup")
|
||||||
|
#uuid=$(cut -d'=' -f2 < "${backupDir}/uuid_$(basename "$original_partition").backup" | tr -d '"')
|
||||||
|
echo "Restoring UUID $uuid to $partition..."
|
||||||
|
|
||||||
|
case "$(blkid -o value -s TYPE "$partition")" in
|
||||||
|
ext2|ext3|ext4)
|
||||||
|
tune2fs -U "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
xfs)
|
||||||
|
xfs_admin -U "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
btrfs)
|
||||||
|
btrfstune -u "$uuid" "$partition"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported filesystem type."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "UUID restored."
|
||||||
|
else
|
||||||
|
echo "Backup file ${backupDir}/uuid_$(basename "$original_partition").backup not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore Btrfs subvolumes from the backup list to the given mount point
|
||||||
|
restore_btrfs_subvolumes() {
|
||||||
|
local partition="$1"
|
||||||
|
local original_partition="$partition"
|
||||||
|
local mount_point
|
||||||
|
local subvol_path
|
||||||
|
local backup_file
|
||||||
|
|
||||||
|
# Check if the partition should be renamed
|
||||||
|
if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
partition="${rename_map[$partition]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_file="${backupDir}/btrfs_$(basename "$original_partition").backup"
|
||||||
|
|
||||||
|
echo "Restoring Btrfs subvolumes from $backup_file to $partition..."
|
||||||
|
|
||||||
|
if [[ ! -f "$backup_file" ]]; then
|
||||||
|
echo "Backup file $backup_file not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#mount_point="/mnt/restore_btrfs"
|
||||||
|
mount_point="/mnt/restore_$(blkid -o value -s UUID "$partition")"
|
||||||
|
mkdir -p "$mount_point" || exit_fail 200 "FATAL: Cannot mkdir '$mount_point'"
|
||||||
|
mount -t btrfs "$partition" "$mount_point" || exit_fail 201 "FATAL: Cannot mount btrfs filesystem '$partition' to '$mount_point'"
|
||||||
|
|
||||||
|
while IFS= read -r subvol_path; do
|
||||||
|
echo "Restoring subvolume $subvol_path"
|
||||||
|
btrfs subvolume create "$mount_point/$subvol_path" || exit_fail 202 "FATAL: Cannot create subvolume '$subvol_path' on '$mount_point'"
|
||||||
|
done < "$backup_file"
|
||||||
|
|
||||||
|
umount "$mount_point"
|
||||||
|
rmdir "$mount_point"
|
||||||
|
|
||||||
|
echo "Btrfs subvolumes restored on $partition"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Format device/partition
|
||||||
|
restore_format() {
|
||||||
|
local partition="$1"
|
||||||
|
local fs_type="$2"
|
||||||
|
|
||||||
|
if [[ ! -b "$partition" ]]; then
|
||||||
|
echoerr "Partition '$partition' is not a block device, cannot format"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$fs_type" in
|
||||||
|
ext2|ext3|ext4)
|
||||||
|
mkfs."$fs_type" "$partition"
|
||||||
|
;;
|
||||||
|
xfs)
|
||||||
|
mkfs.xfs -f "$partition"
|
||||||
|
;;
|
||||||
|
btrfs)
|
||||||
|
mkfs.btrfs -f "$partition"
|
||||||
|
;;
|
||||||
|
vfat)
|
||||||
|
mkfs.vfat "$partition"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported filesystem type."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to handle exclusion list with wildcard and reverse matching
|
||||||
|
is_excluded() {
|
||||||
|
#local pattern="$"
|
||||||
|
local device="$1"
|
||||||
|
|
||||||
|
for exclude in "${exclude_opts[@]}"; do
|
||||||
|
if [[ "$exclude" == !* ]]; then
|
||||||
|
pattern="${exclude#!}"
|
||||||
|
if [[ "$device" == $pattern ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pattern="$exclude"
|
||||||
|
if [[ "$device" == $pattern ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Function to handle all backup operations
|
||||||
|
backup_all() {
|
||||||
|
local partition
|
||||||
|
local base_device
|
||||||
|
local mount_point
|
||||||
|
local fs_type
|
||||||
|
local -a device_nodes
|
||||||
|
|
||||||
|
echo "Backing up all partitions..."
|
||||||
|
backup_mounts
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
partition=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
fs_type=$(echo "$line" | awk '{print $5}')
|
||||||
|
if [[ -z "$line" || -z "$partition" || -z "$mount_point" || -z "$fs_type" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip excluded partition
|
||||||
|
if is_excluded "$partition"; then
|
||||||
|
echo "Skipping excluded device $partition"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check_in_array "$partition" "${device_nodes[@]}"; then
|
||||||
|
device_nodes+=("$partition")
|
||||||
|
base_device=$(get_base_device "$partition")
|
||||||
|
|
||||||
|
if ! check_in_array "$base_device" "${device_nodes[@]}"; then
|
||||||
|
device_nodes+=("$base_device")
|
||||||
|
backup_partition "$base_device"
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_uuid "$partition"
|
||||||
|
|
||||||
|
# If the filesystem type is Btrfs, back up its subvolumes
|
||||||
|
if [[ "$fs_type" == "btrfs" ]]; then
|
||||||
|
backup_btrfs_subvolumes "$partition" "$mount_point"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "${backupDir}/mounts.backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore all partitions and filesystems from backup files
|
||||||
|
restore_all() {
|
||||||
|
local device
|
||||||
|
local original_device="$device"
|
||||||
|
local mount_point
|
||||||
|
local fs_type
|
||||||
|
local -a device_nodes
|
||||||
|
#local partition
|
||||||
|
|
||||||
|
echo "Restoring all partitions and filesystems from backup..."
|
||||||
|
|
||||||
|
# Restore partition tables
|
||||||
|
while IFS= read -r line; do
|
||||||
|
device=$(echo "$line" | awk '{print $1}')
|
||||||
|
mount_point=$(echo "$line" | awk '{print $3}')
|
||||||
|
fs_type=$(echo "$line" | awk '{print $5}')
|
||||||
|
if [[ -z "$line" || -z "$device" || -z "$mount_point" || -z "$fs_type" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip excluded partition
|
||||||
|
if is_excluded "$device"; then
|
||||||
|
echo "Skipping excluded device $device"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Rename device if specified
|
||||||
|
if [[ -n "${rename_map[$device]}" ]]; then
|
||||||
|
device="${rename_map[$device]}"
|
||||||
|
echo "Renaming device '$original_device' to '$device'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check_in_array "$device" "${device_nodes[@]}"; then
|
||||||
|
device_nodes+=("$device")
|
||||||
|
|
||||||
|
restore_partition "$original_device"
|
||||||
|
restore_format "$device" "$fs_type"
|
||||||
|
|
||||||
|
if [[ "$restore_uuid" == true ]]; then
|
||||||
|
restore_uuid "$original_device"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$fs_type" == "btrfs" ]]; then
|
||||||
|
if [[ -z "${btrfs_roots["$device"]}" ]]; then
|
||||||
|
# Keep track of initial unique btrfs mounts per device
|
||||||
|
btrfs_roots["$device"]="$mount_point"
|
||||||
|
restore_btrfs_subvolumes "$original_device"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "${backupDir}/mounts.backup"
|
||||||
|
|
||||||
|
#if [[ "$restore_uuid" == true ]]; then
|
||||||
|
# while IFS= read -r line; do
|
||||||
|
# partition=$(echo "$line" | awk '{print $1}')
|
||||||
|
# # Rename partition if specified
|
||||||
|
# if [[ -n "${rename_map[$partition]}" ]]; then
|
||||||
|
# partition="${rename_map[$partition]}"
|
||||||
|
# fi
|
||||||
|
# restore_uuid "$partition"
|
||||||
|
# done < "${backupDir}/mounts.backup"
|
||||||
|
#fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function to handle command-line arguments and invoke appropriate functions
|
||||||
|
main() {
|
||||||
|
local exclude_file
|
||||||
|
local old_device new_device
|
||||||
|
|
||||||
|
if [[ "$1" == "--help" ]]; then
|
||||||
|
showHelp
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
backup)
|
||||||
|
shift
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--exclude)
|
||||||
|
shift
|
||||||
|
exclude_opts+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude-file)
|
||||||
|
shift
|
||||||
|
exclude_file="$1"
|
||||||
|
if [[ -f "$exclude_file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
exclude_opts+=("$line")
|
||||||
|
done < "$exclude_file"
|
||||||
|
else
|
||||||
|
echo "Exclude file $exclude_file does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
showHelp
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid option: $1"
|
||||||
|
echo "Use --help to display the help message."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
create_backup_dir
|
||||||
|
backup_all
|
||||||
|
;;
|
||||||
|
|
||||||
|
restore)
|
||||||
|
shift
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--no-uuid)
|
||||||
|
restore_uuid=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude)
|
||||||
|
shift
|
||||||
|
exclude_opts+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--exclude-file)
|
||||||
|
shift
|
||||||
|
exclude_file="$1"
|
||||||
|
if [[ -f "$exclude_file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
exclude_opts+=("$line")
|
||||||
|
done < "$exclude_file"
|
||||||
|
else
|
||||||
|
echo "Exclude file $exclude_file does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--rename)
|
||||||
|
shift
|
||||||
|
old_device="$1"
|
||||||
|
shift
|
||||||
|
new_device="$1"
|
||||||
|
rename_map["$old_device"]="$new_device"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
showHelp
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid option: $1"
|
||||||
|
echo "Use --help to display the help message."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
restore_all
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Invalid command: $1"
|
||||||
|
echo "Use --help to display the help message."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the main function with all arguments
|
||||||
|
main "$@"
|
70
scripts/postgresql
Executable file
70
scripts/postgresql
Executable file
|
@ -0,0 +1,70 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir=/etc/restore
|
||||||
|
pgsqlDir="$restoreDir/postgresql"
|
||||||
|
scriptDir="$(dirname "$0")"
|
||||||
|
|
||||||
|
function readConfig() {
|
||||||
|
local $config
|
||||||
|
|
||||||
|
if [[ -r "${scriptDir}/../config/postgresql.cfg" ]]; then
|
||||||
|
config="$(readlink -f "${scriptDir}/../config/postgresql.cfg")"
|
||||||
|
else
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
while read -r -a vals
|
||||||
|
do
|
||||||
|
[[ "${vals[*]}" =~ ^#.*$ ]] && continue
|
||||||
|
[[ -z "${vals[0]}" ]] && continue
|
||||||
|
if [[ "${vals[0]}" -ge 10 ]]; then
|
||||||
|
echo "${vals[@]}"
|
||||||
|
fi
|
||||||
|
done < "$config"
|
||||||
|
}
|
||||||
|
|
||||||
|
function runBackups() {
|
||||||
|
local vals
|
||||||
|
local version
|
||||||
|
local cluster
|
||||||
|
|
||||||
|
while read -r -a vals
|
||||||
|
do
|
||||||
|
version="${vals[0]}"
|
||||||
|
cluster="${vals[1]}"
|
||||||
|
|
||||||
|
echo "Backing up PostgreSQL $version - $cluster"
|
||||||
|
pg_backupcluster "$version" "$cluster" createdirectory || return $?
|
||||||
|
sudo -u postgres pg_backupcluster "$version" "$cluster" basebackup || return $?
|
||||||
|
sudo -u postgres pg_backupcluster "$version" "$cluster" dump || return $?
|
||||||
|
sudo -u postgres pg_backupcluster "$version" "$cluster" expirebasebackups 1 || return $?
|
||||||
|
sudo -u postgres pg_backupcluster "$version" "$cluster" expiredumps 1 || return $?
|
||||||
|
done < <(readConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
if [[ -d "$pgsqlDir" ]]; then
|
||||||
|
rm -rf "$pgsqlDir" || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
runBackups || exit $?
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
rm -rf "$pgsqlDir" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $? ;;
|
||||||
|
after) hook_after || exit $? ;;
|
||||||
|
fail) hook_fail || exit $? ;;
|
||||||
|
finally) hook_final || exit $? ;;
|
||||||
|
esac
|
101
scripts/run-parts
Executable file
101
scripts/run-parts
Executable file
|
@ -0,0 +1,101 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# run-parts - concept taken from Debian
|
||||||
|
|
||||||
|
# keep going when something fails
|
||||||
|
set +e
|
||||||
|
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo "Usage: run-parts [--args | --list | --test] <dir>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while [ $# -gt 1 ]; do
|
||||||
|
case $1 in
|
||||||
|
--args)
|
||||||
|
runargs=$2
|
||||||
|
shift 2
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--list)
|
||||||
|
list=1
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--test)
|
||||||
|
test=1
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
# -- end of options
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# directory
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ! -d $1 ]; then
|
||||||
|
echo "Not a directory: $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /etc/sysconfig/run-parts ]; then
|
||||||
|
. /etc/sysconfig/run-parts
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ignore *~ and *, scripts
|
||||||
|
for i in $(LC_ALL=C; echo ${1%/}/*[^~,]) ; do
|
||||||
|
[ -d $i ] && continue
|
||||||
|
# Don't run *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} scripts
|
||||||
|
[ "${i%.cfsaved}" != "${i}" ] && continue
|
||||||
|
[ "${i%.rpmsave}" != "${i}" ] && continue
|
||||||
|
[ "${i%.rpmorig}" != "${i}" ] && continue
|
||||||
|
[ "${i%.rpmnew}" != "${i}" ] && continue
|
||||||
|
[ "${i%.swp}" != "${i}" ] && continue
|
||||||
|
[ "${i%,v}" != "${i}" ] && continue
|
||||||
|
|
||||||
|
# jobs.deny prevents specific files from being executed
|
||||||
|
# jobs.allow prohibits all non-named jobs from being run.
|
||||||
|
# can be used in conjunction but there's no reason to do so.
|
||||||
|
if [ -r $1/jobs.deny ]; then
|
||||||
|
grep -q "^$(basename $i)$" $1/jobs.deny && continue
|
||||||
|
fi
|
||||||
|
if [ -r $1/jobs.allow ]; then
|
||||||
|
grep -q "^$(basename $i)$" $1/jobs.allow || continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e $i ]; then
|
||||||
|
if [ -r $1/whitelist ]; then
|
||||||
|
grep -q "^$(basename $i)$" $1/whitelist && continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${list:-0} = 1 ]; then
|
||||||
|
echo $i;
|
||||||
|
elif [ -x $i ]; then
|
||||||
|
if [ ${test:-0} = 1 ]; then
|
||||||
|
echo $i;
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$RANDOMIZE" != "" ]; then
|
||||||
|
let "rtime = $RANDOM"
|
||||||
|
if [ "$RANDOMTIME" != "" ]; then
|
||||||
|
let "rtime %= $RANDOMTIME"
|
||||||
|
else
|
||||||
|
let "rtime %= 300"
|
||||||
|
fi
|
||||||
|
sleep $rtime
|
||||||
|
fi
|
||||||
|
|
||||||
|
# run executable files
|
||||||
|
echo "run-parts[$$]" "($1) starting $(basename $i)"
|
||||||
|
$i $runargs 2>&1
|
||||||
|
echo "run-parts[$$]" "($1) finished $(basename $i)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
36
scripts/vaultwarden
Executable file
36
scripts/vaultwarden
Executable file
|
@ -0,0 +1,36 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
restoreDir=/etc/restore
|
||||||
|
vaultwardenDir="$restoreDir/vaultwarden"
|
||||||
|
|
||||||
|
hook_before() {
|
||||||
|
if [[ -d "$vaultwardenDir" ]]; then
|
||||||
|
rm -rf "$vaultwardenDir" || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -x "$(which sqlite3)" || exit 2
|
||||||
|
backupDate=$(date +"%Y-%m-%d")
|
||||||
|
vaultwardenHome=$(getent passwd vaultwarden | cut -f6 -d:)
|
||||||
|
|
||||||
|
mkdir -p "$vaultwardenDir"
|
||||||
|
sqlite3 "${vaultwardenHome}/data/db.sqlite3" ".backup '${vaultwardenDir}/db-${backupDate}.sqlite3'"
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_after() {
|
||||||
|
rm -rf "$vaultwardenDir" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_fail() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
hook_final() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
before) hook_before || exit $?;;
|
||||||
|
after) hook_after || exit $?;;
|
||||||
|
fail) hook_fail || exit $?;;
|
||||||
|
finally) hook_final || exit $?;;
|
||||||
|
esac
|
32
templates/config/base.cfg
Normal file
32
templates/config/base.cfg
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# This is the base configuration used my multiple agents.
|
||||||
|
|
||||||
|
# This is where persistent larger files reside. Including the SystemRescueCD and Backup ISO's reside.
|
||||||
|
# NOTE: This is not where actual backups will reside.
|
||||||
|
systemrescueBaseDir="/var/backups/systemrescue-backup"
|
||||||
|
|
||||||
|
# Backup Engine to use:
|
||||||
|
# Options are either resticprofile or borgmatic.
|
||||||
|
backupEngine="resticprofile"
|
||||||
|
|
||||||
|
# ResticProfile Options:
|
||||||
|
# These are versions of restic and resticprofile to download and use with the
|
||||||
|
# SystemRescueBackup recovery image.
|
||||||
|
resticVersion="0.17.0"
|
||||||
|
resticprofileVersion="0.28.0"
|
||||||
|
|
||||||
|
# Borgmatic Options:
|
||||||
|
# This is the SystemRescueBackup SRM Module to include in the recovery image.
|
||||||
|
# To generate this, boot a SystemRescueCD in a VM, run:
|
||||||
|
# pacman -Sy borgmatic
|
||||||
|
# cowpacman2srm borgmatic.srm
|
||||||
|
# And upon success, copy the borgmatic.srm to your host system and provide
|
||||||
|
# the path to it here:
|
||||||
|
borgmaticSRM=""
|
||||||
|
|
||||||
|
# SystemRescueCD Version to Download and Use. If you're using borgmatic, this
|
||||||
|
# version will be relevant to the previously provided borgmaticSRM module.
|
||||||
|
systemrescueVersion="11.02"
|
||||||
|
|
||||||
|
# Temporary working directory, mostly for downloads to generate the
|
||||||
|
# SystemRescueBackup disc image.
|
||||||
|
systemrescueTempDir="/tmp/systemrescue-backup"
|
3
templates/config/consul_backup.cfg
Normal file
3
templates/config/consul_backup.cfg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# This configuration file is used for providing the path
|
||||||
|
# to consul's binary.
|
||||||
|
# Example: CONSUL_PATH=/opt/consul/bin
|
6
templates/config/gitea_backup.cfg
Normal file
6
templates/config/gitea_backup.cfg
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# This configuration file is used for providing configuration parameters to
|
||||||
|
# the gitea backup agent.
|
||||||
|
# GITEA_BIN Default: Found in PATH
|
||||||
|
# GITEA_CONFIG Default: /etc/gitea/app.ini
|
||||||
|
# GITEA_USER Default: git
|
||||||
|
# GITEA_HOME Default: Home Directory of GITEA_USER
|
4
templates/config/mysql_backup.cfg
Normal file
4
templates/config/mysql_backup.cfg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# This configuration file is used for providing MySQL login
|
||||||
|
# credentials as needed. You can use the environment variables
|
||||||
|
# MYSQL_HOST, MYSQL_PWD, and MYSQL_HOME, for example.
|
||||||
|
# See: https://mariadb.com/kb/en/mariadb-environment-variables/
|
4
templates/config/postgresql.cfg
Normal file
4
templates/config/postgresql.cfg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Configuration for pg_backupcluster stylebackups.
|
||||||
|
# Format per line: VERSION CLUSTER
|
||||||
|
# Example: 10 main
|
||||||
|
10 main
|
Loading…
Reference in a new issue