mirror of
				https://github.com/FPGArtktic/GnuRAMage.git
				synced 2025-11-04 04:28:58 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			625 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			625 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
#!/bin/bash
 | 
						|
# GnuRAMage: Advanced RAM Disk Synchronization Tool
 | 
						|
# Version: 1.0.0
 | 
						|
#
 | 
						|
# Copyright (C) 2025 Mateusz Okulanis
 | 
						|
# Email: FPGArtktic@outlook.com
 | 
						|
#
 | 
						|
# This program is free software: you can redistribute it and/or modify
 | 
						|
# it under the terms of the GNU General Public License as published by
 | 
						|
# the Free Software Foundation, either version 3 of the License, or
 | 
						|
# (at your option) any later version.
 | 
						|
#
 | 
						|
# This program is distributed in the hope that it will be useful,
 | 
						|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
# GNU General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License
 | 
						|
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
# Default values
 | 
						|
CONFIG_FILE="GnuRAMage.ini"
 | 
						|
DRY_RUN=false
 | 
						|
VERBOSE=false
 | 
						|
LOGS_FILE=""
 | 
						|
ERRORS_LOG_FILE=""
 | 
						|
SCRIPT_GEN_ONLY=false
 | 
						|
ONE_TIME_MODE=false
 | 
						|
SYNC_INTERVAL=180  # Default sync interval in seconds (3 minutes)
 | 
						|
LOG_LEVEL="INFO"   # Default log level: ERROR, WARN, INFO, DEBUG
 | 
						|
VERIFY_CHECKSUMS=false
 | 
						|
DEFAULT_SOURCE_DIR=""
 | 
						|
DEFAULT_RAMDISK_DIR=""
 | 
						|
 | 
						|
# Get script directory
 | 
						|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
						|
 | 
						|
# File paths for generated scripts
 | 
						|
RSYNC_SCRIPT="${SCRIPT_DIR}/gramage_sync_to_disk.sh"
 | 
						|
CP_SCRIPT="${SCRIPT_DIR}/gramage_copy_to_ram.sh"
 | 
						|
 | 
						|
# Statistics for report
 | 
						|
TOTAL_FILES_COPIED=0
 | 
						|
TOTAL_FILES_SYNCED=0
 | 
						|
START_TIME=$(date +%s)
 | 
						|
 | 
						|
# Variables for cleanup
 | 
						|
CLEANUP_NEEDED=false
 | 
						|
TRAP_REGISTERED=false
 | 
						|
 | 
						|
# Print usage information
 | 
						|
print_usage() {
 | 
						|
    echo "Usage: $0 [OPTIONS]"
 | 
						|
    echo "GnuRAMage: Advanced RAM Disk Synchronization Tool"
 | 
						|
    echo ""
 | 
						|
    echo "Options:"
 | 
						|
    echo "  --config <file>     Path to the configuration file (default: GnuRAMage.ini)"
 | 
						|
    echo "  --dry-run           Simulate operations without actually copying/syncing files"
 | 
						|
    echo "  --verbose, -v       Display more detailed information about operations"
 | 
						|
    echo "  --logs <file>       Write logs to the specified file (TXT or JSON)"
 | 
						|
    echo "  --errors-log <file> Write error logs to the specified file (TXT or JSON)"
 | 
						|
    echo "  --script-gen-only   Generate scripts only, don't start synchronization"
 | 
						|
    echo "  --one-time          Run only one synchronization cycle (no loop)"
 | 
						|
    echo "  --help              Display this help message and exit"
 | 
						|
    echo ""
 | 
						|
}
 | 
						|
 | 
						|
# Log levels
 | 
						|
LOG_LEVEL_ERROR=0
 | 
						|
LOG_LEVEL_WARN=1
 | 
						|
LOG_LEVEL_INFO=2
 | 
						|
LOG_LEVEL_DEBUG=3
 | 
						|
 | 
						|
# Function to convert log level string to numeric value
 | 
						|
