When automating server backups via cron with rsync, silent failures can be disastrous. Many sysadmins make the mistake of only checking file timestamps without implementing proper logging mechanisms. This leaves critical gaps in backup monitoring.
Here are the most effective approaches to implement robust logging:
# Method 1: Redirect output with timestamps
rsync -avz -e ssh root@example.com:/ /mybackup/ >> /var/log/rsync_backup.log 2>&1
# Method 2: Use syslog integration
rsync -avz -e ssh root@example.com:/ /mybackup/ | logger -t rsync_backup
# Method 3: Custom script with error handling
#!/bin/bash
LOG="/var/log/rsync_backup.log"
echo "Starting backup: $(date)" >> "$LOG"
rsync -avz -e ssh root@example.com:/ /mybackup/ >> "$LOG" 2>&1
if [ $? -eq 0 ]; then
echo "Backup completed successfully: $(date)" >> "$LOG"
else
echo "BACKUP FAILED with error code $?: $(date)" >> "$LOG"
# Add notification logic here
fi
For mission-critical backups, consider these enhancements:
# Verify transfer completion
#!/bin/bash
LOG="/var/log/rsync_backup.log"
TMP_FILE="/tmp/rsync_last_run"
rsync -avz -e ssh root@example.com:/ /mybackup/ >> "$LOG" 2>&1
STATUS=$?
# Record transfer statistics
echo "Exit status: $STATUS" >> "$LOG"
echo "Last run: $(date)" > "$TMP_FILE"
# Check for common failure patterns
if grep -q "connection unexpectedly closed" "$LOG"; then
echo "WARNING: Connection issues detected" >> "$LOG"
fi
Combine logging with notifications:
#!/bin/bash
LOG="/var/log/rsync_backup.log"
EMAIL="admin@example.com"
rsync -avz -e ssh root@example.com:/ /mybackup/ >> "$LOG" 2>&1
if [ $? -ne 0 ]; then
grep -A 10 -B 10 "error\|failed\|warning" "$LOG" | mail -s "Rsync Backup Failed" "$EMAIL"
fi
Prevent log files from growing indefinitely:
# /etc/logrotate.d/rsync
/var/log/rsync_backup.log {
weekly
rotate 4
compress
missingok
notifempty
create 640 root adm
}
Beyond just logging, implement verification:
#!/bin/bash
LOG="/var/log/rsync_verify.log"
SOURCE="/mybackup"
FLAG_FILE="$SOURCE/db_backup.sql"
echo "Verifying backup integrity: $(date)" >> "$LOG"
# Check for critical files
if [ ! -f "$FLAG_FILE" ]; then
echo "CRITICAL: Missing database backup file" >> "$LOG"
exit 1
fi
# Check file freshness
if find "$FLAG_FILE" -mtime +1 | grep -q "."; then
echo "WARNING: Database backup is older than 24 hours" >> "$LOG"
fi
When automating remote backups with rsync via cron, the biggest challenge is monitoring execution status. Many admins make the mistake of only checking file timestamps as success indicators, which can miss partial failures occurring later in the transfer process.
For CentOS systems (or any Linux distribution), here are robust logging methods:
# Method 1: Redirect all output with timestamp
rsync -avz -e ssh root@example.com:/ /mybackup/ >> /var/log/rsync_backup.log 2>&1
# Method 2: Conditional logging (success/failure only)
rsync -avz -e ssh root@example.com:/ /mybackup/ && \
echo "$(date): Rsync completed successfully" >> /var/log/rsync_status.log || \
echo "$(date): Rsync failed with code $?" >> /var/log/rsync_errors.log
For better debugging of "client reset" errors:
#!/bin/bash
LOG_FILE="/var/log/rsync_detailed.log"
MAX_RETRIES=3
RETRY_DELAY=60
for ((i=1; i<=$MAX_RETRIES; i++)); do
rsync -avz --partial --timeout=300 -e ssh root@example.com:/ /mybackup/ >> $LOG_FILE 2>&1
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "$(date): Backup completed successfully" >> $LOG_FILE
exit 0
else
echo "$(date): Attempt $i failed (Code: $EXIT_CODE)" >> $LOG_FILE
if [ $i -lt $MAX_RETRIES ]; then
sleep $RETRY_DELAY
fi
fi
done
# Alert if all retries failed
echo "$(date): Rsync failed after $MAX_RETRIES attempts" | mail -s "Backup Failure" admin@example.com
exit 1
Create /etc/logrotate.d/rsync:
/var/log/rsync_*log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
/usr/bin/systemctl reload rsyslog >/dev/null 2>&1 || true
endscript
}
To confirm backups without checking every file:
# Check exit code from last run
echo $?
# Verify most recently modified file
find /mybackup -type f -printf '%T+ %p\n' | sort -r | head -n 5
# Check for common error patterns
grep -E "error|fail|timeout|reset" /var/log/rsync_errors.log
For comprehensive monitoring:
#!/bin/bash
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
LOG_DIR="/var/log/rsync_backups"
SUMMARY_LOG="$LOG_DIR/summary.log"
DETAIL_LOG="$LOG_DIR/detail_$TIMESTAMP.log"
mkdir -p $LOG_DIR
echo "=== Starting Rsync Backup at $(date) ===" >> $DETAIL_LOG
/usr/bin/rsync -avz --stats \
-e "ssh -o ConnectTimeout=30" \
root@example.com:/ /mybackup/ >> $DETAIL_LOG 2>&1
RSYNC_EXIT=$?
if [ $RSYNC_EXIT -eq 0 ]; then
STATUS="SUCCESS"
else
STATUS="FAILED"
fi
echo "$TIMESTAMP|$STATUS|ExitCode:$RSYNC_EXIT" >> $SUMMARY_LOG
# Send summary notification
echo "Backup $STATUS at $(date)" | \
mail -s "Rsync Backup $STATUS" -a $DETAIL_LOG admin@example.com
exit $RSYNC_EXIT