#!/bin/bash first_be_sure="First be sure that the USB device to backup to is connected now" no_config="There is no configuration file. Let's create it. Choose the USB device that will trigger the backup" devices="Devices" select_path="Select the path in the disk (must be mounted) to place the backup" select_folder="Select the folder to backup" encrypt="Do you want to encrypt the backups? (Recommended)" initializing="Initializing repository" backing_up="Backing up" to="to" there_was_error="There was an error" backup_succeeded="Backup finished without errors.\n Result: " doing_backup="doing the backup" initializing_low="initializing repository" waiting="Waiting another 3 seconds" waited="Waited for 60 seconds for the destination to be available without sucess. Check your configuration and that the destination folder exists" another_copy="There is another copy running" reconfigure_help="Reconfigure the script" help="Show this help" function usage() { echo "${script_name} [-r|--reconfigure] [-h|--help]" echo " -r|--reconfigure ${reconfigure_help}" echo " -h|--help ${help}" } function configure() { zenity --info --text "${first_be_sure}" # shellcheck disable=SC2046 device=$(zenity --list --text="${no_config}" --column="${devices}" --separator='\n' $(lsusb | sed 's/.* ID //g' | sed 's/ /_/g')) echo "device='${device}'" > "${HOME}/.config/simple_backup.conf" zenity --info --text "${select_path}" destination=$(zenity --file-selection --directory) echo "destination='${destination}'" >> "${HOME}/.config/simple_backup.conf" zenity --info --text "${select_folder}" folder=$(zenity --file-selection --directory) echo "folder='${folder}'" >> "${HOME}/.config/simple_backup.conf" if zenity --question --text "${encrypt}"; then password=$(zenity --password) echo "${password}" > "${HOME}/.config/simple_backup.password" chmod go-rwx "${HOME}/.config/simple_backup.password" else rm "${HOME}/.config/simple_backup.password" fi } script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) script_name=$(basename "${BASH_SOURCE[0]}") # shellcheck disable=SC2001 locale=$(echo "${LANG}" | sed 's/\..*$//') if [ -e "${script_dir}/locales/${locale}" ]; then # shellcheck disable=SC1090 source "${script_dir}/locales/${locale}" fi while [ ${#} -gt 0 ] do case "${1}" in "-h"|"--help") usage shift exit 0 ;; '-r'|'--reconfigure') shift configure ;; *) echo "Ignoring unknown parameter '${1}'" shift ;; esac done if [ ! -r "${HOME}/.config/simple_backup.conf" ]; then configure fi if [ ! -x /usr/local/bin/restic ]; then if [ "$(uname -i)" == 'x86_64' ]; then arch="amd64" elif [[ "$(uname -a)" =~ aarch64 ]]; then arch='arm64' fi /usr/bin/wget -q -O - "$(/usr/bin/curl -s -L -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' https://api.github.com/repos/restic/restic/releases/latest | jq ".assets[]|select(.browser_download_url|contains(\"${arch}\"))|.browser_download_url" | sed 's/\"//g')" | bzip2 -dc > /usr/local/bin/restic chmod +x /usr/local/bin/restic fi if [ $(pgrep -f -c "${script_name}") -gt 1 ]; then echo "${another_copy}" exit 3 fi # shellcheck disable=SC1091 source "${HOME}/.config/simple_backup.conf" if [ -r "${HOME}/.config/simple_backup.password" ]; then password_file=(--password-file "${HOME}/.config/simple_backup.password") else password_file=() fi mkdir -p "${HOME}/.logs" vendor="${device:0:4}" product_id="${device:5:4}" if [ ! -e /etc/udev/rules.d/10_simple_backup.rules ]; then sudo touch /etc/udev/rules.d/10_simple_backup.rules echo "SUBSYSTEM==\"usb\" ACTION==\"add\" ATTRS{idVendor}==\"${vendor}\" ATTRS{idProduct}==\"${product_id}\" ATTR{partscan}==\"1\" TAG+=\"systemd\" ENV{SYSTEMD_USER_WANTS}=\"simple_backup@\$devnode.service\"" | sudo tee /etc/udev/rules.d/10_simple_backup.rules fi if [ ! -e "${HOME}/.config/systemd/user/simple_backup@.service" ]; then mkdir -p "${HOME}/.config/systemd/user/" cat << EOF > "${HOME}/.config/systemd/user/simple_backup@.service" [Unit] Description=Simple backup USB serial device at %I [Service] Type=simple ExecStart=bash -c 'sleep \$((1 + \$RANDOM % 10)); ${script_dir}/${script_name} %IEOF' EOF systemctl --user daemon-reload systemctl --user enable simple_backup@.service fi if [ ! -e "${destination}" ]; then count=0 while [ ! -e "${destination}" ] do sleep 3 echo "${waiting}" count=$((count + 1)) if [ ${count} -gt 20 ]; then zenity --error --text "${waited}" exit 2 fi done fi if [ ! -e "${destination}/config" ]; then echo "${initializing} '${destination}'..." if ! /usr/local/bin/restic init "${password_file[@]}" -r "${destination}"; then zenity --error --text "${there_was_error} ${return_code} ${initializing_low}" exit 1 fi fi echo "${backing_up} '${folder}' ${to} '${destination}'..." current_date=$(date +%Y.%m.%d_%H_%M_%S) /usr/local/bin/restic backup "${password_file[@]}" -r "${destination}" "${folder}" --json > "${HOME}/.logs/simple_backup_${current_date}.json" return_code=${?} cp "${HOME}/.logs/simple_backup_${current_date}.json" "${HOME}/.logs/simple_backup_last.json" -f if [ "${return_code}" != "0" ]; then zenity --error --text "${there_was_error} ${return_code} ${doing_backup}" else result=$(tail -n1 "${HOME}/.logs/simple_backup_${current_date}.json" | jq '.') zenity --info --text "${backup_succeeded} ${result}" fi