1
1
#! /usr/bin/env bash
2
2
3
3
# =================================================================
4
- # Restic Backup Script v0.36 - 2025.09.29
4
+ # Restic Backup Script v0.37.1 - 2025.10.02
5
5
# =================================================================
6
6
7
7
set -euo pipefail
8
8
umask 077
9
9
10
10
# --- Script Constants ---
11
- SCRIPT_VERSION=" 0.36 "
11
+ SCRIPT_VERSION=" 0.37.1 "
12
12
SCRIPT_DIR=$( cd -- " $( dirname -- " ${BASH_SOURCE[0]} " ) " & > /dev/null && pwd)
13
13
CONFIG_FILE=" ${SCRIPT_DIR} /restic-backup.conf"
14
14
LOCK_FILE=" /tmp/restic-backup.lock"
@@ -73,17 +73,43 @@ import_restic_key() {
73
73
return 1
74
74
}
75
75
76
+ display_update_info () {
77
+ local component_name=" $1 "
78
+ local current_version=" $2 "
79
+ local new_version=" $3 "
80
+ local release_notes=" $4 "
81
+ echo
82
+ echo -e " ${C_BOLD}${C_YELLOW} A new version of ${component_name} is available!${C_RESET} "
83
+ printf ' %-18s %s\n' " ${C_CYAN} Current Version:${C_RESET} " " ${current_version:- -not installed-} "
84
+ printf ' %-18s %s\n' " ${C_GREEN} New Version:${C_RESET} " " $new_version "
85
+ echo
86
+ if [ -n " $release_notes " ]; then
87
+ echo -e " ${C_YELLOW} Release Notes for v${new_version} :${C_RESET} "
88
+ echo -e " ${release_notes// $' \n ' / $' \n ' } "
89
+ echo
90
+ fi
91
+ }
92
+
76
93
check_and_install_restic () {
77
94
echo -e " ${C_BOLD} --- Checking Restic Version ---${C_RESET} "
78
- if ! command -v bzip2 & > /dev/null || ! command -v curl & > /dev/null || ! command -v gpg & > /dev/null; then
79
- echo -e " ${C_RED} ERROR: 'bzip2', 'curl', and 'gpg' are required for secure auto-installation.${C_RESET} " >&2
80
- echo -e " ${C_YELLOW} On Debian based systems install with: sudo apt-get install bzip2 curl gnupg${C_RESET} " >&2
95
+ if ! command -v bzip2 & > /dev/null || ! command -v curl & > /dev/null || ! command -v gpg & > /dev/null || ! command -v jq & > /dev/null; then
96
+ echo
97
+ echo -e " ${C_RED} ERROR: 'less', 'bzip2', 'curl', 'gpg', and 'jq' are required for secure auto-installation.${C_RESET} " >&2
98
+ echo
99
+ echo -e " ${C_YELLOW} On Debian based systems install with: sudo apt-get install less bzip2 curl gnupg jq${C_RESET} " >&2
100
+ echo
81
101
exit 1
82
102
fi
103
+ local release_info
104
+ release_info=$( curl -s " https://api.github.com/repos/restic/restic/releases/latest" )
105
+ if [ -z " $release_info " ]; then
106
+ echo -e " ${C_YELLOW} Could not fetch latest restic version info from GitHub. Skipping check.${C_RESET} "
107
+ return 0
108
+ fi
83
109
local latest_version
84
- latest_version=$( curl -s " https://api.github.com/repos/restic/restic/releases/latest " | grep -o ' " tag_name": "[^"]*" ' | sed -E ' s/.*"v?([^"]+)".*/\1/ ' )
110
+ latest_version=$( echo " $release_info " | jq -r ' . tag_name | sub("^v"; "") ' )
85
111
if [ -z " $latest_version " ]; then
86
- echo -e " ${C_YELLOW} Could not fetch latest restic version from GitHub. Skipping check.${C_RESET} "
112
+ echo -e " ${C_YELLOW} Could not parse latest restic version from GitHub. Skipping check.${C_RESET} "
87
113
return 0
88
114
fi
89
115
local local_version=" "
@@ -94,7 +120,11 @@ check_and_install_restic() {
94
120
echo -e " ${C_GREEN} ✅ Restic is up to date (version $local_version ).${C_RESET} "
95
121
return 0
96
122
fi
97
- echo -e " ${C_YELLOW} A new version of Restic is available ($latest_version ). Current version is ${local_version:- not installed} .${C_RESET} "
123
+
124
+ local release_notes
125
+ release_notes=$( echo " $release_info " | jq -r ' .body' )
126
+ display_update_info " Restic" " $local_version " " $latest_version " " $release_notes "
127
+
98
128
if [ -t 1 ]; then
99
129
read -p " Would you like to download and install it? (y/n): " confirm
100
130
if [[ " ${confirm,,} " != " y" && " ${confirm,,} " != " yes" ]]; then
@@ -112,7 +142,8 @@ check_and_install_restic() {
112
142
local temp_binary temp_checksums temp_signature
113
143
temp_binary=$( mktemp) && temp_checksums=$( mktemp) && temp_signature=$( mktemp)
114
144
trap ' rm -f "$temp_binary" "$temp_checksums" "$temp_signature"' RETURN
115
- local arch=$( uname -m)
145
+ local arch
146
+ arch=$( uname -m)
116
147
local arch_suffix=" "
117
148
case " $arch " in
118
149
x86_64) arch_suffix=" amd64" ;;
@@ -157,27 +188,36 @@ check_for_script_update() {
157
188
if ! [ -t 0 ]; then
158
189
return 0
159
190
fi
160
- echo -e " ${C_BOLD} --- Checking for script updates ---${C_RESET} "
161
- local SCRIPT_URL=" https://raw.githubusercontent.com/buildplan/restic-backup-script/main/restic-backup.sh"
191
+ if ! command -v jq & > /dev/null; then
192
+ echo -e " ${C_YELLOW} Skipping script update check: 'jq' command not found.${C_RESET} "
193
+ return 0
194
+ fi
195
+ echo -e " ${C_BOLD} --- Checking for script updates ---${C_RESET} "
196
+ local SCRIPT_API_URL=" https://api.github.com/repos/buildplan/restic-backup-script/releases/latest"
197
+ local release_info
198
+ release_info=$( curl -sL -H " Cache-Control: no-cache" -H " Pragma: no-cache" " $SCRIPT_API_URL " )
162
199
local remote_version
163
- remote_version=$( curl -sL " $SCRIPT_URL " | grep ' SCRIPT_VERSION= ' | head -n1 | sed -E ' s/.*"([^"]+)".*/\1/ ' )
200
+ remote_version=$( echo " $release_info " | jq -r ' .tag_name | sub("^v"; "") ' )
164
201
if [ -z " $remote_version " ] || [[ " $remote_version " == " $SCRIPT_VERSION " ]]; then
165
202
echo -e " ${C_GREEN} ✅ Script is up to date (version $SCRIPT_VERSION ).${C_RESET} "
166
203
return 0
167
204
fi
168
- echo -e " ${C_YELLOW} A new version of this script is available ($remote_version ). You are running $SCRIPT_VERSION .${C_RESET} "
169
- read -p " Would you like to download and update now? (y/n): " confirm
170
- if [[ " ${confirm,,} " != " y" && " ${confirm,,} " != " yes" ]]; then
205
+ local release_notes
206
+ release_notes=$( echo " $release_info " | jq -r ' .body // "Could not retrieve release notes."' )
207
+ display_update_info " this script" " $SCRIPT_VERSION " " $remote_version " " $release_notes "
208
+ read -rp " Would you like to download and update now? (y/n): " confirm
209
+ if [[ ! " $confirm " =~ ^[yY]$ ]]; then
171
210
echo " Skipping update."
172
211
return 0
173
212
fi
213
+ local SCRIPT_URL=" https://raw.githubusercontent.com/buildplan/restic-backup-script/main/restic-backup.sh"
214
+ local CHECKSUM_URL=" ${SCRIPT_URL} .sha256"
174
215
local temp_script temp_checksum
175
216
temp_script=$( mktemp)
176
217
temp_checksum=$( mktemp)
177
218
trap ' rm -f "$temp_script" "$temp_checksum"' RETURN
178
- local CHECKSUM_URL=" ${SCRIPT_URL} .sha256"
179
- local curl_opts=(-sL --fail --retry 3 --retry-delay 2)
180
- echo " Downloading script update..."
219
+ local curl_opts=(-sL --fail --retry 3 --retry-delay 2 -H " Cache-Control: no-cache" -H " Pragma: no-cache" )
220
+ echo " Downloading script update from raw file URL..."
181
221
if ! curl " ${curl_opts[@]} " -o " $temp_script " " $SCRIPT_URL " ; then echo " Download failed" ; return 1; fi
182
222
if ! curl " ${curl_opts[@]} " -o " $temp_checksum " " $CHECKSUM_URL " ; then echo " Download failed" ; return 1; fi
183
223
echo " Verifying downloaded file integrity..."
@@ -272,6 +312,9 @@ display_help() {
272
312
echo -e " Verbose diff summary: ${C_GREEN} sudo $prog --verbose --diff${C_RESET} "
273
313
echo -e " Fix perms (interactive): ${C_GREEN} sudo $prog --fix-permissions --test${C_RESET} "
274
314
echo
315
+ echo -e " ${C_BOLD}${C_YELLOW} DEPENDENCIES:${C_RESET} "
316
+ echo -e " This script requires: ${C_GREEN} restic, curl, gpg, bzip2, less, jq, flock${C_RESET} "
317
+ echo
275
318
echo -e " Config: ${C_DIM}${CONFIG_FILE}${C_RESET} Log: ${C_DIM}${LOG_FILE}${C_RESET} "
276
319
echo
277
320
echo -e " For full details, see the online documentation: \e]8;;${readme_url} \a${C_CYAN} README.md${C_RESET} \e]8;;\a"
@@ -636,22 +679,21 @@ run_preflight_checks() {
636
679
# System Dependencies
637
680
if [[ " $verbosity " == " verbose" ]]; then
638
681
echo -e " \n ${C_DIM} - Checking System Dependencies${C_RESET} "
639
- printf " %-65s" " Required commands (restic, curl, flock)..."
682
+ printf " %-65s" " Required commands (restic, curl, gpg, bzip2, less, flock, jq )..."
640
683
fi
641
- local required_cmds=(restic curl flock)
684
+ local required_cmds=(restic curl flock jq less gpg bzip2 )
642
685
for cmd in " ${required_cmds[@]} " ; do
643
686
if ! command -v " $cmd " & > /dev/null; then
644
- handle_failure " Required command '$cmd ' not found." " 10"
687
+ local install_hint=" On Debian-based systems, try: sudo apt install $cmd "
688
+ case " $cmd " in
689
+ gpg) install_hint=" On Debian-based systems, try: sudo apt install gnupg" ;;
690
+ bzip2) install_hint=" On Debian-based systems, try: sudo apt install bzip2" ;;
691
+ less) install_hint=" On Debian-based systems, try: sudo apt install less" ;;
692
+ esac
693
+ handle_failure " Required command '$cmd ' not found. $install_hint " " 10"
645
694
fi
646
695
done
647
696
if [[ " $verbosity " == " verbose" ]]; then echo -e " [${C_GREEN} OK ${C_RESET} ]" ; fi
648
- if [[ " $mode " == " diff" ]]; then
649
- if [[ " $verbosity " == " verbose" ]]; then printf " %-65s" " jq command for --diff..." ; fi
650
- if ! command -v jq & > /dev/null; then
651
- handle_failure " 'jq' is required for the --diff command. Install on Debian based system with sudo apt install jq" " 10"
652
- fi
653
- if [[ " $verbosity " == " verbose" ]]; then echo -e " [${C_GREEN} OK ${C_RESET} ]" ; fi
654
- fi
655
697
# --- Performance Settings Validation ---
656
698
if [[ " $verbosity " == " verbose" ]]; then echo -e " \n ${C_DIM} - Checking Performance Settings${C_RESET} " ; fi
657
699
local numeric_vars=(" GOMAXPROCS_LIMIT" " LIMIT_THREADS" " LIMIT_UPLOAD" " SFTP_CONNECTIONS" )
0 commit comments