get_log_level_value() {
 | 
						|
    case "$1" in
 | 
						|
        "ERROR") echo $LOG_LEVEL_ERROR ;;
 | 
						|
        "WARN")  echo $LOG_LEVEL_WARN ;;
 | 
						|
        "INFO")  echo $LOG_LEVEL_INFO ;;
 | 
						|
        "DEBUG") echo $LOG_LEVEL_DEBUG ;;
 | 
						|
        *)       echo $LOG_LEVEL_INFO ;;  # Default to INFO
 | 
						|
    esac
 | 
						|
}
 | 
						|
 | 
						|
# Parse command line arguments
 | 
						|
parse_arguments() {
 | 
						|
    while [[ $# -gt 0 ]]; do
 | 
						|
        case $1 in
 | 
						|
            --config)
 | 
						|
                CONFIG_FILE="$2"
 | 
						|
                shift 2
 | 
						|
                ;;
 | 
						|
            --dry-run)
 | 
						|
                DRY_RUN=true
 | 
						|
                shift
 | 
						|
                ;;
 | 
						|
            --verbose|-v)
 | 
						|
                VERBOSE=true
 | 
						|
                shift
 | 
						|
                ;;
 | 
						|
            --logs)
 | 
						|
                LOGS_FILE="$2"
 | 
						|
                shift 2
 | 
						|
                ;;
 | 
						|
            --errors-log)
 | 
						|
                ERRORS_LOG_FILE="$2"
 | 
						|
                shift 2
 | 
						|
                ;;
 | 
						|
            --script-gen-only)
 | 
						|
                SCRIPT_GEN_ONLY=true
 | 
						|
                shift
 | 
						|
                ;;
 | 
						|
            --one-time)
 | 
						|
                ONE_TIME_MODE=true
 | 
						|
                shift
 | 
						|
                ;;
 | 
						|
            --help)
 | 
						|
                print_usage
 | 
						|
                exit 0
 | 
						|
                ;;
 | 
						|
            *)
 | 
						|
                log_error "Unknown option: $1"
 | 
						|
                print_usage
 | 
						|
                exit 1
 | 
						|
                ;;
 | 
						|
        esac
 | 
						|
    done
 | 
						|
}
 | 
						|
 | 
						|
# Get current timestamp
 | 
						|
get_timestamp() {
 | 
						|
    date "+%Y-%m-%d %H:%M:%S"
 | 
						|
}
 | 
						|
 | 
						|
# Log function with levels
 | 
						|
