File size: 10,358 Bytes
cf5db51 |
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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
#!/bin/bash
set -e
# Restic Backup Utility Script
# Provides independent backup functionality, can be called by other scripts
# Logging functions
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [BACKUP] $*"
}
log_success() {
echo -e "\033[32m[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $*\033[0m"
}
log_error() {
echo -e "\033[31m[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*\033[0m"
}
log_warn() {
echo -e "\033[33m[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $*\033[0m"
}
# Display usage instructions
show_usage() {
cat << EOF
Usage: $0 [options] [paths...]
Options:
-c, --config FILE Specify configuration file path
-r, --repository DIR Specify repository path (overrides config file)
-p, --password PASS Specify password (overrides config file)
-t, --tag TAG Add backup tag (can be used multiple times)
-e, --exclude PATTERN Add exclude pattern (can be used multiple times)
--compression MODE Compression mode: off, fastest, auto, better, max (default: auto)
-v, --verbose Enable verbose output
-n, --dry-run Only show operations to be executed
-h, --help Show this help message
Compression mode explanation:
off - No compression (fastest backup speed)
fastest - Fastest compression (minimal CPU usage)
auto - Auto compression (default, balanced speed and compression ratio)
better - Better compression (more CPU, better compression ratio)
max - Maximum compression (highest CPU, best compression ratio)
Examples:
$0 # Backup using default configuration
$0 /home/user/data # Backup specified path
$0 -t "manual" -v /important # Verbose backup with tag
$0 --compression max -v # Verbose backup with maximum compression
$0 -c custom.conf -n # Dry run with custom configuration
EOF
}
# Load configuration file
load_config() {
local config_file="$1"
if [[ -f "$config_file" ]]; then
log "Loading configuration file: $config_file"
# Use safe configuration loading method
local temp_config="/tmp/restic_backup_config_$$"
sed 's/^\([^#]*\)=\(.*\)$/\1=${\1:-\2}/' "$config_file" > "$temp_config"
source "$temp_config"
rm -f "$temp_config"
log_success "Configuration loaded (environment variables take precedence)"
else
log_warn "Configuration file does not exist: $config_file"
fi
}
# Set environment variables
setup_environment() {
# Check necessary configuration variables
if [[ -z "$RESTIC_REPOSITORY_PATH" ]]; then
log_error "RESTIC_REPOSITORY_PATH not set, please check configuration file or environment variables"
return 1
fi
# Check password setting
if [[ -z "${RESTIC_PASSWORD:-}" ]]; then
log_error "RESTIC_PASSWORD not set, please check configuration file or environment variables"
return 1
fi
log "Using password from environment variables"
# Export environment variables
export RESTIC_REPOSITORY="$RESTIC_REPOSITORY_PATH"
export RESTIC_PASSWORD
export RESTIC_CACHE_DIR
# Set performance tuning environment variables (read from config file or environment variables)
[[ -n "$RESTIC_MAX_PROCS" ]] && export GOMAXPROCS="$RESTIC_MAX_PROCS"
[[ -n "$RESTIC_TEMP_DIR" ]] && export TMPDIR="$RESTIC_TEMP_DIR"
[[ -n "$RESTIC_FEATURES" ]] && export RESTIC_FEATURES
# Check restic command
if ! command -v restic &> /dev/null; then
log_error "restic command not found"
return 1
fi
log_success "Environment setup completed"
}
# Validate backup paths
validate_paths() {
local paths=("$@")
local valid_paths=()
for path in "${paths[@]}"; do
if [[ -e "$path" ]]; then
valid_paths+=("$path")
log "Valid path: $path"
else
log_warn "Path does not exist: $path"
fi
done
if [[ ${#valid_paths[@]} -eq 0 ]]; then
log_error "No valid backup paths"
return 1
fi
# Store valid paths in global variable
VALIDATED_PATHS=("${valid_paths[@]}")
return 0
}
# Perform backup
perform_backup() {
local dry_run="$1"
shift
local backup_paths=("$@")
log "Starting backup operation..."
# If no paths specified, use paths from configuration
if [[ ${#backup_paths[@]} -eq 0 ]]; then
IFS=':' read -ra backup_paths <<< "$RESTIC_BACKUP_PATHS"
fi
# Validate paths
if ! validate_paths "${backup_paths[@]}"; then
return 1
fi
# Build backup command arguments
local args=("backup")
# Add exclude patterns
if [[ -n "$RESTIC_EXCLUDE_PATTERNS" ]]; then
IFS=',' read -ra patterns <<< "$RESTIC_EXCLUDE_PATTERNS"
for pattern in "${patterns[@]}"; do
args+=("--exclude" "$pattern")
done
fi
# Add extra exclude patterns (from command line)
for exclude in "${EXTRA_EXCLUDES[@]}"; do
args+=("--exclude" "$exclude")
done
# Add tags
if [[ -n "$RESTIC_BACKUP_TAG" ]]; then
IFS=',' read -ra tags <<< "$RESTIC_BACKUP_TAG"
for tag in "${tags[@]}"; do
args+=("--tag" "$tag")
done
fi
# Add extra tags (from command line)
for tag in "${EXTRA_TAGS[@]}"; do
args+=("--tag" "$tag")
done
# Add options
[[ "$RESTIC_VERBOSE" == "true" ]] && args+=("--verbose")
# Add compression option
args+=("--compression" "$RESTIC_COMPRESSION")
# New: Performance tuning options (prioritize RESTIC_READ_CONCURRENCY, otherwise use RESTIC_PARALLEL_UPLOADS)
if [[ -n "$RESTIC_READ_CONCURRENCY" ]]; then
args+=("--read-concurrency" "$RESTIC_READ_CONCURRENCY")
elif [[ -n "$RESTIC_PARALLEL_UPLOADS" ]]; then
args+=("--read-concurrency" "$RESTIC_PARALLEL_UPLOADS")
fi
[[ -n "$RESTIC_PACK_SIZE" ]] && args+=("--pack-size" "$RESTIC_PACK_SIZE")
[[ "$RESTIC_NO_SCAN" == "true" ]] && args+=("--no-scan")
[[ "$RESTIC_EXTRA_VERIFY" == "false" ]] && args+=("--no-extra-verify")
[[ "$RESTIC_NO_CACHE" == "true" ]] && args+=("--no-cache")
# New: Backend connection configuration
if [[ -n "$RESTIC_BACKEND_CONNECTIONS" ]]; then
# Auto-detect backend type
if [[ "$RESTIC_REPOSITORY_PATH" =~ ^s3: ]]; then
args+=("-o" "s3.connections=$RESTIC_BACKEND_CONNECTIONS")
elif [[ "$RESTIC_REPOSITORY_PATH" =~ ^rest: ]]; then
args+=("-o" "rest.connections=$RESTIC_BACKEND_CONNECTIONS")
elif [[ "$RESTIC_REPOSITORY_PATH" =~ ^sftp: ]]; then
args+=("-o" "sftp.connections=$RESTIC_BACKEND_CONNECTIONS")
else
# Local backend
args+=("-o" "local.connections=$RESTIC_BACKEND_CONNECTIONS")
fi
fi
# Add paths
args+=("${VALIDATED_PATHS[@]}")
log "Executing command: restic ${args[*]}"
if [[ "$dry_run" == "true" ]]; then
log_warn "Dry run mode - actual backup not executed"
return 0
fi
# Execute backup
if restic "${args[@]}"; then
log_success "Backup completed successfully"
return 0
else
log_error "Backup failed"
return 1
fi
}
# Main function
main() {
# Parse command line arguments
local config_file=""
local dry_run="false"
local backup_paths=()
local EXTRA_TAGS=()
local EXTRA_EXCLUDES=()
while [[ $# -gt 0 ]]; do
case $1 in
-c|--config)
config_file="$2"
shift 2
;;
-r|--repository)
RESTIC_REPOSITORY_PATH="$2"
shift 2
;;
-p|--password)
RESTIC_PASSWORD="$2"
shift 2
;;
-t|--tag)
EXTRA_TAGS+=("$2")
shift 2
;;
-e|--exclude)
EXTRA_EXCLUDES+=("$2")
shift 2
;;
--compression)
RESTIC_COMPRESSION="$2"
shift 2
;;
-v|--verbose)
RESTIC_VERBOSE="true"
shift
;;
-n|--dry-run)
dry_run="true"
shift
;;
-h|--help)
show_usage
exit 0
;;
-*)
log_error "Unknown option: $1"
show_usage
exit 1
;;
*)
backup_paths+=("$1")
shift
;;
esac
done
log "======= Restic Backup Tool ======="
# Load configuration file
if [[ -n "$config_file" ]]; then
load_config "$config_file"
elif [[ -f "${HOME:-/home/user}/config/restic.conf" ]]; then
load_config "${HOME:-/home/user}/config/restic.conf"
fi
# Setup environment
if ! setup_environment; then
exit 1
fi
# Display configuration information
log "Backup configuration:"
log " Repository path: $RESTIC_REPOSITORY_PATH"
log " Cache directory: $RESTIC_CACHE_DIR"
log " Compression mode: $RESTIC_COMPRESSION"
log " Dry run mode: $dry_run"
log " Performance tuning:"
log " - Backend connections: ${RESTIC_BACKEND_CONNECTIONS:-default}"
log " - CPU core limit: ${RESTIC_MAX_PROCS:-all available}"
log " - Read concurrency: ${RESTIC_READ_CONCURRENCY:-default}"
log " - Pack size: ${RESTIC_PACK_SIZE:-16}MiB"
log " - Disable scan: ${RESTIC_NO_SCAN:-false}"
log " - Extra verify: ${RESTIC_EXTRA_VERIFY:-true}"
log " - Disable cache: ${RESTIC_NO_CACHE:-false}"
[[ -n "$RESTIC_TEMP_DIR" ]] && log " - Temp directory: $RESTIC_TEMP_DIR"
[[ -n "$RESTIC_FEATURES" ]] && log " - Feature flags: $RESTIC_FEATURES"
[[ ${#EXTRA_TAGS[@]} -gt 0 ]] && log " Extra tags: ${EXTRA_TAGS[*]}"
[[ ${#EXTRA_EXCLUDES[@]} -gt 0 ]] && log " Extra excludes: ${EXTRA_EXCLUDES[*]}"
# Execute backup
perform_backup "$dry_run" "${backup_paths[@]}"
}
# If script is executed directly (not sourced)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi |