Last active
August 31, 2022 16:37
-
-
Save jeekkd/9adbd533db838b2c84ae8e05e50c4735 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Written by: Daulton | |
# Website: https://daulton.ca | |
# Github: https://github.com/jeekkd | |
# License: 2-clause BSD license | |
# Purpose: Script Restic backups for myself, only meant for me but modify it if its useful to you. | |
# Notes: Assure Restic and Swaks is installed. | |
# BSD 2-Clause License | |
# | |
# Copyright (c) [2022], [backup-restic.sh] | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are met: | |
# | |
# 1. Redistributions of source code must retain the above copyright notice, this | |
# list of conditions and the following disclaimer. | |
# | |
# 2. Redistributions in binary form must reproduce the above copyright notice, | |
# this list of conditions and the following disclaimer in the documentation | |
# and/or other materials provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
######## Variables ######## | |
# Restic repo password, same for each repo | |
export RESTIC_PASSWORD= | |
# Backup the following directory | |
backupDirList=/home/you/Important/ | |
# S3 bucket path | |
s3Bucket="https://example.com/example" | |
# B2 bucket name | |
B2Bucket= | |
# Minio S3 storage access | |
# https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html#amazon-s3 | |
export AWS_ACCESS_KEY_ID= | |
export AWS_SECRET_ACCESS_KEY= | |
# B2 storage access | |
# https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html#backblaze-b2 | |
export B2_ACCOUNT_ID= | |
export B2_ACCOUNT_KEY= | |
# Mount point for second disk | |
mountPoint=/mnt/data | |
# Secondary disk to mount | |
secondaryDisk=/dev/sdb1 | |
# Local mount point Restic repository name | |
localRepoName=restic-repo | |
# SMTP server hostname | |
smtpHostname=example.com | |
# Email account sending as | |
smtpFrom=sender@example.com | |
smtpFromPassword= | |
# Send email to the following account | |
smtpTo=you@example.com | |
########################### | |
# control_c() | |
# Trap Ctrl-C for a quick and clean exit when necessary | |
control_c() { | |
echo "Control-c pressed - exiting NOW" | |
exit 1 | |
} | |
# Trap any ctrl+c and call control_c function provided through functions.sh | |
trap control_c INT | |
# Exit and send email alert if error | |
check_exit_code_email() { | |
if [ $? -ne 0 ]; then | |
echo "Warning: Fatal error or source files could not be read." | |
echo "Exit code: $?" | |
swaks --to "$smtpTo" --from "$smtpFrom" -s "$smtpHostname":587 -tls -au alerts@tetmail.ca -ap "$smtpFromPassword" --header "Subject: Restic backup error" --body ~/restic.log > /dev/null 2>&1 | |
exit 1 | |
fi | |
} | |
# Check if local disk is mounted as read-only. | |
check_if_drive_ro() { | |
diskCheckResult=$(grep "[[:space:]]ro[[:space:],]" /proc/mounts | grep "$mountPoint") | |
[ "$diskCheckResult" = "" ] && return 3 | |
} | |
# Redirect stdout ( > ) into a named pipe ( >() ) running "tee" | |
exec > >(tee -i restic.log) | |
# Without this, only stdout would be captured - i.e. your | |
# log file would not contain any error messages. | |
# SEE (and upvote) the answer by Adam Spiers, which keeps STDERR | |
# as a separate stream - I did not want to steal from him by simply | |
# adding his answer to mine. | |
exec 2>&1 | |
echo "Backup beginning at: $(date)" | |
echo | |
# Check if Restic is already running | |
check_process() { | |
[ "$1" = "" ] && return 0 | |
[ $(pgrep -n $1) ] && return 1 || return 0 | |
} | |
check_process "restic" | |
if [ $? -eq 1 ]; then | |
echo "Warning: Restic already running, exiting.." | |
exit 1 | |
else | |
echo "Information: Another instance of Restic is not currently running, continuing." | |
fi | |
run_restic_local() { | |
echo "###" | |
echo "# Local backup to second HDD" | |
echo "###" | |
echo | |
restic -r "$mountPoint"/"$localRepoName" --verbose backup "$backupDirList" | |
check_exit_code_email | |
restic -r "$mountPoint"/"$localRepoName" forget --keep-hourly 6 --keep-daily 14 --keep-weekly 4 --keep-monthly 3 | |
restic -r "$mountPoint"/"$localRepoName" check | |
check_exit_code_email | |
echo | |
} | |
mount | grep -q "[[:space:]]$mountPoint[[:space:]]" | |
if [ $? -eq 0 ]; then | |
check_if_drive_ro | |
if [ $? -ne 3 ]; then | |
echo "Notice: Local disk is mounted ro, repairing.." | |
sudo umount -f "$mountPoint" | |
if [ $? -eq 0 ]; then | |
sudo ntfsfix "$secondaryDisk" | |
sudo ntfs-3g "$secondaryDisk" "$mountPoint" | |
if [ $? -eq 0 ]; then | |
run_restic_local | |
check_exit_code_email | |
fi | |
else | |
check_exit_code_email | |
echo "Critical: Unable to umount local disk to remount as rw, exiting." | |
fi | |
else | |
echo "Information: The path $mountPoint is already mounted, doing nothing" | |
run_restic_local | |
check_exit_code_email | |
fi | |
else | |
echo "Notice: Mounting local disk at $mountPoint" | |
sudo ntfsfix "$secondaryDisk" | |
sudo ntfs-3g "$secondaryDisk" "$mountPoint" | |
if [ $? -eq 0 ]; then | |
run_restic_local | |
check_exit_code_email | |
fi | |
fi | |
echo "###" | |
echo "# Backup to Minio on TrueNAS" | |
echo "###" | |
echo | |
restic -r s3:"$s3Bucket" --verbose backup "$backupDirList" | |
check_exit_code_email | |
restic -r s3:"$s3Bucket" forget --keep-hourly 6 --keep-daily 14 --keep-weekly 4 --keep-monthly 3 | |
restic -r s3:"$s3Bucket" check | |
check_exit_code_email | |
echo | |
echo "###" | |
echo "# Backup to Backblaze B2" | |
echo "###" | |
echo | |
restic -r b2:"$B2Bucket" --verbose backup "$backupDirList" | |
check_exit_code_email | |
restic -r b2:"$B2Bucket" forget --keep-hourly 6 --keep-daily 14 --keep-weekly 4 --keep-monthly 3 | |
restic -r b2:"$B2Bucket" check | |
check_exit_code_email | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment