Fixed various bugs
All checks were successful
backup.sh / bash (push) Successful in 11s

This commit is contained in:
Marco Cetica 2024-04-04 11:55:56 +02:00
parent baa6f68706
commit 08e790a13b
Signed by: marco
GPG Key ID: 45060A949E90D0FD
3 changed files with 53 additions and 33 deletions

View File

@ -16,6 +16,7 @@ This will copy `backup.sh` into `/usr/local/bin/backup.sh`, `sources.bk` into `/
you can issue `sudo make uninstall`. you can issue `sudo make uninstall`.
At this point you still need to install the following dependencies: At this point you still need to install the following dependencies:
- `Bash`
- `rsync` - `rsync`
- `tar` - `tar`
- `gpg` - `gpg`
@ -112,7 +113,7 @@ After that, you will find the backup archive and the checksum file in
You can also use `backup.sh` from a crontab rule: You can also use `backup.sh` from a crontab rule:
```sh ```sh
$> sudo crontab -e $> sudo crontab -e
30 03 * * 6 EKEY=$(cat /home/john/.ekey) sh -c '/usr/local/bin/backup.sh -b /usr/local/etc/sources.bk /home/john $EKEY' > /dev/null 2>&1 30 03 * * 6 EKEY=$(cat /home/john/.ekey) bash -c '/usr/local/bin/backup.sh -b /usr/local/etc/sources.bk /home/john $EKEY' > /dev/null 2>&1
``` ```
@ -121,8 +122,8 @@ key is stored in a local file(with fixed permissions) to avoid password leaking
adopt this practice while using the `--extract` option to avoid password leaking in shell history. adopt this practice while using the `--extract` option to avoid password leaking in shell history.
### Backup extraction ### Backup extraction
`backup.sh` can also be used to extract the encrypted backup as well to verify the integrity `backup.sh` can also be used to extract and to verify the encrypted backup.
of the backup data. To do so, use the following commands: To do so, use the following commands:
```sh ```sh
$> ./backup.sh --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> $> ./backup.sh --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD>
@ -142,10 +143,10 @@ backup-nginx-<YYYYMMDD>
backup-ssh-<YYYYMMDD> backup-ssh-<YYYYMMDD>
``` ```
**note:**: be sure to rename any directory with that name to avoid collisions. **note**: be sure to rename any directory with that name to avoid collisions.
Instead, if you also want to verify the integrity of the backup data, use the following commands: If you also want to verify the integrity of the backup data, use the following commands:
```sh ```sh
$> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHECKSUM_ABSOLUTE_PATH> $> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHECKSUM_ABSOLUTE_PATH>
``` ```
@ -153,11 +154,9 @@ $> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHEC
For instance: For instance:
```sh ```sh
$> ./backup.sh --checksum --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234 $PWD/backup-<hostname>-<YYYYMMDD>.sha256 $> ./backup.sh --checksum --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234 backup-<hostname>-<YYYYMMDD>.sha256
``` ```
**note:** be sure to provide the ABSOLUTE PATH of the checksum file.
## How does backup.sh work? ## How does backup.sh work?
**backup.sh** uses _rsync_ to copy the files, _tar_ to compress the backup, _gpg_ to encrypt it and **backup.sh** uses _rsync_ to copy the files, _tar_ to compress the backup, _gpg_ to encrypt it and
_sha256sum_ to verify it. _sha256sum_ to verify it.

View File

@ -1,4 +1,4 @@
#!/bin/sh -e #!/usr/bin/env bash
# backup.sh is a POSIX compliant, modular and lightweight # backup.sh is a POSIX compliant, modular and lightweight
# backup utility to save and encrypt your files. # backup utility to save and encrypt your files.
# #
@ -34,6 +34,8 @@
# Copyright (c) 2018,2023,2024 Marco Cetica <email@marcocetica.com> # Copyright (c) 2018,2023,2024 Marco Cetica <email@marcocetica.com>
# #
set -e
checkdeps() { checkdeps() {
# Check if dependencies are installed # Check if dependencies are installed
missing_dep=0 missing_dep=0
@ -51,6 +53,20 @@ checkdeps() {
fi fi
} }
# $1: filename
gethash() {
FILE_NAME="$1"
OS="$(uname)"
if [ "$OS" = "Linux" ]; then
HASH="$(sha256sum "$FILE_NAME" | awk '{print $1}')"
else
HASH="$(sha256 -q "$FILE_NAME")"
fi
echo "$HASH"
}
# $1: sources.bk file # $1: sources.bk file
# $2: output path # $2: output path
# $3: password # $3: password
@ -75,12 +91,6 @@ make_backup() {
exit 1 exit 1
fi fi
# Check whether the sources file exists or not
if [ ! -f "$BACKUP_SH_SOURCES_PATH" ]; then
echo "$BACKUP_SH_SOURCES_PATH does not exist."
exit 1
fi
# Create temporary directory # Create temporary directory
mkdir -p "$BACKUP_SH_OUTPUT" mkdir -p "$BACKUP_SH_OUTPUT"
@ -97,7 +107,13 @@ make_backup() {
# Compute SHA256 of all files of the current directory # Compute SHA256 of all files of the current directory
if [ "$BACKUP_SH_SHA256" -eq 1 ]; then if [ "$BACKUP_SH_SHA256" -eq 1 ]; then
find "$path" -type f -exec sha256sum {} + | sort -k 2 | awk '{print $1}' >> "$BACKUP_SH_CHECKSUM_FILE" shopt -s globstar dotglob
for file in "$path"/**/*; do
# Skip directories
[ -d "$file" ] && continue
gethash "$file" >> "$BACKUP_SH_CHECKSUM_FILE"
done
shopt -u globstar dotglob
fi fi
# Copy files # Copy files
@ -150,7 +166,7 @@ extract_backup() {
--decrypt \ --decrypt \
--no-symkey-cache \ --no-symkey-cache \
--pinentry-mode=loopback \ --pinentry-mode=loopback \
--batch --passphrase "$BACKUP_SH_ARCHIVE_PW" \ --batch --passphrase-fd 3 3<<< "$BACKUP_SH_ARCHIVE_PW" \
--output backup.sh.tar.gz \ --output backup.sh.tar.gz \
"$BACKUP_SH_ARCHIVE_PATH" "$BACKUP_SH_ARCHIVE_PATH"
@ -159,16 +175,20 @@ extract_backup() {
# If specified, use SHA256 file to compute checksum of files # If specified, use SHA256 file to compute checksum of files
if [ -n "$BACKUP_SH_SHA256_FILE" ]; then if [ -n "$BACKUP_SH_SHA256_FILE" ]; then
for file in $(find "backup.sh.tmp" -type f | sort -k 2); do shopt -s globstar dotglob
for file in "backup.sh.tmp"/**/*; do
# Skip directories
[ -d "$file" ] && continue;
# Compute sha256 for current file # Compute sha256 for current file
sha256="$(sha256sum "$file" | awk '{print $1}')" SHA256="$(gethash "$file")"
# Check if checksum file contains hash # Check if checksum file contains hash
if ! grep -wq "$sha256" "$BACKUP_SH_SHA256_FILE"; then if ! grep -wq "$SHA256" "$BACKUP_SH_SHA256_FILE"; then
printf "[FATAL] - integrity error for '%s'.\n" "$file" printf "[FATAL] - integrity error for '%s'.\n" "$file"
rm -rf backup.sh.tar.gz backup.sh.tmp rm -rf backup.sh.tar.gz backup.sh.tmp
exit 1 exit 1
fi fi
done done
shopt -u globstar dotglob
fi fi
rm -rf backup.sh.tar.gz rm -rf backup.sh.tar.gz
@ -218,6 +238,7 @@ main() {
fi fi
if [ "$CHECKSUM_FLAG" -eq 1 ]; then if [ "$CHECKSUM_FLAG" -eq 1 ]; then
[ -e "$BACKUP_SH_SOURCES_PATH" ] || { echo "Sources file does not exist"; exit 1; }
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 1 make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 1
else else
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 0 make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 0
@ -231,18 +252,18 @@ main() {
shift 1 shift 1
;; ;;
-e|--extract) -e|--extract)
BACKUP_SH_ARCHIVE_PATH="$2" BACKUP_SH_ARCHIVE_FILE="$2"
BACKUP_SH_ARCHIVE_PW="$3" BACKUP_SH_ARCHIVE_PW="$3"
BACKUP_SH_SHA256_FILE="$4" BACKUP_SH_SHA256_FILE="$4"
if [ "$CHECKSUM_FLAG" -eq 1 ]; then if [ "$CHECKSUM_FLAG" -eq 1 ]; then
if [ -z "$BACKUP_SH_ARCHIVE_PATH" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ] || [ -z "$BACKUP_SH_SHA256_FILE" ]; then if [ -z "$BACKUP_SH_ARCHIVE_FILE" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ] || [ -z "$BACKUP_SH_SHA256_FILE" ]; then
echo "Please, specify an encrypted archive, a password and a SHA256 file." echo "Please, specify an encrypted archive, a password and a SHA256 file."
echo "For more informatio, try --help" echo "For more informatio, try --help"
exit 1 exit 1
fi fi
else else
if [ -z "$BACKUP_SH_ARCHIVE_PATH" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ]; then if [ -z "$BACKUP_SH_ARCHIVE_FILE" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ]; then
echo "Please, specify an encrypted archive and a password." echo "Please, specify an encrypted archive and a password."
echo "For more informatio, try --help" echo "For more informatio, try --help"
exit 1 exit 1
@ -251,9 +272,10 @@ main() {
if [ "$CHECKSUM_FLAG" -eq 1 ]; then if [ "$CHECKSUM_FLAG" -eq 1 ]; then
[ -e "$BACKUP_SH_SHA256_FILE" ] || { echo "Checksum file does not exist"; exit 1; } [ -e "$BACKUP_SH_SHA256_FILE" ] || { echo "Checksum file does not exist"; exit 1; }
extract_backup "$BACKUP_SH_ARCHIVE_PATH" "$BACKUP_SH_ARCHIVE_PW" "$BACKUP_SH_SHA256_FILE" [ -e "$BACKUP_SH_ARCHIVE_FILE" ] || { echo "Backup file does not exist"; exit 1; }
extract_backup "$BACKUP_SH_ARCHIVE_FILE" "$BACKUP_SH_ARCHIVE_PW" "$BACKUP_SH_SHA256_FILE"
else else
extract_backup "$BACKUP_SH_ARCHIVE_PATH" "$BACKUP_SH_ARCHIVE_PW" extract_backup "$BACKUP_SH_ARCHIVE_FILE" "$BACKUP_SH_ARCHIVE_PW"
fi fi
exit 0 exit 0

15
man.md
View File

@ -3,7 +3,7 @@ title: backup.sh
section: 1 section: 1
header: General Commands Manual header: General Commands Manual
footer: Marco Cetica footer: Marco Cetica
date: April 3, 2024 date: April 4, 2024
--- ---
# NAME # NAME
@ -101,7 +101,7 @@ After that, you will find the backup archive and the checksum file in
You can also use `backup.sh` from a crontab rule: You can also use `backup.sh` from a crontab rule:
``` ```
$> sudo crontab -e $> sudo crontab -e
30 03 * * 6 EKEY=$(cat /home/john/.ekey) sh -c '/usr/local/bin/backup.sh -b /usr/local/etc/sources.bk /home/john $EKEY' > /dev/null 2>&1 30 03 * * 6 EKEY=$(cat /home/john/.ekey) bash -c '/usr/local/bin/backup.sh -b /usr/local/etc/sources.bk /home/john $EKEY' > /dev/null 2>&1
``` ```
@ -110,8 +110,8 @@ key is stored in a local file(with fixed permissions) to avoid password leaking
adopt this practice while using the `--extract` option to avoid password leaking in shell history. adopt this practice while using the `--extract` option to avoid password leaking in shell history.
## Backup extraction ## Backup extraction
**backup.sh** can also be used to extract the encrypted backup as well to verify the integrity **backup.sh** can also be used to extract and to verify the encrypted backup.
of the backup data. To do so, use the following commands: To do so, use the following commands:
``` ```
$> ./backup.sh --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> $> ./backup.sh --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD>
@ -131,10 +131,10 @@ backup-nginx-<YYYYMMDD>
backup-ssh-<YYYYMMDD> backup-ssh-<YYYYMMDD>
``` ```
**note:**: be sure to rename any directory with that name to avoid collisions. **note**: be sure to rename any directory with that name to avoid collisions.
Instead, if you also want to verify the integrity of the backup data, use the following commands: If you also want to verify the integrity of the backup data, use the following commands:
``` ```
$> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHECKSUM_ABSOLUTE_PATH> $> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHECKSUM_ABSOLUTE_PATH>
``` ```
@ -142,10 +142,9 @@ $> ./backup.sh --checksum --extract <ENCRYPTED_ARCHIVE> <ARCHIVE_PASSWORD> <CHEC
For instance: For instance:
``` ```
$> ./backup.sh --checksum --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234 $PWD/backup-<hostname>-<YYYYMMDD>.sha256 $> ./backup.sh --checksum --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234 backup-<hostname>-<YYYYMMDD>.sha256
``` ```
**note:** be sure to provide the ABSOLUTE PATH of the checksum file.
## How does backup.sh work? ## How does backup.sh work?
**backup.sh** uses _rsync_ to copy the files, _tar_ to compress the backup, _gpg_ to encrypt it and **backup.sh** uses _rsync_ to copy the files, _tar_ to compress the backup, _gpg_ to encrypt it and