-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackup.sh
161 lines (133 loc) · 5.33 KB
/
backup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/bash
# Description:
# This script performs backups of specified application directories, uploads the backups to a remote location using rclone,
# and cleans up old backups both locally and remotely. It checks for changes in the directories and creates backups only if changes are found.
set -euo pipefail
trap 'echo "❌ Error occurred on line $LINENO. Exiting."' ERR
# Load environment variables from .env file
source .env
# Default log file if not specified
LOG_FILE="${LOG_FILE:-/var/log/backup_script.log}"
# Logging function
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG_FILE"
}
# Announce an action in the log
announce_action() {
local action="$1"
log "🔔 Starting action: $action"
}
# Check if required external tools are installed
check_required_tools() {
local missing_tools=()
# List of required tools
local required_tools=("rclone" "zip")
for tool in "${required_tools[@]}"; do
if ! command -v "$tool" &> /dev/null; then
missing_tools+=("$tool")
fi
done
if [ "${#missing_tools[@]}" -gt 0 ]; then
log "❌ The following required tools are missing: ${missing_tools[*]}"
log "Please install them and try again. Example installation commands:"
if [ -x "$(command -v apt)" ]; then
log "sudo apt-get install ${missing_tools[*]}"
elif [ -x "$(command -v yum)" ]; then
log "sudo yum install ${missing_tools[*]}"
elif [ -x "$(command -v pacman)" ]; then
log "sudo pacman -S ${missing_tools[*]}"
else
log "Manual installation required for: ${missing_tools[*]}"
fi
exit 1
fi
}
# Check if dependency scripts exist and are executable
check_scripts() {
for script in "$UPLOAD_SCRIPT" "$CLEANING_SCRIPT" "$STATS_SCRIPT"; do
[[ -x "$script" ]] || { log "Required script $script not found or not executable."; exit 1; }
done
}
# Function to check for changes and create backup if needed
backup_if_changed() {
local app_path=$1
local app_name
app_name=$(basename "$app_path")
local last_backup_file="${LOCAL_BACKUP_PATH}/${app_name}_last_backup.txt"
local current_backup_file="${LOCAL_BACKUP_PATH}/${app_name}_current.txt"
mkdir -p "$LOCAL_BACKUP_PATH"
# Create a file list for the current state of the directory
find "$app_path" -type f -printf '%T@ %p\n' | sort -k 2 > "$current_backup_file"
# If no previous backup file, treat it as "changes detected"
if [ ! -f "$last_backup_file" ]; then
log "📦 No previous backup for $app_path. Creating initial backup."
local archive_file="${LOCAL_BACKUP_PATH}/${app_name}_$(date +%Y%m%d%H%M%S).zip"
zip -rq "$archive_file" "$app_path"
mv "$current_backup_file" "$last_backup_file"
announce_action "Uploading new backup for $app_name"
"$UPLOAD_SCRIPT" "$archive_file"
announce_action "Cleaning up backups for $app_name"
"$CLEANING_SCRIPT" "$LOCAL_BACKUP_PATH"
else
# Compare file list hashes for performance
local hash_now
local hash_then
hash_now=$(sha256sum "$current_backup_file" | awk '{print $1}')
hash_then=$(sha256sum "$last_backup_file" | awk '{print $1}')
# If hashes don't match, create a new backup
if [ "$hash_now" != "$hash_then" ]; then
log "📂 Changes detected in $app_path. Creating new backup."
local archive_file="${LOCAL_BACKUP_PATH}/${app_name}_$(date +%Y%m%d%H%M%S).zip"
zip -rq "$archive_file" "$app_path"
mv "$current_backup_file" "$last_backup_file"
announce_action "Uploading new backup for $app_name"
"$UPLOAD_SCRIPT" "$archive_file"
announce_action "Cleaning up backups for $app_name"
"$CLEANING_SCRIPT" "$LOCAL_BACKUP_PATH"
else
log "✅ No changes in $app_path. Skipping backup."
rm -f "$current_backup_file"
fi
fi
}
# Ensure the backups match app_paths.txt
sync_backups_with_paths() {
mapfile -t current_paths < "$LIST_FILE"
# Loop through backups
for backup_file in "$LOCAL_BACKUP_PATH"/*_last_backup.txt; do
local app_name
app_name=$(basename "$backup_file" "_last_backup.txt")
# Attempt to find app path in the list
local app_path
app_path=""
for path in "${current_paths[@]}"; do
if [[ "$path" == *"$app_name"* ]]; then
app_path="$path"
break
fi
done
if [ -z "$app_path" ]; then
log "🧹 Backup for $app_name not found in $LIST_FILE. Deleting the backup."
rm -f "$backup_file"
rm -f "${LOCAL_BACKUP_PATH}/${app_name}_current.txt"
fi
done
}
# Make sure all required tools are installed
check_required_tools
# Make sure all dependency scripts are present and executable
check_scripts
# Synchronize backups with the current app paths list
sync_backups_with_paths
# Read each app path and process it
while IFS= read -r app_path; do
if [ -d "$app_path" ]; then
backup_if_changed "$app_path"
else
log "⚠️ Directory $app_path does not exist. Skipping."
fi
done < "$LIST_FILE"
# End with storage stats
announce_action "Publishing storage statistics"
"$STATS_SCRIPT"
log "🎉 Backup process complete."