Copia de Seguridad Comprimida con tar y gzip: Guía Práctica Completa
Introducción
La utilidad tar (Tape Archive), combinada con la compresión gzip, ha sido una piedra angular de las copias de seguridad en sistemas Unix/Linux durante décadas. A pesar de la aparición de herramientas modernas de respaldo con características avanzadas como deduplicación y cifrado, tar y gzip siguen siendo relevantes debido a su universalidad, simplicidad y fiabilidad. Cada sistema Linux incluye estas herramientas por defecto, lo que las hace ideales para situaciones donde necesitas copias de seguridad portables y autocontenidas que pueden restaurarse en cualquier sistema tipo Unix sin instalar software especializado.
Comprender tar y gzip es fundamental para cualquier administrador de sistemas Linux. Estas herramientas proporcionan la base para muchos flujos de trabajo de respaldo, desde archivos de archivos simples hasta sistemas de respaldo automatizados complejos. Su operación directa, combinada con opciones poderosas para respaldos selectivos, compresión y archivo incremental, las hace adecuadas para todo, desde respaldos personales rápidos hasta implementaciones de recuperación ante desastres empresariales siguiendo la regla de respaldo 3-2-1.
Esta guía completa explora tar y gzip desde los conceptos básicos hasta el uso avanzado en producción, cubriendo sintaxis, estrategias de compresión, respaldos incrementales, automatización, procedimientos de restauración y escenarios del mundo real.
Comprendiendo tar y gzip
¿Qué es tar?
Tar (Tape Archive) crea archivos de archivo combinando múltiples archivos y directorios en un solo archivo. Originalmente diseñado para respaldos en cinta magnética, tar ahora sirve como un formato de archivo universal.
Características clave:
- Preserva los metadatos de archivos (permisos, propiedad, marcas de tiempo)
- Mantiene las estructuras de directorios
- Puede archivar archivos especiales (enlaces simbólicos, dispositivos)
- Crea archivos secuenciales adecuados para streaming
- Sin compresión por defecto (tar en sí no comprime)
¿Qué es gzip?
Gzip (GNU zip) es una utilidad de compresión que reduce el tamaño de los archivos utilizando el algoritmo DEFLATE. Mientras gzip comprime archivos, tradicionalmente opera en archivos individuales a la vez.
Características clave:
- Buena relación de compresión (típicamente reducción del 50-80%)
- Compresión/descompresión rápida
- Disponible en prácticamente todos los sistemas Unix/Linux
- Se combina naturalmente con tar para archivos comprimidos
Flujo de trabajo tar + gzip
El flujo de trabajo estándar combina ambos:
# Create tar archive
tar -cf archive.tar /path/to/backup
# Compress with gzip
gzip archive.tar
# Result: archive.tar.gz
# Or combine in single command
tar -czf archive.tar.gz /path/to/backup
Operaciones Básicas de tar
Creando Archivos
Sintaxis básica:
tar -cf archive.tar file1 file2 directory/
Opciones esenciales:
-c: Crear archivo-f: Especificar nombre de archivo-v: Salida detallada-z: Compresión gzip-j: Compresión bzip2-J: Compresión xz-t: Listar contenido-x: Extraer archivo
Crear archivo básico:
# Archive single directory
tar -cf backup.tar /home/user/
# Archive multiple items
tar -cf backup.tar /etc/ /var/www/ /home/
# Verbose output
tar -cvf backup.tar /home/user/
# Archive with gzip compression
tar -czf backup.tar.gz /home/user/
# Archive with bzip2 (better compression, slower)
tar -cjf backup.tar.bz2 /home/user/
# Archive with xz (best compression, slowest)
tar -cJf backup.tar.xz /home/user/
Eliminar barra diagonal inicial (recomendado para portabilidad):
# Keep leading slash (absolute paths)
tar -czf backup.tar.gz /home/user/
# Extracts to: /home/user/
# Remove leading slash (relative paths)
tar -czf backup.tar.gz -C / home/user/
# or
tar -czf backup.tar.gz --exclude-vcs /home/user/
Listando Contenido de Archivos
# List files in archive
tar -tf archive.tar.gz
# Verbose listing with details
tar -tvf archive.tar.gz
# List specific files matching pattern
tar -tf archive.tar.gz | grep '.conf$'
# Count files in archive
tar -tf archive.tar.gz | wc -l
Extrayendo Archivos
# Extract to current directory
tar -xzf archive.tar.gz
# Extract to specific directory
tar -xzf archive.tar.gz -C /restore/location/
# Extract specific files
tar -xzf archive.tar.gz path/to/specific/file.txt
# Extract with verbose output
tar -xzvf archive.tar.gz
# Extract files matching pattern
tar -xzf archive.tar.gz --wildcards '*.conf'
# Extract and preserve permissions (default)
tar -xzpf archive.tar.gz
# Overwrite existing files
tar -xzf archive.tar.gz --overwrite
Opciones y Estrategias de Compresión
Comparando Algoritmos de Compresión
gzip (por defecto, equilibrado):
tar -czf archive.tar.gz /data/
# Compression ratio: ~60-70%
# Speed: Fast
# Compatibility: Universal
bzip2 (mejor compresión):
tar -cjf archive.tar.bz2 /data/
# Compression ratio: ~70-80%
# Speed: Slower than gzip
# Compatibility: Very good
xz (mejor compresión):
tar -cJf archive.tar.xz /data/
# Compression ratio: ~80-90%
# Speed: Slowest
# Compatibility: Good (modern systems)
lz4 (más rápido):
tar -c /data/ | lz4 > archive.tar.lz4
# Compression ratio: ~50-60%
# Speed: Very fast
# Compatibility: Requires lz4 installed
Ejemplo de comparación de rendimiento:
#!/bin/bash
# Compare compression methods
SOURCE="/var/www"
RESULTS="compression-test-results.txt"
echo "Compression Performance Test" > "$RESULTS"
echo "Source: $SOURCE" >> "$RESULTS"
echo "Original size: $(du -sh $SOURCE | cut -f1)" >> "$RESULTS"
echo "" >> "$RESULTS"
# gzip
echo "Testing gzip..." >> "$RESULTS"
time tar -czf test-gzip.tar.gz "$SOURCE" 2>&1 | grep real >> "$RESULTS"
echo "Size: $(du -h test-gzip.tar.gz | cut -f1)" >> "$RESULTS"
echo "" >> "$RESULTS"
# bzip2
echo "Testing bzip2..." >> "$RESULTS"
time tar -cjf test-bzip2.tar.bz2 "$SOURCE" 2>&1 | grep real >> "$RESULTS"
echo "Size: $(du -h test-bzip2.tar.bz2 | cut -f1)" >> "$RESULTS"
echo "" >> "$RESULTS"
# xz
echo "Testing xz..." >> "$RESULTS"
time tar -cJf test-xz.tar.xz "$SOURCE" 2>&1 | grep real >> "$RESULTS"
echo "Size: $(du -h test-xz.tar.xz | cut -f1)" >> "$RESULTS"
cat "$RESULTS"
Ajuste de Nivel de Compresión
Niveles de compresión gzip (1-9):
# Fast compression (level 1)
tar -czf archive.tar.gz --gzip-level=1 /data/
# Default (level 6)
tar -czf archive.tar.gz /data/
# Maximum compression (level 9)
tar -czf archive.tar.gz --gzip-level=9 /data/
Usando pigz (gzip paralelo):
# Install pigz
sudo apt install pigz # Ubuntu/Debian
sudo yum install pigz # CentOS/RHEL
# Use with tar
tar -cf - /data/ | pigz -p 4 > archive.tar.gz
# -p 4: Use 4 CPU cores
# Extract
pigz -dc archive.tar.gz | tar -xf -
Estrategia de Compresión Óptima
Elegir según el caso de uso:
Respaldos rápidos (priorizar velocidad):
tar -czf --gzip-level=1 backup.tar.gz /data/
# or
tar -c /data/ | lz4 > backup.tar.lz4
Espacio limitado (priorizar tamaño):
tar -cJf backup.tar.xz /data/
# or
tar -cjf backup.tar.bz2 /data/
Equilibrado (por defecto en producción):
tar -czf backup.tar.gz /data/
# Standard gzip, good balance
Conjuntos de datos grandes con CPU multi-núcleo:
tar -cf - /data/ | pigz -p $(nproc) > backup.tar.gz
# Parallel compression using all cores
Características Avanzadas de tar
Respaldos Incrementales
Tar admite respaldos incrementales utilizando archivos de instantáneas:
Crear archivo de instantánea:
# Full backup with snapshot
tar -czf full-backup.tar.gz \
--listed-incremental=backup.snar \
/home/user/
Respaldo incremental (solo archivos modificados):
# Incremental backup 1
tar -czf incremental-1.tar.gz \
--listed-incremental=backup.snar \
/home/user/
# Incremental backup 2
tar -czf incremental-2.tar.gz \
--listed-incremental=backup.snar \
/home/user/
Restaurar respaldos incrementales:
# Restore must be in order
tar -xzf full-backup.tar.gz --listed-incremental=/dev/null
tar -xzf incremental-1.tar.gz --listed-incremental=/dev/null
tar -xzf incremental-2.tar.gz --listed-incremental=/dev/null
Excluyendo Archivos y Directorios
Patrones de exclusión:
# Exclude specific files/directories
tar -czf backup.tar.gz \
--exclude='*.log' \
--exclude='*.tmp' \
--exclude='cache' \
--exclude='node_modules' \
/var/www/
Archivo de exclusión:
Crear /etc/tar-exclude.txt:
*.log
*.tmp
.cache
cache/
tmp/
*.swp
node_modules/
vendor/
__pycache__/
.git/
Usar con tar:
tar -czf backup.tar.gz \
--exclude-from=/etc/tar-exclude.txt \
/var/www/
Excluir control de versiones:
tar -czf backup.tar.gz --exclude-vcs /project/
# Excludes .git, .svn, .hg, etc.
Inclusión Selectiva de Archivos
Incluir solo archivos específicos:
# Backup only .conf files
tar -czf configs.tar.gz \
--wildcards \
--no-recursion \
$(find /etc -name '*.conf')
Respaldar tipos de archivos específicos:
# All PHP and HTML files
find /var/www -name '*.php' -o -name '*.html' | \
tar -czf web-files.tar.gz -T -
Preservando Metadatos y Permisos
# Preserve all attributes (default)
tar -czpf backup.tar.gz /data/
# Preserve permissions (-p)
tar -czpf backup.tar.gz /data/
# Preserve SELinux context
tar -czf backup.tar.gz --selinux /data/
# Preserve extended attributes
tar -czf backup.tar.gz --xattrs /data/
# Preserve ACLs
tar -czf backup.tar.gz --acls /data/
# All preservation options
tar -czf backup.tar.gz \
--preserve-permissions \
--selinux \
--xattrs \
--acls \
/data/
Scripts de Respaldo en Producción
Script de Respaldo Completo
#!/bin/bash
# /usr/local/bin/tar-backup.sh
# Production tar-based backup with rotation and verification
set -euo pipefail
# Configuration
BACKUP_NAME="backup-$(hostname)-$(date +%Y%m%d-%H%M%S)"
BACKUP_ROOT="/backup"
BACKUP_PATH="$BACKUP_ROOT/$BACKUP_NAME.tar.gz"
LOG_FILE="/var/log/tar-backup.log"
RETENTION_DAYS=30
ADMIN_EMAIL="[email protected]"
# Sources to backup
BACKUP_SOURCES=(
"/etc"
"/home"
"/var/www"
"/opt"
"/root"
)
# Exclude file
EXCLUDE_FILE="/etc/tar-exclude.txt"
# Logging
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
error_exit() {
log "ERROR: $1"
echo "Backup failed: $1" | mail -s "Backup FAILED - $(hostname)" "$ADMIN_EMAIL"
exit 1
}
# Create exclude file if doesn't exist
if [ ! -f "$EXCLUDE_FILE" ]; then
cat > "$EXCLUDE_FILE" << 'EOF'
*.log
*.tmp
.cache/
tmp/
cache/
node_modules/
vendor/
__pycache__/
.git/
lost+found/
*.swp
EOF
fi
log "Starting backup: $BACKUP_NAME"
# Pre-backup: Database dumps
log "Creating database dumps"
mkdir -p /var/backups/db-dumps
if command -v mysqldump &> /dev/null; then
mysqldump --all-databases --single-transaction | \
gzip > /var/backups/db-dumps/mysql-all.sql.gz
fi
if command -v pg_dumpall &> /dev/null; then
sudo -u postgres pg_dumpall | \
gzip > /var/backups/db-dumps/postgresql-all.sql.gz
fi
# Create tar backup with parallel compression
log "Creating compressed archive"
tar -cf - \
--exclude-from="$EXCLUDE_FILE" \
--exclude-caches \
--exclude-vcs \
"${BACKUP_SOURCES[@]}" \
/var/backups/db-dumps \
2>> "$LOG_FILE" | \
pigz -p $(nproc) > "$BACKUP_PATH"
if [ ${PIPESTATUS[0]} -ne 0 ]; then
error_exit "Tar command failed"
fi
# Verify archive integrity
log "Verifying archive integrity"
if ! gzip -t "$BACKUP_PATH" 2>> "$LOG_FILE"; then
error_exit "Archive integrity check failed"
fi
# Check archive size
ARCHIVE_SIZE=$(stat -c%s "$BACKUP_PATH" 2>/dev/null || stat -f%z "$BACKUP_PATH")
MIN_SIZE=1048576 # 1MB minimum
if [ "$ARCHIVE_SIZE" -lt "$MIN_SIZE" ]; then
error_exit "Archive suspiciously small: $ARCHIVE_SIZE bytes"
fi
# Create checksum
log "Creating checksum"
sha256sum "$BACKUP_PATH" > "$BACKUP_PATH.sha256"
# Create manifest
log "Creating manifest"
cat > "$BACKUP_ROOT/$BACKUP_NAME.txt" << EOF
Backup Manifest
Date: $(date)
Server: $(hostname)
Archive: $BACKUP_NAME.tar.gz
Size: $(du -h "$BACKUP_PATH" | cut -f1)
Checksum: $(cat "$BACKUP_PATH.sha256")
Sources:
$(printf '%s\n' "${BACKUP_SOURCES[@]}")
File count: $(tar -tzf "$BACKUP_PATH" | wc -l)
EOF
# Cleanup old backups
log "Cleaning up old backups"
find "$BACKUP_ROOT" -name "backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_ROOT" -name "backup-*.txt" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_ROOT" -name "backup-*.sha256" -mtime +$RETENTION_DAYS -delete
# Cleanup old database dumps
find /var/backups/db-dumps -name "*.sql.gz" -mtime +3 -delete
log "Backup completed successfully"
# Success notification
{
echo "Backup completed successfully"
echo ""
cat "$BACKUP_ROOT/$BACKUP_NAME.txt"
} | mail -s "Backup Success - $(hostname)" "$ADMIN_EMAIL"
exit 0
Hacer ejecutable:
sudo chmod +x /usr/local/bin/tar-backup.sh
Script de Respaldo Rotativo con Retención Escalonada
#!/bin/bash
# /usr/local/bin/tar-rotating-backup.sh
# Implements GFS (Grandfather-Father-Son) rotation
BACKUP_TYPE="$1" # daily, weekly, or monthly
BACKUP_ROOT="/backup/tar"
DATE=$(date +%Y%m%d)
SOURCES="/etc /home /var/www"
case "$BACKUP_TYPE" in
daily)
BACKUP_FILE="$BACKUP_ROOT/daily/backup-daily-$DATE.tar.gz"
KEEP_DAYS=7
;;
weekly)
BACKUP_FILE="$BACKUP_ROOT/weekly/backup-weekly-$(date +%YW%V).tar.gz"
KEEP_DAYS=28
;;
monthly)
BACKUP_FILE="$BACKUP_ROOT/monthly/backup-monthly-$(date +%Y%m).tar.gz"
KEEP_DAYS=365
;;
*)
echo "Usage: $0 {daily|weekly|monthly}"
exit 1
;;
esac
# Create backup directory
mkdir -p "$(dirname "$BACKUP_FILE")"
# Create backup
echo "Creating $BACKUP_TYPE backup: $BACKUP_FILE"
tar -czf "$BACKUP_FILE" \
--exclude='*.log' \
--exclude='cache' \
--exclude='tmp' \
$SOURCES
# Cleanup old backups
find "$(dirname "$BACKUP_FILE")" -name "*.tar.gz" -mtime +$KEEP_DAYS -delete
echo "$BACKUP_TYPE backup completed: $BACKUP_FILE"
Programación Cron:
# Daily backup at 2 AM
0 2 * * * /usr/local/bin/tar-rotating-backup.sh daily
# Weekly backup on Sunday at 3 AM
0 3 * * 0 /usr/local/bin/tar-rotating-backup.sh weekly
# Monthly backup on 1st at 4 AM
0 4 1 * * /usr/local/bin/tar-rotating-backup.sh monthly
Procedimientos de Restauración
Restauración Básica
# Extract entire archive
tar -xzf backup.tar.gz
# Extract to specific location
tar -xzf backup.tar.gz -C /restore/path/
# Extract with verbose output
tar -xzvf backup.tar.gz
# Extract and overwrite existing files
tar -xzf backup.tar.gz --overwrite
Restauración Selectiva
# List archive contents first
tar -tzf backup.tar.gz | grep important-file.txt
# Extract specific file
tar -xzf backup.tar.gz path/to/important-file.txt
# Extract directory
tar -xzf backup.tar.gz path/to/directory/
# Extract multiple items
tar -xzf backup.tar.gz \
path/to/file1.txt \
path/to/file2.txt \
path/to/directory/
# Extract files matching pattern
tar -xzf backup.tar.gz --wildcards '*.conf'
# Extract to stdout (view without extracting)
tar -xzf backup.tar.gz -O path/to/file.txt
Recuperación ante Desastres
Restauración completa del sistema:
# Boot from live USB
# Mount target filesystem
mount /dev/sda1 /mnt/target
# Extract backup
cd /mnt/target
tar -xzf /backup/full-system-backup.tar.gz
# Restore bootloader
grub-install --root-directory=/mnt/target /dev/sda
update-grub
# Reboot
reboot
Verificación Después de la Restauración
# Compare restored files with archive
tar -tzf backup.tar.gz > archive-files.txt
find /restored/path -type f > restored-files.txt
diff archive-files.txt restored-files.txt
# Verify file counts match
ARCHIVE_COUNT=$(tar -tzf backup.tar.gz | wc -l)
RESTORED_COUNT=$(find /restored/path | wc -l)
echo "Archive: $ARCHIVE_COUNT | Restored: $RESTORED_COUNT"
Automatización y Monitoreo
Implementación de Temporizador Systemd
Archivo de servicio (/etc/systemd/system/tar-backup.service):
[Unit]
Description=Tar Backup Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/tar-backup.sh
User=root
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
[Install]
WantedBy=multi-user.target
Archivo de temporizador (/etc/systemd/system/tar-backup.timer):
[Unit]
Description=Daily Tar Backup
Requires=tar-backup.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Habilitar:
sudo systemctl daemon-reload
sudo systemctl enable --now tar-backup.timer
Script de Monitoreo
#!/bin/bash
# /usr/local/bin/monitor-tar-backups.sh
BACKUP_DIR="/backup"
MAX_AGE_HOURS=26
ADMIN_EMAIL="[email protected]"
# Find latest backup
LATEST_BACKUP=$(find "$BACKUP_DIR" -name "backup-*.tar.gz" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)
if [ -z "$LATEST_BACKUP" ]; then
echo "ERROR: No backups found" | \
mail -s "Backup Monitoring Alert" "$ADMIN_EMAIL"
exit 1
fi
# Check age
BACKUP_TIME=$(stat -c %Y "$LATEST_BACKUP")
CURRENT_TIME=$(date +%s)
AGE_HOURS=$(( (CURRENT_TIME - BACKUP_TIME) / 3600 ))
if [ $AGE_HOURS -gt $MAX_AGE_HOURS ]; then
echo "WARNING: Latest backup is $AGE_HOURS hours old" | \
mail -s "Backup Age Alert" "$ADMIN_EMAIL"
exit 1
else
echo "OK: Latest backup is $AGE_HOURS hours old"
exit 0
fi
Escenarios del Mundo Real
Escenario 1: Respaldo de Sitio Web
#!/bin/bash
# Website backup with database
BACKUP_DIR="/backup/website"
DATE=$(date +%Y%m%d)
# Dump database
mysqldump website_db | gzip > /tmp/website-db.sql.gz
# Create tar backup
tar -czf "$BACKUP_DIR/website-$DATE.tar.gz" \
--exclude='cache/*' \
--exclude='logs/*' \
/var/www/website/ \
/tmp/website-db.sql.gz
# Cleanup
rm /tmp/website-db.sql.gz
# Keep 30 days
find "$BACKUP_DIR" -name "website-*.tar.gz" -mtime +30 -delete
Escenario 2: Respaldo de Configuración
#!/bin/bash
# System configuration backup
tar -czf /backup/config-$(date +%Y%m%d).tar.gz \
/etc \
/root/.ssh \
/home/*/.ssh \
/var/spool/cron \
--exclude='/etc/shadow-' \
--exclude='/etc/gshadow-'
Escenario 3: Respaldo Fuera del Sitio
#!/bin/bash
# Create backup and sync to remote server
# Create backup
/usr/local/bin/tar-backup.sh
# Sync to remote
rsync -avz --delete \
/backup/ \
user@backup-server:/backups/$(hostname)/
# Upload to S3
LATEST=$(ls -t /backup/backup-*.tar.gz | head -1)
aws s3 cp "$LATEST" s3://my-backups/$(hostname)/
Conclusión
Tar y gzip proporcionan soluciones de respaldo confiables y universales que funcionan en todos los sistemas Unix/Linux. Aunque las herramientas modernas de respaldo ofrecen características avanzadas, tar+gzip sigue siendo relevante por su simplicidad, portabilidad y efectividad.
Puntos clave:
- Elige la compresión sabiamente: Equilibra velocidad vs. tamaño según tus necesidades
- Excluye datos innecesarios: Usa patrones de exclusión para optimizar respaldos
- Verifica archivos: Siempre prueba la integridad del archivo después de la creación
- Automatiza consistentemente: Programa respaldos automáticos regulares
- Prueba la restauración: Practica procedimientos de restauración regularmente
- Implementa retención: La limpieza automática previene el agotamiento del disco
- Sigue 3-2-1: Respaldos tar locales, remotos y fuera del sitio
Combinado con automatización adecuada, monitoreo y la regla de respaldo 3-2-1, tar y gzip proporcionan una base sólida para la protección de datos en entornos Linux.


