Master automated file transfers with rsync, scp, cron, and systemd timers. This comprehensive guide covers everything from basic synchronization to complex backup strategies with practical examples and best practices.
Why Automate File Transfers?
Automated file transfers are essential for modern infrastructure management, providing reliability, consistency, and efficiency.
- Reliability: Eliminate human error in manual transfers
- Consistency: Ensure transfers happen at scheduled times, every time
- Efficiency: Free up administrative time for higher-value tasks
- Disaster Recovery: Automated backups ensure data protection
- Compliance: Meet regulatory requirements for data retention
- Scalability: Handle growing data volumes without additional effort
- Monitoring: Centralized logging and alerting for transfer operations
1. Core Transfer Tools Comparison
Transfer Tool Feature Matrix
rsyncscpsftplftprclonetar + ssh2. rsync Mastery for Automation
Advanced rsync Options for Automation
# Complete rsync automation template
rsync \
--archive \ # Archive mode (recursive, preserve permissions, etc.)
--verbose \ # Verbose output
--compress \ # Compress during transfer
--progress \ # Show progress during transfer
--stats \ # Print transfer statistics
--human-readable \ # Human-friendly numbers
--partial \ # Keep partially transferred files
--partial-dir=.rsync-partial \ # Directory for partial transfers
--timeout=300 \ # Connection timeout (seconds)
--contimeout=120 \ # Connection establishment timeout
--bwlimit=1000 \ # Bandwidth limit (KB/s)
--exclude='*.tmp' \ # Exclude temporary files
--exclude='*.log' \ # Exclude log files
--exclude='temp/' \ # Exclude temp directory
--exclude='cache/' \ # Exclude cache directory
--delete \ # Delete extra files at destination
--delete-excluded \ # Delete excluded files from destination
--backup \ # Backup overwritten files
--backup-dir=../backup_$(date +%Y%m%d) \ # Backup directory
--link-dest=/path/to/previous_backup \ # Hardlink to unchanged files
--log-file=/var/log/rsync/$(date +%Y%m%d).log \ # Log file
--log-file-format='%i %n%L' \ # Custom log format
--max-size=100M \ # Skip files larger than 100M
--min-size=1k \ # Skip files smaller than 1k
/source/directory/ \
user@remotehost:/destination/directory/
# Example with SSH options
rsync -avz \
-e "ssh -i /path/to/key -o StrictHostKeyChecking=no -o ConnectTimeout=10" \
/source/ \
user@host:/dest/
3. Automation with Cron
Cron Syntax & Examples
Practical Cron Examples for File Transfers
# File Transfer Automation Crontab
# ==============================================
# Environment settings
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=admin@example.com
HOME=/home/backupuser
# Log all output to files (append >>) instead of email
# 0 * * * * /path/command >> /var/log/cron.log 2>&1
# Hourly: Sync web server logs
0 * * * * /usr/bin/rsync -avz --remove-source-files /var/log/nginx/ user@backup:/backup/logs/hourly/ >> /var/log/rsync-hourly.log 2>&1
# Every 6 hours: Database backups
0 */6 * * * /usr/local/bin/backup-database.sh >> /var/log/db-backup.log 2>&1
# Daily at 2 AM: Full system backup
0 2 * * * /usr/local/bin/full-backup.sh >> /var/log/full-backup.log 2>&1
# Daily at 3 AM: Sync important documents
0 3 * * * /usr/bin/rsync -avz --delete /home/shared/ user@fileserver:/backup/shared/ >> /var/log/shared-sync.log 2>&1
# Daily at 4 AM: Cleanup old backups (keep 30 days)
0 4 * * * find /backup/daily/ -type f -mtime +30 -delete >> /var/log/backup-cleanup.log 2>&1
# Monday at 1 AM: Weekly archive
0 1 * * 1 /usr/local/bin/weekly-archive.sh >> /var/log/weekly-archive.log 2>&1
# 1st of month at 5 AM: Monthly backup
0 5 1 * * /usr/local/bin/monthly-backup.sh >> /var/log/monthly-backup.log 2>&1
# Every 15 minutes: Sync configuration files
*/15 * * * * /usr/bin/rsync -avz /etc/nginx/sites-available/ user@backup:/backup/configs/nginx/ >> /var/log/config-sync.log 2>&1
# Every 5 minutes: Heartbeat/status check
*/5 * * * * /usr/local/bin/transfer-status.sh >> /var/log/transfer-status.log 2>&1
# Business hours only (9 AM to 5 PM, Monday-Friday)
0 9-17 * * 1-5 /usr/bin/rsync -avz --bwlimit=5000 /data/sales/ user@offsite:/backup/sales/ >> /var/log/sales-backup.log 2>&1
# Weekend processing (Saturday and Sunday at 6 AM)
0 6 * * 6,7 /usr/local/bin/weekend-processing.sh >> /var/log/weekend-processing.log 2>&1
# Special: First day of quarter
0 7 1 1,4,7,10 * /usr/local/bin/quarterly-backup.sh >> /var/log/quarterly-backup.log 2>&1
4. Systemd Timers for Modern Automation
Systemd Timer vs Cron Comparison
systemctl statusComplete Systemd Timer Example
# /etc/systemd/system/backup.service
[Unit]
Description=Daily Backup Service
Documentation=https://example.com/docs/backup
After=network-online.target
Wants=network-online.target
ConditionPathExists=/backup/source/
[Service]
Type=oneshot
User=backup
Group=backup
WorkingDirectory=/home/backup
Environment=BACKUP_DIR=/backup/daily
Environment=LOG_FILE=/var/log/backup/$(date +%Y%m%d).log
ExecStartPre=/bin/mkdir -p /var/log/backup
ExecStartPre=/usr/bin/test -f /etc/backup.conf
ExecStart=/usr/local/bin/backup-script.sh
ExecStop=/bin/true
StandardOutput=journal
StandardError=journal
SyslogIdentifier=backup
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=/backup/daily /var/log/backup
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer
Documentation=https://example.com/docs/backup
Requires=backup.service
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1h
AccuracySec=1min
Unit=backup.service
# Alternative calendar expressions:
# OnCalendar=*-*-* 02:00:00 # Daily at 2 AM
# OnCalendar=Mon,Fri *-*-* 10:00 # Monday and Friday at 10 AM
# OnCalendar=*-*-15 00:00 # 15th of every month
# OnCalendar=*-12-25 00:00 # December 25th every year
# OnCalendar=hourly # Every hour
# OnCalendar=weekly # Every week
[Install]
WantedBy=timers.target
# Enable the timer
sudo systemctl daemon-reload
sudo systemctl enable backup.timer
sudo systemctl start backup.timer
# Check status
systemctl status backup.timer
systemctl list-timers --all
journalctl -u backup.service -f # Follow logs
# Manual trigger
sudo systemctl start backup.service
# Disable
sudo systemctl stop backup.timer
sudo systemctl disable backup.timer
5. Complete Automation Scripts
Intelligent Backup Script
#!/bin/bash
# intelligent-backup.sh - Smart backup with rsync and rotation
set -euo pipefail
# Configuration
BACKUP_SOURCE="/data"
BACKUP_DEST="/backup"
BACKUP_NAME="data_backup"
LOG_FILE="/var/log/backup/$(date +%Y%m%d_%H%M%S).log"
MAX_DAILY_BACKUPS=30
MAX_WEEKLY_BACKUPS=4
MAX_MONTHLY_BACKUPS=12
EMAIL="admin@example.com"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging function
log() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case "$level" in
"INFO") color="$BLUE" ;;
"SUCCESS") color="$GREEN" ;;
"WARNING") color="$YELLOW" ;;
"ERROR") color="$RED" ;;
*) color="$NC" ;;
esac
echo -e "${color}[$timestamp] [$level]${NC} $message" | tee -a "$LOG_FILE"
}
# Error handling
trap 'log "ERROR" "Backup script failed on line $LINENO"; exit 1' ERR
# Check prerequisites
check_prerequisites() {
log "INFO" "Checking prerequisites..."
# Check if source exists
if [[ ! -d "$BACKUP_SOURCE" ]]; then
log "ERROR" "Source directory does not exist: $BACKUP_SOURCE"
exit 1
fi
# Check if destination exists
if [[ ! -d "$BACKUP_DEST" ]]; then
log "WARNING" "Destination directory does not exist, creating: $BACKUP_DEST"
mkdir -p "$BACKUP_DEST"
fi
# Check disk space (minimum 10% free)
local free_space=$(df -h "$BACKUP_DEST" | awk 'NR==2 {print $5}' | sed 's/%//')
if [[ "$free_space" -gt 90 ]]; then
log "ERROR" "Insufficient disk space on backup destination (${free_space}% used)"
exit 1
fi
# Check rsync availability
if ! command -v rsync &> /dev/null; then
log "ERROR" "rsync not found. Please install rsync."
exit 1
fi
}
# Create backup directory with timestamp
create_backup_dir() {
local backup_type="$1"
local timestamp=$(date '+%Y%m%d_%H%M%S')
local backup_dir="$BACKUP_DEST/${backup_type}_${BACKUP_NAME}_${timestamp}"
log "INFO" "Creating backup directory: $backup_dir"
mkdir -p "$backup_dir"
echo "$backup_dir"
}
# Perform rsync backup
perform_backup() {
local source_dir="$1"
local dest_dir="$2"
local backup_type="$3"
log "INFO" "Starting $backup_type backup from $source_dir to $dest_dir"
# Rsync command with appropriate options
local rsync_cmd="rsync"
local rsync_opts="-avz --progress --stats --human-readable --delete"
case "$backup_type" in
"daily")
rsync_opts="$rsync_opts --link-dest=$BACKUP_DEST/latest_daily"
;;
"weekly")
rsync_opts="$rsync_opts --link-dest=$BACKUP_DEST/latest_weekly"
;;
"monthly")
rsync_opts="$rsync_opts --link-dest=$BACKUP_DEST/latest_monthly"
;;
esac
# Add exclusion patterns
local exclude_file="/etc/backup-exclude.conf"
if [[ -f "$exclude_file" ]]; then
rsync_opts="$rsync_opts --exclude-from=$exclude_file"
else
# Default exclusions
rsync_opts="$rsync_opts --exclude='*.tmp' --exclude='*.log' --exclude='temp/' --exclude='cache/'"
fi
# Execute rsync
log "INFO" "Executing: $rsync_cmd $rsync_opts $source_dir/ $dest_dir/"
if eval "$rsync_cmd $rsync_opts \"$source_dir/\" \"$dest_dir/\"" >> "$LOG_FILE" 2>&1; then
log "SUCCESS" "$backup_type backup completed successfully"
# Update latest symlink
local latest_link="$BACKUP_DEST/latest_${backup_type}"
ln -sfn "$dest_dir" "$latest_link"
log "INFO" "Updated symlink: $latest_link → $dest_dir"
return 0
else
log "ERROR" "$backup_type backup failed"
return 1
fi
}
# Rotate old backups
rotate_backups() {
local backup_type="$1"
local max_backups="$2"
log "INFO" "Rotating $backup_type backups (keeping $max_backups)"
# Get list of backups, sort by date (newest first)
local backups=($(ls -td $BACKUP_DEST/${backup_type}_${BACKUP_NAME}_* 2>/dev/null || true))
if [[ ${#backups[@]} -gt $max_backups ]]; then
local to_delete=${backups[@]:$max_backups}
for backup in $to_delete; do
log "INFO" "Deleting old backup: $backup"
rm -rf "$backup"
done
log "SUCCESS" "Deleted ${#to_delete[@]} old $backup_type backups"
else
log "INFO" "No $backup_type backups to rotate (${#backups[@]} out of $max_backups)"
fi
}
# Send notification
send_notification() {
local status="$1"
local subject="Backup ${status}: $(date '+%Y-%m-%d %H:%M')"
local body=$(tail -20 "$LOG_FILE")
log "INFO" "Sending notification: $status"
# Email notification (if mail command available)
if command -v mail &> /dev/null; then
echo "$body" | mail -s "$subject" "$EMAIL"
fi
# Log the notification
echo "=== Notification Sent ===" >> "$LOG_FILE"
echo "Status: $status" >> "$LOG_FILE"
echo "Subject: $subject" >> "$LOG_FILE"
echo "=========================" >> "$LOG_FILE"
}
# Main execution
main() {
log "INFO" "=== Starting Intelligent Backup ==="
log "INFO" "Date: $(date)"
log "INFO" "Source: $BACKUP_SOURCE"
log "INFO" "Destination: $BACKUP_DEST"
# Check prerequisites
check_prerequisites
# Determine backup type based on date
local day_of_month=$(date +%d)
local day_of_week=$(date +%u) # 1=Monday, 7=Sunday
local backup_type="daily"
if [[ "$day_of_month" == "01" ]]; then
backup_type="monthly"
elif [[ "$day_of_week" == "7" ]]; then
backup_type="weekly"
fi
log "INFO" "Backup type: $backup_type"
# Create backup directory
local backup_dir=$(create_backup_dir "$backup_type")
# Perform backup
if perform_backup "$BACKUP_SOURCE" "$backup_dir" "$backup_type"; then
# Rotate backups
case "$backup_type" in
"daily")
rotate_backups "daily" "$MAX_DAILY_BACKUPS"
;;
"weekly")
rotate_backups "weekly" "$MAX_WEEKLY_BACKUPS"
;;
"monthly")
rotate_backups "monthly" "$MAX_MONTHLY_BACKUPS"
;;
esac
# Send success notification
send_notification "SUCCESS"
log "SUCCESS" "=== Backup completed successfully ==="
exit 0
else
# Send failure notification
send_notification "FAILED"
log "ERROR" "=== Backup failed ==="
exit 1
fi
}
# Run main function
main "$@"
Multi-Server Sync Script
#!/bin/bash
# multi-server-sync.sh - Synchronize files across multiple servers
set -euo pipefail
# Configuration
CONFIG_FILE="/etc/sync-config.conf"
LOG_DIR="/var/log/sync"
LOCK_FILE="/tmp/sync.lock"
MAX_RETRIES=3
RETRY_DELAY=30
# Load configuration
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
else
# Default configuration
SOURCE_DIR="/data/shared"
DEST_SERVERS=(
"user@server1:/backup/shared/"
"user@server2:/backup/shared/"
"user@server3:/backup/shared/"
)
SYNC_OPTIONS="-avz --delete --progress --stats"
EXCLUDE_PATTERNS=("*.tmp" "*.log" "temp/*" "cache/*")
fi
# Setup logging
setup_logging() {
local timestamp=$(date +%Y%m%d_%H%M%S)
local log_file="$LOG_DIR/sync_${timestamp}.log"
mkdir -p "$LOG_DIR"
exec > >(tee -a "$log_file") 2>&1
echo "=== Multi-Server Sync Started ==="
echo "Time: $(date)"
echo "Source: $SOURCE_DIR"
echo "Destination servers: ${#DEST_SERVERS[@]}"
echo "================================="
}
# Check for existing lock
check_lock() {
if [[ -f "$LOCK_FILE" ]]; then
local pid=$(cat "$LOCK_FILE")
if kill -0 "$pid" 2>/dev/null; then
echo "ERROR: Sync already running (PID: $pid)"
exit 1
else
echo "WARNING: Stale lock file found, removing"
rm -f "$LOCK_FILE"
fi
fi
# Create lock file
echo $$ > "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"' EXIT
}
# Validate source directory
validate_source() {
if [[ ! -d "$SOURCE_DIR" ]]; then
echo "ERROR: Source directory does not exist: $SOURCE_DIR"
exit 1
fi
if [[ ! -r "$SOURCE_DIR" ]]; then
echo "ERROR: Cannot read source directory: $SOURCE_DIR"
exit 1
fi
}
# Build rsync command
build_rsync_command() {
local server="$1"
local cmd="rsync $SYNC_OPTIONS"
# Add exclude patterns
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
cmd="$cmd --exclude='$pattern'"
done
# Add source and destination
cmd="$cmd $SOURCE_DIR/ $server"
echo "$cmd"
}
# Test server connectivity
test_server_connectivity() {
local server="$1"
local host=$(echo "$server" | cut -d: -f1)
echo "Testing connectivity to $host..."
if ssh -o ConnectTimeout=10 -o BatchMode=yes "$host" "echo connected" 2>/dev/null; then
echo "✓ Connected to $host"
return 0
else
echo "✗ Cannot connect to $host"
return 1
fi
}
# Sync to single server with retry
sync_to_server() {
local server="$1"
local retry_count=0
while [[ $retry_count -lt $MAX_RETRIES ]]; do
echo "Starting sync to $server (attempt $((retry_count + 1))/$MAX_RETRIES)"
local rsync_cmd=$(build_rsync_command "$server")
echo "Command: $rsync_cmd"
if eval "$rsync_cmd"; then
echo "✓ Successfully synced to $server"
return 0
else
retry_count=$((retry_count + 1))
if [[ $retry_count -lt $MAX_RETRIES ]]; then
echo "✗ Sync failed, retrying in $RETRY_DELAY seconds..."
sleep $RETRY_DELAY
fi
fi
done
echo "✗ Failed to sync to $server after $MAX_RETRIES attempts"
return 1
}
# Generate sync report
generate_report() {
local success_count=0
local failure_count=0
local report_file="$LOG_DIR/report_$(date +%Y%m%d_%H%M%S).txt"
echo "=== Sync Report ===" > "$report_file"
echo "Date: $(date)" >> "$report_file"
echo "Source: $SOURCE_DIR" >> "$report_file"
echo "" >> "$report_file"
echo "Results:" >> "$report_file"
for server in "${DEST_SERVERS[@]}"; do
if sync_to_server "$server"; then
echo "✓ $server" >> "$report_file"
success_count=$((success_count + 1))
else
echo "✗ $server" >> "$report_file"
failure_count=$((failure_count + 1))
fi
done
echo "" >> "$report_file"
echo "Summary:" >> "$report_file"
echo "Successful: $success_count" >> "$report_file"
echo "Failed: $failure_count" >> "$report_file"
echo "Total: ${#DEST_SERVERS[@]}" >> "$report_file"
if [[ $failure_count -eq 0 ]]; then
echo "Status: COMPLETE SUCCESS" >> "$report_file"
elif [[ $success_count -eq 0 ]]; then
echo "Status: COMPLETE FAILURE" >> "$report_file"
else
echo "Status: PARTIAL SUCCESS" >> "$report_file"
fi
cat "$report_file"
echo "Detailed report: $report_file"
}
# Main execution
main() {
setup_logging
check_lock
validate_source
echo "Testing connectivity to all servers..."
local reachable_servers=()
for server in "${DEST_SERVERS[@]}"; do
if test_server_connectivity "$server"; then
reachable_servers+=("$server")
fi
done
if [[ ${#reachable_servers[@]} -eq 0 ]]; then
echo "ERROR: No servers are reachable"
exit 1
fi
echo "Starting sync to ${#reachable_servers[@]} reachable servers"
# Generate and display report
DEST_SERVERS=("${reachable_servers[@]}")
generate_report
echo "=== Multi-Server Sync Completed ==="
}
# Run main function
main "$@"
6. Monitoring & Alerting
Transfer Monitoring Script
#!/bin/bash
# transfer-monitor.sh - Monitor file transfer health and performance
set -euo pipefail
# Configuration
LOG_DIR="/var/log/transfers"
ALERT_EMAIL="admin@example.com"
ALERT_SLACK_WEBHOOK="https://hooks.slack.com/services/..."
PERFORMANCE_THRESHOLD=100 # KB/s minimum
SUCCESS_RATE_THRESHOLD=95 # Percentage
# Create log directory
mkdir -p "$LOG_DIR"
# Function to send alerts
send_alert() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Log alert
echo "[$timestamp] [$level] $message" >> "$LOG_DIR/alerts.log"
# Email alert
if command -v mail &> /dev/null; then
echo "Alert: $level - $message" | mail -s "Transfer Alert: $level" "$ALERT_EMAIL"
fi
# Slack alert (if curl is available)
if command -v curl &> /dev/null && [[ -n "$ALERT_SLACK_WEBHOOK" ]]; then
local payload="{\"text\":\"🚨 Transfer Alert ($level): $message\"}"
curl -s -X POST -H 'Content-type: application/json' --data "$payload" "$ALERT_SLACK_WEBHOOK" > /dev/null
fi
}
# Check recent transfer logs
check_transfer_logs() {
local log_pattern="$LOG_DIR/*.log"
local recent_logs=$(find $LOG_DIR -name "*.log" -mtime -1)
local failed_transfers=0
local total_transfers=0
echo "=== Transfer Log Analysis ==="
for log_file in $recent_logs; do
total_transfers=$((total_transfers + 1))
# Check for errors in log
if grep -q -i "error\|failed\|timed out" "$log_file"; then
failed_transfers=$((failed_transfers + 1))
local error_details=$(grep -i "error\|failed\|timed out" "$log_file" | head -3)
send_alert "ERROR" "Failed transfer detected in $log_file: $error_details"
fi
# Check transfer speed
if grep -q "bytes/sec" "$log_file"; then
local speed=$(grep "bytes/sec" "$log_file" | tail -1 | grep -o '[0-9.]* bytes/sec' | cut -d' ' -f1)
local speed_kbs=$(echo "$speed / 1024" | bc)
if (( $(echo "$speed_kbs < $PERFORMANCE_THRESHOLD" | bc -l) )); then
send_alert "WARNING" "Slow transfer detected in $log_file: ${speed_kbs}KB/s (threshold: ${PERFORMANCE_THRESHOLD}KB/s)"
fi
fi
done
# Calculate success rate
if [[ $total_transfers -gt 0 ]]; then
local success_rate=$(( (total_transfers - failed_transfers) * 100 / total_transfers ))
echo "Total transfers: $total_transfers"
echo "Failed transfers: $failed_transfers"
echo "Success rate: ${success_rate}%"
if [[ $success_rate -lt $SUCCESS_RATE_THRESHOLD ]]; then
send_alert "CRITICAL" "Low success rate: ${success_rate}% (threshold: ${SUCCESS_RATE_THRESHOLD}%)"
fi
else
echo "No transfer logs found in the last 24 hours"
send_alert "WARNING" "No transfer activity detected in last 24 hours"
fi
}
# Check disk space on source and destination
check_disk_space() {
local critical_paths=("/" "/backup" "/data")
echo "=== Disk Space Check ==="
for path in "${critical_paths[@]}"; do
if [[ -d "$path" ]]; then
local usage=$(df -h "$path" | awk 'NR==2 {print $5}' | sed 's/%//')
local available=$(df -h "$path" | awk 'NR==2 {print $4}')
echo "$path: ${usage}% used, ${available} available"
if [[ $usage -gt 90 ]]; then
send_alert "CRITICAL" "Disk space critical on $path: ${usage}% used"
elif [[ $usage -gt 80 ]]; then
send_alert "WARNING" "Disk space warning on $path: ${usage}% used"
fi
fi
done
}
# Check transfer schedule
check_schedule() {
echo "=== Transfer Schedule Check ==="
# Check cron jobs
if crontab -l 2>/dev/null | grep -q "rsync\|scp\|backup"; then
echo "✓ Transfer cron jobs configured"
else
send_alert "WARNING" "No transfer cron jobs found in user crontab"
fi
# Check systemd timers
if systemctl list-timers --all 2>/dev/null | grep -q "backup\|sync\|transfer"; then
echo "✓ Transfer systemd timers configured"
fi
}
# Check network connectivity
check_connectivity() {
echo "=== Network Connectivity Check ==="
local test_hosts=("google.com" "backup-server.example.com" "8.8.8.8")
for host in "${test_hosts[@]}"; do
if ping -c 2 -W 1 "$host" &> /dev/null; then
echo "✓ Reachable: $host"
else
echo "✗ Unreachable: $host"
send_alert "WARNING" "Host unreachable: $host"
fi
done
}
# Generate summary report
generate_summary() {
local report_file="$LOG_DIR/health_report_$(date +%Y%m%d).txt"
{
echo "=== Transfer Health Report ==="
echo "Generated: $(date)"
echo ""
check_transfer_logs
echo ""
check_disk_space
echo ""
check_schedule
echo ""
check_connectivity
echo ""
echo "=== End of Report ==="
} > "$report_file"
echo "Health report generated: $report_file"
}
# Main execution
main() {
echo "Starting transfer health check..."
check_transfer_logs
check_disk_space
check_schedule
check_connectivity
generate_summary
echo "Transfer health check completed"
}
# Run main function
main "$@"
7. Best Practices & Optimization
1. Use dry-run first: Always test with
--dry-run before automation2. Implement proper logging: Log all transfers with timestamps and outcomes
3. Set bandwidth limits: Use
--bwlimit to avoid network congestion4. Monitor disk space: Check available space before and after transfers
5. Use checksums for critical data: Verify integrity with
--checksum6. Implement retry logic: Handle temporary network failures gracefully
7. Secure credentials: Use SSH keys, never store passwords in scripts
8. Version your backups: Use
--link-dest for efficient versioning9. Test recovery regularly: Periodically restore from backups to verify integrity
10. Implement monitoring: Set up alerts for failed transfers
Performance Optimization Tips
-z or --compress--parallel=N (rsync 3.1+)--skip-compress=gz/jpg/mp4--link-dest=/previous/--partial --partial-dir=-e "ssh -o BatchMode=yes"-e "ssh -o ControlMaster=yes"Master File Transfer Automation
File transfer automation is essential for modern infrastructure management, providing reliability, efficiency, and consistency for data movement tasks. By mastering rsync, scp, cron, and systemd timers, you can create robust automation systems that handle everything from simple file copies to complex multi-server backup strategies.
Remember: Start simple and add complexity gradually. Always implement proper logging and monitoring from the beginning. Test your automation thoroughly before relying on it for critical operations. Regularly review and update your automation scripts as your infrastructure evolves.
Next Steps: Begin by automating one simple transfer task. Implement logging and error handling. Add monitoring and alerting. Gradually build up to more complex multi-server synchronization. As you gain experience, you'll be able to design sophisticated automation systems that reliably handle all your file transfer needs.