log() {
 | 
						|
    local level="$1"
 | 
						|
    local message="$2"
 | 
						|
    local timestamp=$(get_timestamp)
 | 
						|
    local numeric_level=$(get_log_level_value "$level")
 | 
						|
    local current_level=$(get_log_level_value "$LOG_LEVEL")
 | 
						|
    
 | 
						|
    # Only log if the message level is less than or equal to the current log level
 | 
						|
    if [ $numeric_level -le $current_level ]; then
 | 
						|
        local log_message="[$timestamp] [$level] $message"
 | 
						|
        
 | 
						|
        # If not in dry-run mode or if it's an error, show on console
 | 
						|
        if ! $DRY_RUN || [ "$level" = "ERROR" ]; then
 | 
						|
            echo "$log_message"
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Log to file if specified
 | 
						|
        if [ -n "$LOGS_FILE" ]; then
 | 
						|
            echo "$log_message" >> "$LOGS_FILE"
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Log errors to error log file if specified
 | 
						|
        if [ "$level" = "ERROR" ] && [ -n "$ERRORS_LOG_FILE" ]; then
 | 
						|
            echo "$log_message" >> "$ERRORS_LOG_FILE"
 | 
						|
        elif [ "$level" = "WARN" ] && [ -n "$ERRORS_LOG_FILE" ]; then
 | 
						|
            echo "$log_message" >> "$ERRORS_LOG_FILE"
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Shorthand logging functions
 | 
						|
log_error() {
 | 
						|
    log "ERROR" "$1"
 | 
						|
}
 | 
						|
 | 
						|
log_warn() {
 | 
						|
    log "WARN" "$1"
 | 
						|
}
 | 
						|
 | 
						|
log_info() {
 | 
						|
    log "INFO" "$1"
 | 
						|
}
 | 
						|
 | 
						|
log_debug() {
 | 
						|
    log "DEBUG" "$1"
 | 
						|
}
 | 
						|
 | 
						|
# Check if rsync is installed
 | 
						|
check_rsync() {
 | 
						|
    if ! command -v rsync &> /dev/null; then
 | 
						|
        log_error "rsync is not installed. Please install it and try again."
 | 
						|
        exit 1
 | 
						|
    else
 | 
						|
        log_debug "rsync is installed."
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Read and parse INI file
 | 
						|
parse_config_file() {
 | 
						|
    if [ ! -f "$CONFIG_FILE" ]; then
 | 
						|
        # Check if config file exists in script directory
 | 
						|
        if [ -f "$SCRIPT_DIR/$CONFIG_FILE" ]; then
 | 
						|
            CONFIG_FILE="$SCRIPT_DIR/$CONFIG_FILE"
 | 
						|
            log_debug "Using configuration file from script directory: $CONFIG_FILE"
 | 
						|
        else
 | 
						|
            log_error "Configuration file '$CONFIG_FILE' not found."
 | 
						|
            exit 1
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
    
 | 
						|
    log_info "Reading configuration from: $CONFIG_FILE"
 | 
						|
    
 | 
						|
    # Read general settings
 | 
						|
    if grep -q "^\[SETTINGS\]" "$CONFIG_FILE"; then
 | 
						|
        # Read sync interval
 | 
						|
        if grep -q "^sync_interval" "$CONFIG_FILE"; then
 | 
						|
            SYNC_INTERVAL=$(grep "^sync_interval" "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
 | 
						|
            log_debug "Set sync interval to $SYNC_INTERVAL seconds"
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Read log level
 | 
						|
        if grep -q "^log_level" "$CONFIG_FILE"; then
 | 
						|
            LOG_LEVEL=$(grep "^log_level" "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ' | tr '[:lower:]' '[:upper:]')
 | 
						|
            log_debug "Set log level to $LOG_LEVEL"
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Read verify checksums setting
 | 
						|
        if grep -q "^verify_checksums" "$CONFIG_FILE"; then
 | 
						|
            verify_checksums_val=$(grep "^verify_checksums" "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ' | tr '[:upper:]' '[:lower:]')
 | 
						|
            if [ "$verify_checksums_val" = "true" ] || [ "$verify_checksums_val" = "1" ] || [ "$verify_checksums_val" = "yes" ]; then
 | 
						|
                VERIFY_CHECKSUMS=true
 | 
						|
                log_debug "Checksum verification enabled"
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
    
 | 
						|
    # Read source and destination directories
 | 
						|
    if grep -q "^\[DIRECTORIES\]" "$CONFIG_FILE"; then
 | 
						|
        # Read source directory
 | 
						|
        if grep -q "^source_dir" "$CONFIG_FILE"; then
 | 
						|
            DEFAULT_SOURCE_DIR=$(grep "^source_dir" "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
 | 
						|
            log_debug "Source directory: $DEFAULT_SOURCE_DIR"
 | 
						|
        else
 | 
						|
            log_error "Source directory not specified in config file"
 | 
						|
            exit 1
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Read ramdisk directory
 | 
						|
        if grep -q "^ramdisk_dir" "$CONFIG_FILE"; then
 | 
						|
            DEFAULT_RAMDISK_DIR=$(grep "^ramdisk_dir" "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
 | 
						|
            log_debug "RAM disk directory: $DEFAULT_RAMDISK_DIR"
 | 
						|
        else
 | 
						|
            log_error "RAM disk directory not specified in config file"
 | 
						|
            exit 1
 | 
						|
        fi
 | 
						|
    else
 | 
						|
        log_error "DIRECTORIES section not found in config file"
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Check and create target directories if they don't exist
 | 
						|
check_directories() {
 | 
						|
    log_info "Checking target directories"
 | 
						|
    
 | 
						|
    if [ ! -d "$DEFAULT_SOURCE_DIR" ]; then
 | 
						|
        log_error "Source directory '$DEFAULT_SOURCE_DIR' does not exist"
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
    
 | 
						|
    if [ ! -d "$DEFAULT_RAMDISK_DIR" ]; then
 | 
						|
        log_info "Creating RAM disk directory: $DEFAULT_RAMDISK_DIR"
 | 
						|
        if ! $DRY_RUN; then
 | 
						|
            mkdir -p "$DEFAULT_RAMDISK_DIR"
 | 
						|
            if [ $? -ne 0 ]; then
 | 
						|
                log_error "Failed to create RAM disk directory: $DEFAULT_RAMDISK_DIR"
 | 
						|
                exit 1
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Generate the rsync script (from RAM disk to hard disk)
 | 
						|
generate_rsync_script() {
 | 
						|
    log_info "Generating rsync script: $RSYNC_SCRIPT"
 | 
						|
    
 | 
						|
    if ! $DRY_RUN; then
 | 
						|
        cat > "$RSYNC_SCRIPT" << EOF
 | 
						|
#!/bin/bash
 | 
						|
# Auto-generated rsync script for RAM disk synchronization
 | 
						|
# Created by GnuRAMage: Advanced RAM Disk Synchronization Tool on $(date)
 | 
						|
 | 
						|
# Options explanation:
 | 
						|
# -a: archive mode (recursive, preserves permissions, timestamps, etc.)
 | 
						|
# -v: verbose (if --verbose is specified)
 | 
						|
# --delete: remove files in destination that don't exist in source
 | 
						|
# --exclude: exclude patterns from config
 | 
						|
# Check if required variables are set and directories exist
 | 
						|
if [ -z "$DEFAULT_RAMDISK_DIR" ]; then
 | 
						|
    echo "[ERROR] Source or RAM disk directory variable is empty! Aborting."
 | 
						|
    exit 3
 | 
						|
fi
 | 
						|
if [ ! -d "$DEFAULT_RAMDISK_DIR" ]; then
 | 
						|
    echo "[ERROR] Source or RAM disk directory does not exist! Aborting."
 | 
						|
    exit 4
 | 
						|
fi
 | 
						|
if [ ! "\$(ls -A "$DEFAULT_RAMDISK_DIR" 2>/dev/null)" ]; then
 | 
						|
    echo "[WARNING] RAM disk directory is empty!"
 | 
						|
fi
 | 
						|
 | 
						|
# Create directories if they don't exist
 | 
						|
mkdir -p "$DEFAULT_SOURCE_DIR"
 | 
						|
 | 
						|
# Build rsync command as array
 | 
						|
RSYNC_CMD=(rsync -a)
 | 
						|
 | 
						|
# Add options based on settings
 | 
						|
if [ "$1" = "--verbose" ]; then
 | 
						|
    RSYNC_CMD+=( -v )
 | 
						|
fi
 | 
						|
 | 
						|
if [ "$1" = "--dry-run" ]; then
 | 
						|
    RSYNC_CMD+=( --dry-run )
 | 
						|
fi
 | 
						|
 | 
						|
EOF
 | 
						|
        # Add exclude patterns from INI if they exist, all in one line
 | 
						|
        if grep -q "^\[EXCLUDE\]" "$CONFIG_FILE"; then
 | 
						|
            exclude_patterns=$(sed -n '/^\[EXCLUDE\]/,/^\[/p' "$CONFIG_FILE" | grep -v "^\[" | grep -v "^;" | grep -v "^$" | grep -v '^#' | grep -v -i 'pattern' | grep -v -i 'exclude' | grep -v -i 'synchronization' | grep -v -i 'line' | grep -v -i 'format')
 | 
						|
            for pattern in $exclude_patterns; do
 | 
						|
                echo "RSYNC_CMD+=( --exclude='$pattern' )" >> "$RSYNC_SCRIPT"
 | 
						|
            done
 | 
						|
        fi
 | 
						|
        echo "RSYNC_CMD+=( --delete \"$DEFAULT_RAMDISK_DIR/\" \"$DEFAULT_SOURCE_DIR/\" )" >> "$RSYNC_SCRIPT"
 | 
						|
        echo '' >> "$RSYNC_SCRIPT"
 | 
						|
        echo '#echo "[INFO] Rsync command: ${RSYNC_CMD[*]}"' >> "$RSYNC_SCRIPT"
 | 
						|
        echo '# Execute rsync command' >> "$RSYNC_SCRIPT"
 | 
						|
        echo '"${RSYNC_CMD[@]}"' >> "$RSYNC_SCRIPT"
 | 
						|
        
 | 
						|
        # Make the script executable
 | 
						|
        chmod +x "$RSYNC_SCRIPT"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    log_debug "Rsync script generated successfully"
 | 
						|
}
 | 
						|
 | 
						|
# Generate the cp script (from hard disk to RAM disk)
 | 
						|
generate_cp_script() {
 | 
						|
    log_info "Generating cp script: $CP_SCRIPT"
 | 
						|
    
 | 
						|
    if ! $DRY_RUN; then
 | 
						|
        cat > "$CP_SCRIPT" << EOF
 | 
						|
#!/bin/bash
 | 
						|
# Auto-generated cp script for RAM disk synchronization
 | 
						|
# Created by GnuRAMage: Advanced RAM Disk Synchronization Tool on $(date)
 | 
						|
 | 
						|
# Create directories if they don't exist
 | 
						|
mkdir -p "$DEFAULT_RAMDISK_DIR"
 | 
						|
 | 
						|
# If verbose flag is set, add -v option to cp
 | 
						|
CP_CMD="cp -a"
 | 
						|
if [ "\$1" = "--verbose" ]; then
 | 
						|
    CP_CMD="cp -av"
 | 
						|
fi
 | 
						|
 | 
						|
# If dry-run flag is set, just echo what would be done
 | 
						|
if [ "\$1" = "--dry-run" ]; then
 | 
						|
    echo "Would copy files from $DEFAULT_SOURCE_DIR to $DEFAULT_RAMDISK_DIR"
 | 
						|
    exit 0
 | 
						|
fi
 | 
						|
 | 
						|
# Copy files from source to RAM disk
 | 
						|
\$CP_CMD "$DEFAULT_SOURCE_DIR"* "$DEFAULT_RAMDISK_DIR" 2>/dev/null
 | 
						|
 | 
						|
# Handle case where source directory is empty or no files match
 | 
						|
if [ \$? -ne 0 ]; then
 | 
						|
    # Check if source directory exists and is not empty
 | 
						|
    if [ -d "$DEFAULT_SOURCE_DIR" ] && [ "\$(ls -A "$DEFAULT_SOURCE_DIR" 2>/dev/null)" ]; then
 | 
						|
        echo "Error: Failed to copy files to RAM disk"
 | 
						|
        exit 1
 | 
						|
    else
 | 
						|
        # Create an empty file to mark successful execution even if no files were copied
 | 
						|
        touch "$DEFAULT_RAMDISK_DIR/.rsyncignore"
 | 
						|
    fi
 | 
						|
fi
 | 
						|
 | 
						|
exit 0
 | 
						|
EOF
 | 
						|
 | 
						|
        # Make the script executable
 | 
						|
        chmod +x "$CP_SCRIPT"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    log_debug "Copy script generated successfully"
 | 
						|
}
 | 
						|
 | 
						|
# Execute cp script to copy from hard disk to RAM disk
 | 
						|
execute_cp_script() {
 | 
						|
    log_info "Executing copy to RAM disk script"
 | 
						|
    
 | 
						|
    local verbose_flag=""
 | 
						|
    if $VERBOSE; then
 | 
						|
        verbose_flag="--verbose"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    local dry_run_flag=""
 | 
						|
    if $DRY_RUN; then
 | 
						|
        dry_run_flag="--dry-run"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    if ! $DRY_RUN; then
 | 
						|
        if $VERBOSE; then
 | 
						|
            "$CP_SCRIPT" "$verbose_flag"
 | 
						|
        else
 | 
						|
            "$CP_SCRIPT" > /dev/null
 | 
						|
        fi
 | 
						|
        
 | 
						|
        if [ $? -ne 0 ]; then
 | 
						|
            log_error "Failed to copy files to RAM disk"
 | 
						|
            return 1
 | 
						|
        else
 | 
						|
            log_info "Files copied to RAM disk successfully"
 | 
						|
            TOTAL_FILES_COPIED=$(find "$DEFAULT_RAMDISK_DIR" -type f | wc -l)
 | 
						|
            log_debug "Total files copied: $TOTAL_FILES_COPIED"
 | 
						|
        fi
 | 
						|
    else
 | 
						|
        log_info "Dry run: Would execute copy script"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    return 0
 | 
						|
}
 | 
						|
 | 
						|
# Execute rsync script to sync from RAM disk to hard disk
 | 
						|
execute_rsync_script() {
 | 
						|
    log_info "Executing rsync to hard disk script"
 | 
						|
    
 | 
						|
    local verbose_flag=""
 | 
						|
    if $VERBOSE; then
 | 
						|
        verbose_flag="--verbose"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    local dry_run_flag=""
 | 
						|
    if $DRY_RUN; then
 | 
						|
        dry_run_flag="--dry-run"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    if ! $DRY_RUN; then
 | 
						|
        if $VERBOSE; then
 | 
						|
            "$RSYNC_SCRIPT" "$verbose_flag" 2> /tmp/rsync_error.log
 | 
						|
        else
 | 
						|
            "$RSYNC_SCRIPT" > /dev/null 2> /tmp/rsync_error.log
 | 
						|
        fi
 | 
						|
        
 | 
						|
        local rsync_status=$?
 | 
						|
        if [ $rsync_status -ne 0 ]; then
 | 
						|
            local error_msg=$(cat /tmp/rsync_error.log)
 | 
						|
            log_error "Failed to sync files to hard disk: Error code $rsync_status"
 | 
						|
            log_error "Rsync error: $error_msg"
 | 
						|
            # Add rsync errors to the error log as well
 | 
						|
            if [ -n "$ERRORS_LOG_FILE" ]; then
 | 
						|
                echo "[$(get_timestamp)] [ERROR] Rsync error: $error_msg" >> "$ERRORS_LOG_FILE"
 | 
						|
            fi
 | 
						|
            rm -f /tmp/rsync_error.log
 | 
						|
            return 1
 | 
						|
        else
 | 
						|
            log_info "Files synced to hard disk successfully"
 | 
						|
            TOTAL_FILES_SYNCED=$((TOTAL_FILES_SYNCED + 1))
 | 
						|
            log_debug "Total sync operations: $TOTAL_FILES_SYNCED"
 | 
						|
            rm -f /tmp/rsync_error.log
 | 
						|
        fi
 | 
						|
    else
 | 
						|
        log_info "Dry run: Would execute rsync script"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    return 0
 | 
						|
}
 | 
						|
 | 
						|
# Wait for key press with timeout
 | 
						|
wait_for_key() {
 | 
						|
    local interval=$1
 | 
						|
    log_info "Syncing every $interval seconds. Press any key to stop..."
 | 
						|
    
 | 
						|
    # Use read with timeout
 | 
						|
    if read -t "$interval" -n 1 key; then
 | 
						|
        log_info "Key pressed. Stopping synchronization..."
 | 
						|
        return 1  # Key was pressed
 | 
						|
    else
 | 
						|
        return 0  # Timeout occurred
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Initialize log files
 | 
						|
initialize_log_files() {
 | 
						|
    # Create log file if specified and doesn't exist
 | 
						|
    if [ -n "$LOGS_FILE" ]; then
 | 
						|
        touch "$LOGS_FILE"
 | 
						|
        log_info "Log file initialized: $LOGS_FILE"
 | 
						|
    fi
 | 
						|
    
 | 
						|
    # Create error log file if specified and doesn't exist
 | 
						|
    if [ -n "$ERRORS_LOG_FILE" ]; then
 | 
						|
        touch "$ERRORS_LOG_FILE"
 | 
						|
        # Add a header to the error log file
 | 
						|
        echo "[$(get_timestamp)] [INFO] Error log file initialized" > "$ERRORS_LOG_FILE"
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Clean up function for proper termination
 | 
						|
cleanup() {
 | 
						|
    # Skip if cleanup has already been done
 | 
						|
    if $CLEANUP_NEEDED; then
 | 
						|
        log_info "Starting cleanup process..."
 | 
						|
        
 | 
						|
        # Final sync before exiting
 | 
						|
        log_info "Performing final sync to disk..."
 | 
						|
        execute_rsync_script
 | 
						|
        
 | 
						|
        # Run sync command to ensure data is written to disk
 | 
						|
        if ! $DRY_RUN; then
 | 
						|
            log_info "Running sync command..."
 | 
						|
            sync
 | 
						|
            sync
 | 
						|
        else
 | 
						|
            log_info "Dry run: Would run sync command"
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Generate report
 | 
						|
        generate_report
 | 
						|
        
 | 
						|
        # Reset cleanup flag
 | 
						|
        CLEANUP_NEEDED=false
 | 
						|
        
 | 
						|
        log_info "Cleanup completed. Exiting."
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Generate report
 | 
						|
generate_report() {
 | 
						|
    local end_time=$(date +%s)
 | 
						|
    local duration=$((end_time - START_TIME))
 | 
						|
    local hours=$((duration / 3600))
 | 
						|
    local minutes=$(( (duration % 3600) / 60 ))
 | 
						|
    local seconds=$((duration % 60))
 | 
						|
    
 | 
						|
    log_info "===== RAM Disk Sync Report ====="
 | 
						|
    log_info "Start time: $(date -d @$START_TIME)"
 | 
						|
    log_info "End time: $(date -d @$end_time)"
 | 
						|
    log_info "Duration: ${hours}h ${minutes}m ${seconds}s"
 | 
						|
    log_info "Files copied to RAM disk: $TOTAL_FILES_COPIED"
 | 
						|
    log_info "Sync operations performed: $TOTAL_FILES_SYNCED"
 | 
						|
    log_info "============================"
 | 
						|
}
 | 
						|
 | 
						|
# Main synchronization loop
 | 
						|
run_sync_loop() {
 | 
						|
    # Register trap for cleanup
 | 
						|
    if ! $TRAP_REGISTERED; then
 | 
						|
        trap cleanup EXIT INT TERM
 | 
						|
        TRAP_REGISTERED=true
 | 
						|
        CLEANUP_NEEDED=true
 | 
						|
    fi
 | 
						|
    
 | 
						|
    # Start report timer
 | 
						|
    START_TIME=$(date +%s)
 | 
						|
    
 | 
						|
    # Execute copy script once at start
 | 
						|
    execute_cp_script
 | 
						|
    if [ $? -ne 0 ]; then
 | 
						|
        log_error "Initial copy failed. Exiting."
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
    
 | 
						|
    # If one-time mode, run rsync once and exit
 | 
						|
    if $ONE_TIME_MODE; then
 | 
						|
        log_info "Running in one-time mode"
 | 
						|
        execute_rsync_script
 | 
						|
        exit 0
 | 
						|
    fi
 | 
						|
    
 | 
						|
    # Main sync loop
 | 
						|
    log_info "Starting synchronization loop"
 | 
						|
    while true; do
 | 
						|
        # Wait for key press or timeout
 | 
						|
        if ! wait_for_key "$SYNC_INTERVAL"; then
 | 
						|
            break
 | 
						|
        fi
 | 
						|
        
 | 
						|
        # Execute rsync script
 | 
						|
        execute_rsync_script
 | 
						|
    done
 | 
						|
    execute_rsync_script
 | 
						|
    log_info "Synchronization loop ended"
 | 
						|
    sync
 | 
						|
    sync
 | 
						|
    log_info "Final sync command executed"
 | 
						|
}
 | 
						|
 | 
						|
# Main function
 | 
						|
main() {
 | 
						|
    # Parse command line arguments
 | 
						|
    parse_arguments "$@"
 | 
						|
    
 | 
						|
    # Check if rsync is installed
 | 
						|
    check_rsync
 | 
						|
    
 | 
						|
    # Parse configuration file
 | 
						|
    parse_config_file
 | 
						|
    
 | 
						|
    # Check and create directories
 | 
						|
    check_directories
 | 
						|
    
 | 
						|
    # Generate scripts
 | 
						|
    generate_rsync_script
 | 
						|
    generate_cp_script
 | 
						|
    
 | 
						|
    # Initialize log files
 | 
						|
    initialize_log_files
 | 
						|
    
 | 
						|
    # Exit if only script generation is requested
 | 
						|
    if $SCRIPT_GEN_ONLY; then
 | 
						|
        log_info "Scripts generated. Exiting as requested."
 | 
						|
        exit 0
 | 
						|
    fi
 | 
						|
    
 | 
						|
    # Run synchronization loop
 | 
						|
    run_sync_loop
 | 
						|
}
 | 
						|
 | 
						|
# Start the program
 | 
						|
main "$@"
 |