File size: 8,553 Bytes
cf5db51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429d345
cf5db51
429d345
cf5db51
 
 
 
 
 
429d345
cf5db51
 
 
 
 
 
 
 
 
 
519d346
cf5db51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28975d3
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
#!/bin/bash

set -e

# Restic Service Startup Script for HuggingFace Environment
# Supports automatic backup and restore functionality

# Logging functions
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [RESTIC] $*"
}

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"
}

# Cleanup function
cleanup() {
    log "Performing cleanup operations..."
    # Kill background processes
    if [[ -n "$BACKUP_PID" ]]; then
        kill "$BACKUP_PID" 2>/dev/null || true
    fi
}

trap cleanup EXIT

# Prepare configuration file
prepare_config() {
    USER_HOME="${HOME:-/home/user}"
    local config_file="$USER_HOME/config/restic.conf"
    
    if [[ ! -f "$config_file" ]]; then
        log "Configuration file does not exist, creating from template..."
        mkdir -p "$(dirname "$config_file")"
        
        if [[ -f "$USER_HOME/config/restic.conf" ]]; then
            # Copy project configuration file and adapt paths
            cp "$USER_HOME/config/restic.conf" "$config_file"
            
            # Simple path replacement (adapt to different user environments)
            if [[ "$USER_HOME" != "/home/user" ]]; then
                sed -i "s|/home/user|$USER_HOME|g" "$config_file"
            fi
            
            log_success "Created configuration from template: $USER_HOME/config/restic.conf"
        else
            # Create basic configuration
            cat > "$config_file" << EOF
# Basic restic configuration
RESTIC_ENABLED="false"
RESTIC_REPOSITORY_PATH="$USER_HOME/data/restic-repo"
RESTIC_PASSWORD=""
RESTIC_BACKUP_PATHS="$USER_HOME"
RESTIC_BACKUP_INTERVAL="3600"
RESTIC_MAINTENANCE_INTERVAL="86400"
RESTIC_LOG_FILE="$USER_HOME/log/restic.log"
RESTIC_CACHE_DIR="$USER_HOME/.cache/restic"
RESTIC_BACKUP_ON_STARTUP="true"
RESTIC_AUTO_PRUNE="true"
RESTIC_KEEP_DAILY="7"
RESTIC_KEEP_WEEKLY="4"
RESTIC_KEEP_MONTHLY="6"
EOF
            log_success "Created basic configuration file"
        fi
    else
        log "Configuration file already exists: $config_file"
    fi
}

# Load configuration file (environment variables take precedence)
load_config() {
    local config_file="${1:-${HOME:-/home/user}/config/restic.conf}"
    
    if [[ -f "$config_file" ]]; then
        log "Loading configuration file: $config_file"
        
        # Use safer configuration loading method, remove inline comments
        local temp_config="/tmp/restic_config_$$"
        
        # Process configuration file: remove inline comments, keep valid variable assignments
        grep -E '^[^#]*=' "$config_file" | \
        sed 's/\([^"]*"[^"]*"\)[[:space:]]*#.*/\1/' | \
        sed 's/^\([^#]*\)=\(.*\)$/\1=${\1:-\2}/' > "$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"
        log "Using environment variables and default values"
    fi
}

# Create necessary directories
ensure_directories() {
    local dirs=(
        "$(dirname "$RESTIC_REPOSITORY_PATH")" 
        "$(dirname "$RESTIC_LOG_FILE")" 
        "$RESTIC_CACHE_DIR"
    )
    
    for dir in "${dirs[@]}"; do
        mkdir -p "$dir" 2>/dev/null || true
    done
}

# Setup password
setup_password() {
    if [[ -z "${RESTIC_PASSWORD:-}" ]]; then
        # Auto-generate password
        RESTIC_PASSWORD="$(openssl rand -base64 32)"
        log_success "Password auto-generated"
    fi
    
    export RESTIC_REPOSITORY="$RESTIC_REPOSITORY_PATH"
    export RESTIC_PASSWORD
    export RESTIC_CACHE_DIR
}

# Check restic command
check_restic() {
    if ! command -v restic &> /dev/null; then
        log_error "Restic command not found"
        return 1
    fi
    
    local version
    version=$(restic version | head -n1)
    log_success "Found: $version"
}

# Initialize repository
init_repository() {
    log "Checking repository..."
    
    if restic snapshots > /dev/null 2>&1; then
        log_success "Repository already exists"
    else
        log "Initializing repository..."
        if restic init; then
            log_success "Repository initialized successfully"
        else
            log_error "Repository initialization failed"
            return 1
        fi
    fi
}

# Find backup script path
find_backup_script() {
    local script_paths=(
        "$(dirname "$0")/../utils/restic-backup.sh"
        "./script/utils/restic-backup.sh"
        "./restic-backup.sh"
    )
    
    for script_path in "${script_paths[@]}"; do
        if [[ -f "$script_path" ]]; then
            echo "$script_path"
            return 0
        fi
    done
    
    log_error "restic-backup.sh script not found"
    return 1
}

# Perform backup (using independent backup script)
perform_backup() {
    local backup_script
    if ! backup_script=$(find_backup_script); then
        log_error "Cannot find backup script, falling back to built-in backup functionality"
        return 1
    fi
    
    log "Using backup script: $backup_script"
    
    # Use independent backup script
    bash "$backup_script" -c "${config_file:-${HOME:-/home/user}/config/restic.conf}"
    return $?
}

# Maintenance tasks
run_maintenance() {
    log "Starting maintenance tasks..."
    
    # Check repository
    log "Checking repository integrity..."
    if restic check; then
        log_success "Repository check passed"
    else
        log_error "Repository check failed"
        return 1
    fi
    
    # Clean old snapshots
    log "Cleaning old snapshots..."
    local args=("forget")
    
    [[ -n "${RESTIC_KEEP_HOURLY:-}" ]] && args+=("--keep-hourly" "${RESTIC_KEEP_HOURLY}")
    [[ -n "${RESTIC_KEEP_DAILY:-}" ]] && args+=("--keep-daily" "${RESTIC_KEEP_DAILY}")
    [[ -n "${RESTIC_KEEP_WEEKLY:-}" ]] && args+=("--keep-weekly" "${RESTIC_KEEP_WEEKLY}")
    [[ -n "${RESTIC_KEEP_MONTHLY:-}" ]] && args+=("--keep-monthly" "${RESTIC_KEEP_MONTHLY}")
    [[ "${RESTIC_AUTO_PRUNE:-true}" == "true" ]] && args+=("--prune")
    
    if restic "${args[@]}"; then
        log_success "Cleanup completed"
    else
        log_warn "Cleanup failed"
    fi
    
    log_success "Maintenance tasks completed"
}

# Main service loop
main_service() {
    log "Starting restic service..."
    
    # Backup on startup
    if [[ "${RESTIC_BACKUP_ON_STARTUP:-true}" == "true" ]]; then
        perform_backup
    fi
    
    # Main loop
    local last_backup=$(date +%s)
    local last_maintenance=$(date +%s)
    
    while true; do
        local current_time=$(date +%s)
        
        # Check if backup is needed
        if [[ $((current_time - last_backup)) -ge "${RESTIC_BACKUP_INTERVAL:-3600}" ]]; then
            if perform_backup; then
                last_backup=$current_time
            fi
        fi
        
        # Check if maintenance is needed
        if [[ $((current_time - last_maintenance)) -ge "${RESTIC_MAINTENANCE_INTERVAL:-86400}" ]]; then
            if run_maintenance; then
                last_maintenance=$current_time
            fi
        fi
        
        # Wait 60 seconds
        sleep 60
    done
}

# Main program
main() {
    log "======= Restic Service Startup ======="
    
    # 1. Prepare configuration file (if it doesn't exist)
    prepare_config
    
    # 2. Load configuration file
    local config_file="${1:-${HOME:-/home/user}/config/restic.conf}"
    load_config "$config_file"
    
    # 3. Create necessary directories
    ensure_directories
    
    # 4. Check if enabled
    if [[ "${RESTIC_ENABLED:-false}" != "true" ]]; then
        log_warn "Restic service is disabled"
        log "To enable: set RESTIC_ENABLED=true in environment variables or configuration file"
        exit 0
    fi
    
    # 5. Check dependencies and setup environment
    check_restic || exit 1
    setup_password
    
    # Display configuration
    log "Backup service configuration:"
    log "  Repository path: $RESTIC_REPOSITORY_PATH"
    log "  Backup paths: $RESTIC_BACKUP_PATHS"
    log "  Backup interval: ${RESTIC_BACKUP_INTERVAL:-3600} seconds"
    log "  Maintenance interval: ${RESTIC_MAINTENANCE_INTERVAL:-86400} seconds"
    log "  Backup on startup: ${RESTIC_BACKUP_ON_STARTUP:-true}"
    
    # Initialize repository
    init_repository || exit 1
    
    # Start service
    main_service
}

# Run main program
main "$@"