[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-/blog/tutorial/respaldos-incrementales-rsync-bash":3,"prev-/blog/tutorial/respaldos-incrementales-rsync-bash":3316,"next-/blog/tutorial/respaldos-incrementales-rsync-bash":3319,"related-/blog/tutorial/respaldos-incrementales-rsync-bash":3322},{"id":4,"title":5,"author":6,"authorUrl":7,"body":8,"category":3284,"cta":3285,"date":3288,"dateModified":3288,"description":3289,"draft":3290,"extension":3291,"faq":3292,"featured":3290,"image":3305,"imageAlt":3306,"meta":3307,"navigation":410,"path":3308,"readingTime":444,"seo":3309,"stem":3310,"tags":3311,"__hash__":3315},"blog/blog/tutorial/respaldos-incrementales-rsync-bash.md","Respaldos incrementales con rsync y scripts Bash","Syswork México","/nosotros",{"type":9,"value":10,"toc":3264},"minimark",[11,21,26,29,94,98,101,124,132,136,139,161,215,242,247,273,277,313,316,320,323,361,371,379,382,386,2669,2671,2675,2713,2716,2791,2795,2810,2827,2831,2834,2897,2906,2910,2913,2944,2947,2972,2986,2988,2992,2996,3076,3080,3109,3113,3197,3200,3204,3207,3251,3260],[12,13,14,15,20],"p",{},"El ",[16,17,19],"a",{"href":18},"/blog/backup-automatizado-python-cron","backup con Python"," que construimos antes es perfecto para bases de datos y archivos que necesitan lógica de procesamiento. Pero para respaldos de archivos puros — directorios de datos, uploads de usuarios, configuraciones de servidor — rsync es más eficiente: solo transfiere los bytes que cambiaron, maneja permisos y ownership correctamente, y con hard links puedes mantener versiones diarias que ocupan una fracción del espacio total.",[22,23,25],"h2",{"id":24},"por-qué-rsync","¿Por qué rsync?",[12,27,28],{},"rsync compara los archivos entre origen y destino y solo transfiere las diferencias. Cuando combinas rsync con hard links, obtienes lo mejor de los dos mundos — backups rápidos (solo se copian los cambios) con restauración simple (cada backup es una carpeta completa que puedes navegar y copiar directamente).",[30,31,32,51],"table",{},[33,34,35],"thead",{},[36,37,38,42,45,48],"tr",{},[39,40,41],"th",{},"Método",[39,43,44],{},"Primer backup 100 GB",[39,46,47],{},"Backup diario (500 MB cambios)",[39,49,50],{},"30 días de backups",[52,53,54,68,81],"tbody",{},[36,55,56,60,63,65],{},[57,58,59],"td",{},"cp -r",[57,61,62],{},"100 GB, 30 min",[57,64,62],{},[57,66,67],{},"3 TB",[36,69,70,73,76,78],{},[57,71,72],{},"tar.gz",[57,74,75],{},"100 GB, 45 min",[57,77,75],{},[57,79,80],{},"3 TB (comprimido ~1 TB)",[36,82,83,86,88,91],{},[57,84,85],{},"rsync incremental",[57,87,62],{},[57,89,90],{},"500 MB, 30 seg",[57,92,93],{},"~115 GB",[22,95,97],{"id":96},"requisitos-previos","Requisitos previos",[12,99,100],{},"rsync viene preinstalado en Ubuntu. Verifica:",[102,103,108],"pre",{"className":104,"code":105,"language":106,"meta":107,"style":107},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","rsync --version\n","bash","",[109,110,111],"code",{"__ignoreMap":107},[112,113,116,120],"span",{"class":114,"line":115},"line",1,[112,117,119],{"class":118},"sbgvK","rsync",[112,121,123],{"class":122},"stzsN"," --version\n",[12,125,126,127,131],{},"Si respaldar a un servidor remoto, necesitas acceso SSH con ",[16,128,130],{"href":129},"/blog/hardening-servidores-linux","llaves"," (sin contraseña).",[22,133,135],{"id":134},"paso-1-rsync-básico","Paso 1: rsync básico",[12,137,138],{},"Antes de automatizar, entiende el comando base:",[102,140,142],{"className":104,"code":141,"language":106,"meta":107,"style":107},"rsync -avz --delete /origen/ /destino/\n",[109,143,144],{"__ignoreMap":107},[112,145,146,148,151,154,158],{"class":114,"line":115},[112,147,119],{"class":118},[112,149,150],{"class":122}," -avz",[112,152,153],{"class":122}," --delete",[112,155,157],{"class":156},"s_sjI"," /origen/",[112,159,160],{"class":156}," /destino/\n",[30,162,163,173],{},[33,164,165],{},[36,166,167,170],{},[39,168,169],{},"Flag",[39,171,172],{},"Función",[52,174,175,185,195,205],{},[36,176,177,182],{},[57,178,179],{},[109,180,181],{},"-a",[57,183,184],{},"Archive — preserva permisos, ownership, timestamps, symlinks",[36,186,187,192],{},[57,188,189],{},[109,190,191],{},"-v",[57,193,194],{},"Verbose — muestra los archivos que transfiere",[36,196,197,202],{},[57,198,199],{},[109,200,201],{},"-z",[57,203,204],{},"Compress — comprime durante la transferencia (útil en remoto)",[36,206,207,212],{},[57,208,209],{},[109,210,211],{},"--delete",[57,213,214],{},"Elimina archivos en destino que ya no existen en origen",[216,217,220],"alert",{"title":218,"type":219},"La barra final importa","warning",[12,221,222,225,226,229,230,233,234,237,238,241],{},[109,223,224],{},"/origen/"," (con barra) copia el contenido del directorio. ",[109,227,228],{},"/origen"," (sin barra) copia el directorio mismo. La diferencia: ",[109,231,232],{},"/datos/"," → los archivos de datos van directo al destino. ",[109,235,236],{},"/datos"," → se crea una carpeta ",[109,239,240],{},"datos"," dentro del destino. Para backups, generalmente quieres la barra.",[243,244,246],"h3",{"id":245},"ejemplo-backup-local","Ejemplo: backup local",[102,248,250],{"className":104,"code":249,"language":106,"meta":107,"style":107},"# Respaldar /var/www a /backup\nrsync -avz --delete /var/www/ /backup/www/\n",[109,251,252,258],{"__ignoreMap":107},[112,253,254],{"class":114,"line":115},[112,255,257],{"class":256},"sutJx","# Respaldar /var/www a /backup\n",[112,259,261,263,265,267,270],{"class":114,"line":260},2,[112,262,119],{"class":118},[112,264,150],{"class":122},[112,266,153],{"class":122},[112,268,269],{"class":156}," /var/www/",[112,271,272],{"class":156}," /backup/www/\n",[243,274,276],{"id":275},"ejemplo-backup-a-servidor-remoto","Ejemplo: backup a servidor remoto",[102,278,280],{"className":104,"code":279,"language":106,"meta":107,"style":107},"# Respaldar /var/www al servidor de backup\nrsync -avz --delete -e \"ssh -p 2222\" /var/www/ backup@10.0.1.50:/backups/web/\n",[109,281,282,287],{"__ignoreMap":107},[112,283,284],{"class":114,"line":115},[112,285,286],{"class":256},"# Respaldar /var/www al servidor de backup\n",[112,288,289,291,293,295,298,302,305,308,310],{"class":114,"line":260},[112,290,119],{"class":118},[112,292,150],{"class":122},[112,294,153],{"class":122},[112,296,297],{"class":122}," -e",[112,299,301],{"class":300},"sjJ54"," \"",[112,303,304],{"class":156},"ssh -p 2222",[112,306,307],{"class":300},"\"",[112,309,269],{"class":156},[112,311,312],{"class":156}," backup@10.0.1.50:/backups/web/\n",[314,315],"ad-banner",{},[22,317,319],{"id":318},"paso-2-backups-incrementales-con-hard-links","Paso 2: Backups incrementales con hard links",[12,321,322],{},"La técnica de hard links es la joya de rsync para backups. Cada backup diario es una carpeta completa (puedes navegar y restaurar cualquier archivo directamente), pero los archivos que no cambiaron son hard links al backup anterior — no ocupan espacio adicional.",[102,324,326],{"className":104,"code":325,"language":106,"meta":107,"style":107},"rsync -avz --delete \\\n  --link-dest=/backup/latest \\\n  /datos/ \\\n  /backup/2026-01-08/\n",[109,327,328,340,347,355],{"__ignoreMap":107},[112,329,330,332,334,336],{"class":114,"line":115},[112,331,119],{"class":118},[112,333,150],{"class":122},[112,335,153],{"class":122},[112,337,339],{"class":338},"s_hVV"," \\\n",[112,341,342,345],{"class":114,"line":260},[112,343,344],{"class":122},"  --link-dest=/backup/latest",[112,346,339],{"class":338},[112,348,350,353],{"class":114,"line":349},3,[112,351,352],{"class":156},"  /datos/",[112,354,339],{"class":338},[112,356,358],{"class":114,"line":357},4,[112,359,360],{"class":156},"  /backup/2026-01-08/\n",[12,362,363,366,367,370],{},[109,364,365],{},"--link-dest"," le dice a rsync: \"antes de copiar un archivo, verifica si es idéntico al que está en ",[109,368,369],{},"/backup/latest",". Si es idéntico, crea un hard link en vez de copiar.\" El resultado: solo los archivos que cambiaron se copian realmente.",[102,372,377],{"className":373,"code":375,"language":376},[374],"language-text","/backup/\n├── 2026-01-06/      ← Backup del 6 (completo)\n│   ├── archivo1.txt   (inode 12345)\n│   ├── archivo2.txt   (inode 12346)\n│   └── archivo3.txt   (inode 12347)\n├── 2026-01-07/      ← Backup del 7 (solo archivo2 cambió)\n│   ├── archivo1.txt   (inode 12345) ← Hard link, 0 bytes extra\n│   ├── archivo2.txt   (inode 12400) ← Copia nueva, cambió\n│   └── archivo3.txt   (inode 12347) ← Hard link, 0 bytes extra\n├── 2026-01-08/      ← Backup del 8 (solo archivo1 cambió)\n│   ├── archivo1.txt   (inode 12500) ← Copia nueva, cambió\n│   ├── archivo2.txt   (inode 12400) ← Hard link al del 7\n│   └── archivo3.txt   (inode 12347) ← Hard link al del 6\n└── latest -> 2026-01-08/  ← Symlink al más reciente\n","text",[109,378,375],{"__ignoreMap":107},[12,380,381],{},"Cada carpeta parece un backup completo, pero solo los archivos modificados ocupan espacio real.",[22,383,385],{"id":384},"paso-3-script-de-backup-completo","Paso 3: Script de backup completo",[102,387,389],{"className":104,"code":388,"language":106,"meta":107,"style":107},"#!/bin/bash\n# backup-rsync.sh — Backup incremental con rsync y hard links\n# Uso: sudo ./backup-rsync.sh\n\nset -euo pipefail\n\n# =====================\n# CONFIGURACIÓN\n# =====================\nBACKUP_ROOT=\"/backup\"\nSOURCE_DIRS=(\n    \"/var/www\"\n    \"/etc/nginx\"\n    \"/etc/postgresql\"\n    \"/opt/apps\"\n    \"/home\"\n)\nRETENTION_DAYS=30\nLOG_DIR=\"${BACKUP_ROOT}/logs\"\nDATE=$(date +%Y-%m-%d_%H%M%S)\nBACKUP_DIR=\"${BACKUP_ROOT}/${DATE}\"\nLATEST_LINK=\"${BACKUP_ROOT}/latest\"\nLOG_FILE=\"${LOG_DIR}/backup-${DATE}.log\"\n\n# Servidor remoto (dejar vacío para backup local)\nREMOTE_HOST=\"\"\nREMOTE_DIR=\"\"\n# REMOTE_HOST=\"backup@10.0.1.50\"\n# REMOTE_DIR=\"/backups/servidor-web\"\n\n# Notificación Slack (opcional)\nSLACK_WEBHOOK=\"${SLACK_WEBHOOK:-}\"\n\n# =====================\n# FUNCIONES\n# =====================\nmkdir -p \"$LOG_DIR\"\n\nlog() {\n    echo \"[$(date '+%Y-%m-%d %H:%M:%S')] $1\" | tee -a \"$LOG_FILE\"\n}\n\nnotify_slack() {\n    local message=\"$1\"\n    local color=\"$2\"\n    if [[ -n \"$SLACK_WEBHOOK\" ]]; then\n        curl -s -X POST \"$SLACK_WEBHOOK\" \\\n            -H \"Content-Type: application/json\" \\\n            -d \"{\\\"attachments\\\":[{\\\"color\\\":\\\"${color}\\\",\\\"text\\\":\\\"${message}\\\"}]}\" \\\n            > /dev/null 2>&1 || true\n    fi\n}\n\ncleanup_old_backups() {\n    log \"Limpiando backups con más de ${RETENTION_DAYS} días...\"\n    local count=0\n    local target_dir=\"${1:-$BACKUP_ROOT}\"\n\n    find \"$target_dir\" -maxdepth 1 -type d -name \"20*\" -mtime +${RETENTION_DAYS} | sort | while read -r dir; do\n        log \"  Eliminando: $(basename \"$dir\")\"\n        rm -rf \"$dir\"\n        ((count++)) || true\n    done\n\n    log \"  Backups eliminados: ${count}\"\n}\n\n# =====================\n# EJECUCIÓN\n# =====================\nlog \"==========================================\"\nlog \"BACKUP INICIADO — ${DATE}\"\nlog \"==========================================\"\n\nSTART_TIME=$(date +%s)\nTOTAL_SIZE=0\nERRORS=0\n\n# Crear directorio de backup\nmkdir -p \"$BACKUP_DIR\"\n\n# Construir --link-dest\nLINK_DEST_FLAG=\"\"\nif [[ -L \"$LATEST_LINK\" ]] && [[ -d \"$LATEST_LINK\" ]]; then\n    LINK_DEST_FLAG=\"--link-dest=${LATEST_LINK}\"\n    log \"Usando link-dest: $(readlink -f \"$LATEST_LINK\")\"\nelse\n    log \"Sin link-dest (primer backup completo)\"\nfi\n\n# Respaldar cada directorio\nfor SRC in \"${SOURCE_DIRS[@]}\"; do\n    if [[ ! -d \"$SRC\" ]]; then\n        log \"  ⚠ ${SRC} no existe, saltando...\"\n        continue\n    fi\n\n    DEST_NAME=$(echo \"$SRC\" | tr '/' '_' | sed 's/^_//')\n    DEST=\"${BACKUP_DIR}/${DEST_NAME}\"\n    mkdir -p \"$DEST\"\n\n    log \"Respaldando: ${SRC} → ${DEST_NAME}\"\n\n    if rsync -a --delete $LINK_DEST_FLAG \\\n        --exclude='.cache' \\\n        --exclude='node_modules' \\\n        --exclude='__pycache__' \\\n        --exclude='*.log' \\\n        --exclude='.git' \\\n        \"$SRC/\" \"$DEST/\" >> \"$LOG_FILE\" 2>&1; then\n\n        DIR_SIZE=$(du -sh \"$DEST\" | cut -f1)\n        log \"  ✓ ${SRC} completado (${DIR_SIZE})\"\n    else\n        log \"  ✗ ERROR en ${SRC}\"\n        ((ERRORS++)) || true\n    fi\ndone\n\n# Actualizar symlink latest\nrm -f \"$LATEST_LINK\"\nln -s \"$BACKUP_DIR\" \"$LATEST_LINK\"\n\n# Backup remoto (opcional)\nif [[ -n \"$REMOTE_HOST\" ]] && [[ -n \"$REMOTE_DIR\" ]]; then\n    log \"Sincronizando a servidor remoto: ${REMOTE_HOST}:${REMOTE_DIR}\"\n\n    if rsync -az --delete \\\n        -e \"ssh -o StrictHostKeyChecking=no\" \\\n        \"${BACKUP_DIR}/\" \\\n        \"${REMOTE_HOST}:${REMOTE_DIR}/${DATE}/\" >> \"$LOG_FILE\" 2>&1; then\n        log \"  ✓ Sincronización remota completada\"\n    else\n        log \"  ✗ ERROR en sincronización remota\"\n        ((ERRORS++)) || true\n    fi\nfi\n\n# Limpieza\ncleanup_old_backups \"$BACKUP_ROOT\"\n\n# Resumen\nEND_TIME=$(date +%s)\nDURATION=$((END_TIME - START_TIME))\nTOTAL_SIZE=$(du -sh \"$BACKUP_DIR\" | cut -f1)\nDISK_FREE=$(df -h \"$BACKUP_ROOT\" | tail -1 | awk '{print $4}')\n\nlog \"==========================================\"\nlog \"BACKUP COMPLETADO\"\nlog \"  Duración: ${DURATION}s\"\nlog \"  Tamaño: ${TOTAL_SIZE}\"\nlog \"  Errores: ${ERRORS}\"\nlog \"  Espacio libre: ${DISK_FREE}\"\nlog \"==========================================\"\n\n# Notificación\nif [[ $ERRORS -eq 0 ]]; then\n    notify_slack \"✅ Backup completado | ${TOTAL_SIZE} | ${DURATION}s | $(hostname)\" \"#36a64f\"\nelse\n    notify_slack \"🚨 Backup con ${ERRORS} error(es) | $(hostname) | Ver log: ${LOG_FILE}\" \"#ff0000\"\nfi\n\nexit $ERRORS\n",[109,390,391,396,401,406,412,425,430,436,442,447,466,478,489,499,509,519,529,535,546,567,586,611,630,658,663,669,680,690,696,702,707,713,730,735,740,746,751,767,772,785,834,840,845,855,873,890,916,939,954,1025,1043,1049,1054,1059,1069,1091,1105,1129,1134,1206,1230,1245,1264,1270,1275,1291,1296,1301,1306,1312,1317,1329,1345,1356,1361,1378,1388,1398,1403,1409,1423,1428,1434,1444,1483,1502,1526,1532,1544,1550,1555,1561,1590,1613,1635,1641,1646,1651,1703,1726,1741,1746,1771,1776,1794,1809,1823,1837,1851,1865,1900,1905,1937,1968,1974,1990,2005,2010,2016,2021,2027,2041,2061,2066,2072,2107,2131,2136,2150,2165,2181,2224,2236,2241,2253,2268,2273,2278,2283,2289,2300,2305,2311,2327,2349,2376,2420,2425,2436,2448,2469,2485,2501,2517,2528,2533,2539,2559,2603,2608,2650,2655,2660],{"__ignoreMap":107},[112,392,393],{"class":114,"line":115},[112,394,395],{"class":256},"#!/bin/bash\n",[112,397,398],{"class":114,"line":260},[112,399,400],{"class":256},"# backup-rsync.sh — Backup incremental con rsync y hard links\n",[112,402,403],{"class":114,"line":349},[112,404,405],{"class":256},"# Uso: sudo ./backup-rsync.sh\n",[112,407,408],{"class":114,"line":357},[112,409,411],{"emptyLinePlaceholder":410},true,"\n",[112,413,415,419,422],{"class":114,"line":414},5,[112,416,418],{"class":417},"sptTA","set",[112,420,421],{"class":122}," -euo",[112,423,424],{"class":156}," pipefail\n",[112,426,428],{"class":114,"line":427},6,[112,429,411],{"emptyLinePlaceholder":410},[112,431,433],{"class":114,"line":432},7,[112,434,435],{"class":256},"# =====================\n",[112,437,439],{"class":114,"line":438},8,[112,440,441],{"class":256},"# CONFIGURACIÓN\n",[112,443,445],{"class":114,"line":444},9,[112,446,435],{"class":256},[112,448,450,454,458,460,463],{"class":114,"line":449},10,[112,451,453],{"class":452},"su5hD","BACKUP_ROOT",[112,455,457],{"class":456},"smGrS","=",[112,459,307],{"class":300},[112,461,462],{"class":156},"/backup",[112,464,465],{"class":300},"\"\n",[112,467,469,472,474],{"class":114,"line":468},11,[112,470,471],{"class":452},"SOURCE_DIRS",[112,473,457],{"class":456},[112,475,477],{"class":476},"sP7_E","(\n",[112,479,481,484,487],{"class":114,"line":480},12,[112,482,483],{"class":300},"    \"",[112,485,486],{"class":156},"/var/www",[112,488,465],{"class":300},[112,490,492,494,497],{"class":114,"line":491},13,[112,493,483],{"class":300},[112,495,496],{"class":156},"/etc/nginx",[112,498,465],{"class":300},[112,500,502,504,507],{"class":114,"line":501},14,[112,503,483],{"class":300},[112,505,506],{"class":156},"/etc/postgresql",[112,508,465],{"class":300},[112,510,512,514,517],{"class":114,"line":511},15,[112,513,483],{"class":300},[112,515,516],{"class":156},"/opt/apps",[112,518,465],{"class":300},[112,520,522,524,527],{"class":114,"line":521},16,[112,523,483],{"class":300},[112,525,526],{"class":156},"/home",[112,528,465],{"class":300},[112,530,532],{"class":114,"line":531},17,[112,533,534],{"class":476},")\n",[112,536,538,541,543],{"class":114,"line":537},18,[112,539,540],{"class":452},"RETENTION_DAYS",[112,542,457],{"class":456},[112,544,545],{"class":156},"30\n",[112,547,549,552,554,557,559,562,565],{"class":114,"line":548},19,[112,550,551],{"class":452},"LOG_DIR",[112,553,457],{"class":456},[112,555,556],{"class":300},"\"${",[112,558,453],{"class":452},[112,560,561],{"class":300},"}",[112,563,564],{"class":156},"/logs",[112,566,465],{"class":300},[112,568,570,573,575,578,581,584],{"class":114,"line":569},20,[112,571,572],{"class":452},"DATE",[112,574,457],{"class":456},[112,576,577],{"class":476},"$(",[112,579,580],{"class":118},"date",[112,582,583],{"class":156}," +%Y-%m-%d_%H%M%S",[112,585,534],{"class":476},[112,587,589,592,594,596,598,600,603,606,608],{"class":114,"line":588},21,[112,590,591],{"class":452},"BACKUP_DIR",[112,593,457],{"class":456},[112,595,556],{"class":300},[112,597,453],{"class":452},[112,599,561],{"class":300},[112,601,602],{"class":156},"/",[112,604,605],{"class":300},"${",[112,607,572],{"class":452},[112,609,610],{"class":300},"}\"\n",[112,612,614,617,619,621,623,625,628],{"class":114,"line":613},22,[112,615,616],{"class":452},"LATEST_LINK",[112,618,457],{"class":456},[112,620,556],{"class":300},[112,622,453],{"class":452},[112,624,561],{"class":300},[112,626,627],{"class":156},"/latest",[112,629,465],{"class":300},[112,631,633,636,638,640,642,644,647,649,651,653,656],{"class":114,"line":632},23,[112,634,635],{"class":452},"LOG_FILE",[112,637,457],{"class":456},[112,639,556],{"class":300},[112,641,551],{"class":452},[112,643,561],{"class":300},[112,645,646],{"class":156},"/backup-",[112,648,605],{"class":300},[112,650,572],{"class":452},[112,652,561],{"class":300},[112,654,655],{"class":156},".log",[112,657,465],{"class":300},[112,659,661],{"class":114,"line":660},24,[112,662,411],{"emptyLinePlaceholder":410},[112,664,666],{"class":114,"line":665},25,[112,667,668],{"class":256},"# Servidor remoto (dejar vacío para backup local)\n",[112,670,672,675,677],{"class":114,"line":671},26,[112,673,674],{"class":452},"REMOTE_HOST",[112,676,457],{"class":456},[112,678,679],{"class":300},"\"\"\n",[112,681,683,686,688],{"class":114,"line":682},27,[112,684,685],{"class":452},"REMOTE_DIR",[112,687,457],{"class":456},[112,689,679],{"class":300},[112,691,693],{"class":114,"line":692},28,[112,694,695],{"class":256},"# REMOTE_HOST=\"backup@10.0.1.50\"\n",[112,697,699],{"class":114,"line":698},29,[112,700,701],{"class":256},"# REMOTE_DIR=\"/backups/servidor-web\"\n",[112,703,705],{"class":114,"line":704},30,[112,706,411],{"emptyLinePlaceholder":410},[112,708,710],{"class":114,"line":709},31,[112,711,712],{"class":256},"# Notificación Slack (opcional)\n",[112,714,716,719,721,723,725,728],{"class":114,"line":715},32,[112,717,718],{"class":452},"SLACK_WEBHOOK",[112,720,457],{"class":456},[112,722,556],{"class":300},[112,724,718],{"class":452},[112,726,727],{"class":456},":-",[112,729,610],{"class":300},[112,731,733],{"class":114,"line":732},33,[112,734,411],{"emptyLinePlaceholder":410},[112,736,738],{"class":114,"line":737},34,[112,739,435],{"class":256},[112,741,743],{"class":114,"line":742},35,[112,744,745],{"class":256},"# FUNCIONES\n",[112,747,749],{"class":114,"line":748},36,[112,750,435],{"class":256},[112,752,754,757,760,762,765],{"class":114,"line":753},37,[112,755,756],{"class":118},"mkdir",[112,758,759],{"class":122}," -p",[112,761,301],{"class":300},[112,763,764],{"class":452},"$LOG_DIR",[112,766,465],{"class":300},[112,768,770],{"class":114,"line":769},38,[112,771,411],{"emptyLinePlaceholder":410},[112,773,775,779,782],{"class":114,"line":774},39,[112,776,778],{"class":777},"sGLFI","log",[112,780,781],{"class":476},"()",[112,783,784],{"class":476}," {\n",[112,786,788,791,793,796,798,800,803,806,809,812,816,818,821,824,827,829,832],{"class":114,"line":787},40,[112,789,790],{"class":417},"    echo",[112,792,301],{"class":300},[112,794,795],{"class":156},"[",[112,797,577],{"class":300},[112,799,580],{"class":118},[112,801,802],{"class":300}," '",[112,804,805],{"class":156},"+%Y-%m-%d %H:%M:%S",[112,807,808],{"class":300},"')",[112,810,811],{"class":156},"] ",[112,813,815],{"class":814},"sfi6f","$1",[112,817,307],{"class":300},[112,819,820],{"class":456}," |",[112,822,823],{"class":118}," tee",[112,825,826],{"class":122}," -a",[112,828,301],{"class":300},[112,830,831],{"class":452},"$LOG_FILE",[112,833,465],{"class":300},[112,835,837],{"class":114,"line":836},41,[112,838,839],{"class":476},"}\n",[112,841,843],{"class":114,"line":842},42,[112,844,411],{"emptyLinePlaceholder":410},[112,846,848,851,853],{"class":114,"line":847},43,[112,849,850],{"class":777},"notify_slack",[112,852,781],{"class":476},[112,854,784],{"class":476},[112,856,858,862,865,867,869,871],{"class":114,"line":857},44,[112,859,861],{"class":860},"sbsja","    local",[112,863,864],{"class":452}," message",[112,866,457],{"class":456},[112,868,307],{"class":300},[112,870,815],{"class":814},[112,872,465],{"class":300},[112,874,876,878,881,883,885,888],{"class":114,"line":875},45,[112,877,861],{"class":860},[112,879,880],{"class":452}," color",[112,882,457],{"class":456},[112,884,307],{"class":300},[112,886,887],{"class":814},"$2",[112,889,465],{"class":300},[112,891,893,897,900,903,905,908,910,913],{"class":114,"line":892},46,[112,894,896],{"class":895},"sVHd0","    if",[112,898,899],{"class":476}," [[",[112,901,902],{"class":456}," -n",[112,904,301],{"class":300},[112,906,907],{"class":452},"$SLACK_WEBHOOK",[112,909,307],{"class":300},[112,911,912],{"class":476}," ]];",[112,914,915],{"class":895}," then\n",[112,917,919,922,925,928,931,933,935,937],{"class":114,"line":918},47,[112,920,921],{"class":118},"        curl",[112,923,924],{"class":122}," -s",[112,926,927],{"class":122}," -X",[112,929,930],{"class":156}," POST",[112,932,301],{"class":300},[112,934,907],{"class":452},[112,936,307],{"class":300},[112,938,339],{"class":338},[112,940,942,945,947,950,952],{"class":114,"line":941},48,[112,943,944],{"class":122},"            -H",[112,946,301],{"class":300},[112,948,949],{"class":156},"Content-Type: application/json",[112,951,307],{"class":300},[112,953,339],{"class":338},[112,955,957,960,962,965,968,971,973,976,978,981,983,986,988,990,992,994,996,999,1001,1003,1005,1007,1009,1011,1014,1016,1018,1021,1023],{"class":114,"line":956},49,[112,958,959],{"class":122},"            -d",[112,961,301],{"class":300},[112,963,964],{"class":156},"{",[112,966,967],{"class":338},"\\\"",[112,969,970],{"class":156},"attachments",[112,972,967],{"class":338},[112,974,975],{"class":156},":[{",[112,977,967],{"class":338},[112,979,980],{"class":156},"color",[112,982,967],{"class":338},[112,984,985],{"class":156},":",[112,987,967],{"class":338},[112,989,605],{"class":300},[112,991,980],{"class":452},[112,993,561],{"class":300},[112,995,967],{"class":338},[112,997,998],{"class":156},",",[112,1000,967],{"class":338},[112,1002,376],{"class":156},[112,1004,967],{"class":338},[112,1006,985],{"class":156},[112,1008,967],{"class":338},[112,1010,605],{"class":300},[112,1012,1013],{"class":452},"message",[112,1015,561],{"class":300},[112,1017,967],{"class":338},[112,1019,1020],{"class":156},"}]}",[112,1022,307],{"class":300},[112,1024,339],{"class":338},[112,1026,1028,1031,1034,1037,1040],{"class":114,"line":1027},50,[112,1029,1030],{"class":456},"            >",[112,1032,1033],{"class":156}," /dev/null",[112,1035,1036],{"class":456}," 2>&1",[112,1038,1039],{"class":456}," ||",[112,1041,1042],{"class":417}," true\n",[112,1044,1046],{"class":114,"line":1045},51,[112,1047,1048],{"class":895},"    fi\n",[112,1050,1052],{"class":114,"line":1051},52,[112,1053,839],{"class":476},[112,1055,1057],{"class":114,"line":1056},53,[112,1058,411],{"emptyLinePlaceholder":410},[112,1060,1062,1065,1067],{"class":114,"line":1061},54,[112,1063,1064],{"class":777},"cleanup_old_backups",[112,1066,781],{"class":476},[112,1068,784],{"class":476},[112,1070,1072,1075,1077,1080,1082,1084,1086,1089],{"class":114,"line":1071},55,[112,1073,1074],{"class":118},"    log",[112,1076,301],{"class":300},[112,1078,1079],{"class":156},"Limpiando backups con más de ",[112,1081,605],{"class":300},[112,1083,540],{"class":452},[112,1085,561],{"class":300},[112,1087,1088],{"class":156}," días...",[112,1090,465],{"class":300},[112,1092,1094,1096,1099,1101],{"class":114,"line":1093},56,[112,1095,861],{"class":860},[112,1097,1098],{"class":452}," count",[112,1100,457],{"class":456},[112,1102,1104],{"class":1103},"srdBf","0\n",[112,1106,1108,1110,1113,1115,1117,1120,1122,1125,1127],{"class":114,"line":1107},57,[112,1109,861],{"class":860},[112,1111,1112],{"class":452}," target_dir",[112,1114,457],{"class":456},[112,1116,307],{"class":300},[112,1118,1119],{"class":814},"${1",[112,1121,727],{"class":456},[112,1123,1124],{"class":452},"$BACKUP_ROOT",[112,1126,561],{"class":814},[112,1128,465],{"class":300},[112,1130,1132],{"class":114,"line":1131},58,[112,1133,411],{"emptyLinePlaceholder":410},[112,1135,1137,1140,1142,1145,1147,1150,1153,1156,1159,1162,1164,1167,1169,1172,1175,1177,1179,1181,1183,1186,1188,1191,1194,1197,1200,1203],{"class":114,"line":1136},59,[112,1138,1139],{"class":118},"    find",[112,1141,301],{"class":300},[112,1143,1144],{"class":452},"$target_dir",[112,1146,307],{"class":300},[112,1148,1149],{"class":122}," -maxdepth",[112,1151,1152],{"class":1103}," 1",[112,1154,1155],{"class":122}," -type",[112,1157,1158],{"class":156}," d",[112,1160,1161],{"class":122}," -name",[112,1163,301],{"class":300},[112,1165,1166],{"class":156},"20*",[112,1168,307],{"class":300},[112,1170,1171],{"class":122}," -mtime",[112,1173,1174],{"class":156}," +",[112,1176,605],{"class":476},[112,1178,540],{"class":452},[112,1180,561],{"class":476},[112,1182,820],{"class":456},[112,1184,1185],{"class":118}," sort",[112,1187,820],{"class":456},[112,1189,1190],{"class":895}," while",[112,1192,1193],{"class":417}," read",[112,1195,1196],{"class":122}," -r",[112,1198,1199],{"class":156}," dir",[112,1201,1202],{"class":476},";",[112,1204,1205],{"class":895}," do\n",[112,1207,1209,1212,1214,1217,1219,1222,1224,1227],{"class":114,"line":1208},60,[112,1210,1211],{"class":118},"        log",[112,1213,301],{"class":300},[112,1215,1216],{"class":156},"  Eliminando: ",[112,1218,577],{"class":300},[112,1220,1221],{"class":118},"basename",[112,1223,301],{"class":300},[112,1225,1226],{"class":452},"$dir",[112,1228,1229],{"class":300},"\")\"\n",[112,1231,1233,1236,1239,1241,1243],{"class":114,"line":1232},61,[112,1234,1235],{"class":118},"        rm",[112,1237,1238],{"class":122}," -rf",[112,1240,301],{"class":300},[112,1242,1226],{"class":452},[112,1244,465],{"class":300},[112,1246,1248,1251,1254,1257,1260,1262],{"class":114,"line":1247},62,[112,1249,1250],{"class":476},"        ((",[112,1252,1253],{"class":452},"count",[112,1255,1256],{"class":456},"++",[112,1258,1259],{"class":476},"))",[112,1261,1039],{"class":456},[112,1263,1042],{"class":417},[112,1265,1267],{"class":114,"line":1266},63,[112,1268,1269],{"class":895},"    done\n",[112,1271,1273],{"class":114,"line":1272},64,[112,1274,411],{"emptyLinePlaceholder":410},[112,1276,1278,1280,1282,1285,1287,1289],{"class":114,"line":1277},65,[112,1279,1074],{"class":118},[112,1281,301],{"class":300},[112,1283,1284],{"class":156},"  Backups eliminados: ",[112,1286,605],{"class":300},[112,1288,1253],{"class":452},[112,1290,610],{"class":300},[112,1292,1294],{"class":114,"line":1293},66,[112,1295,839],{"class":476},[112,1297,1299],{"class":114,"line":1298},67,[112,1300,411],{"emptyLinePlaceholder":410},[112,1302,1304],{"class":114,"line":1303},68,[112,1305,435],{"class":256},[112,1307,1309],{"class":114,"line":1308},69,[112,1310,1311],{"class":256},"# EJECUCIÓN\n",[112,1313,1315],{"class":114,"line":1314},70,[112,1316,435],{"class":256},[112,1318,1320,1322,1324,1327],{"class":114,"line":1319},71,[112,1321,778],{"class":118},[112,1323,301],{"class":300},[112,1325,1326],{"class":156},"==========================================",[112,1328,465],{"class":300},[112,1330,1332,1334,1336,1339,1341,1343],{"class":114,"line":1331},72,[112,1333,778],{"class":118},[112,1335,301],{"class":300},[112,1337,1338],{"class":156},"BACKUP INICIADO — ",[112,1340,605],{"class":300},[112,1342,572],{"class":452},[112,1344,610],{"class":300},[112,1346,1348,1350,1352,1354],{"class":114,"line":1347},73,[112,1349,778],{"class":118},[112,1351,301],{"class":300},[112,1353,1326],{"class":156},[112,1355,465],{"class":300},[112,1357,1359],{"class":114,"line":1358},74,[112,1360,411],{"emptyLinePlaceholder":410},[112,1362,1364,1367,1369,1371,1373,1376],{"class":114,"line":1363},75,[112,1365,1366],{"class":452},"START_TIME",[112,1368,457],{"class":456},[112,1370,577],{"class":476},[112,1372,580],{"class":118},[112,1374,1375],{"class":156}," +%s",[112,1377,534],{"class":476},[112,1379,1381,1384,1386],{"class":114,"line":1380},76,[112,1382,1383],{"class":452},"TOTAL_SIZE",[112,1385,457],{"class":456},[112,1387,1104],{"class":156},[112,1389,1391,1394,1396],{"class":114,"line":1390},77,[112,1392,1393],{"class":452},"ERRORS",[112,1395,457],{"class":456},[112,1397,1104],{"class":156},[112,1399,1401],{"class":114,"line":1400},78,[112,1402,411],{"emptyLinePlaceholder":410},[112,1404,1406],{"class":114,"line":1405},79,[112,1407,1408],{"class":256},"# Crear directorio de backup\n",[112,1410,1412,1414,1416,1418,1421],{"class":114,"line":1411},80,[112,1413,756],{"class":118},[112,1415,759],{"class":122},[112,1417,301],{"class":300},[112,1419,1420],{"class":452},"$BACKUP_DIR",[112,1422,465],{"class":300},[112,1424,1426],{"class":114,"line":1425},81,[112,1427,411],{"emptyLinePlaceholder":410},[112,1429,1431],{"class":114,"line":1430},82,[112,1432,1433],{"class":256},"# Construir --link-dest\n",[112,1435,1437,1440,1442],{"class":114,"line":1436},83,[112,1438,1439],{"class":452},"LINK_DEST_FLAG",[112,1441,457],{"class":456},[112,1443,679],{"class":300},[112,1445,1447,1450,1452,1455,1457,1460,1462,1465,1468,1470,1473,1475,1477,1479,1481],{"class":114,"line":1446},84,[112,1448,1449],{"class":895},"if",[112,1451,899],{"class":476},[112,1453,1454],{"class":456}," -L",[112,1456,301],{"class":300},[112,1458,1459],{"class":452},"$LATEST_LINK",[112,1461,307],{"class":300},[112,1463,1464],{"class":476}," ]]",[112,1466,1467],{"class":476}," &&",[112,1469,899],{"class":476},[112,1471,1472],{"class":456}," -d",[112,1474,301],{"class":300},[112,1476,1459],{"class":452},[112,1478,307],{"class":300},[112,1480,912],{"class":476},[112,1482,915],{"class":895},[112,1484,1486,1489,1491,1493,1496,1498,1500],{"class":114,"line":1485},85,[112,1487,1488],{"class":452},"    LINK_DEST_FLAG",[112,1490,457],{"class":456},[112,1492,307],{"class":300},[112,1494,1495],{"class":156},"--link-dest=",[112,1497,605],{"class":300},[112,1499,616],{"class":452},[112,1501,610],{"class":300},[112,1503,1505,1507,1509,1512,1514,1517,1520,1522,1524],{"class":114,"line":1504},86,[112,1506,1074],{"class":118},[112,1508,301],{"class":300},[112,1510,1511],{"class":156},"Usando link-dest: ",[112,1513,577],{"class":300},[112,1515,1516],{"class":118},"readlink",[112,1518,1519],{"class":122}," -f",[112,1521,301],{"class":300},[112,1523,1459],{"class":452},[112,1525,1229],{"class":300},[112,1527,1529],{"class":114,"line":1528},87,[112,1530,1531],{"class":895},"else\n",[112,1533,1535,1537,1539,1542],{"class":114,"line":1534},88,[112,1536,1074],{"class":118},[112,1538,301],{"class":300},[112,1540,1541],{"class":156},"Sin link-dest (primer backup completo)",[112,1543,465],{"class":300},[112,1545,1547],{"class":114,"line":1546},89,[112,1548,1549],{"class":895},"fi\n",[112,1551,1553],{"class":114,"line":1552},90,[112,1554,411],{"emptyLinePlaceholder":410},[112,1556,1558],{"class":114,"line":1557},91,[112,1559,1560],{"class":256},"# Respaldar cada directorio\n",[112,1562,1564,1567,1570,1573,1576,1578,1580,1583,1586,1588],{"class":114,"line":1563},92,[112,1565,1566],{"class":895},"for",[112,1568,1569],{"class":452}," SRC ",[112,1571,1572],{"class":895},"in",[112,1574,1575],{"class":300}," \"${",[112,1577,471],{"class":452},[112,1579,795],{"class":300},[112,1581,1582],{"class":456},"@",[112,1584,1585],{"class":300},"]}\"",[112,1587,1202],{"class":476},[112,1589,1205],{"class":895},[112,1591,1593,1595,1597,1600,1602,1604,1607,1609,1611],{"class":114,"line":1592},93,[112,1594,896],{"class":895},[112,1596,899],{"class":476},[112,1598,1599],{"class":456}," !",[112,1601,1472],{"class":456},[112,1603,301],{"class":300},[112,1605,1606],{"class":452},"$SRC",[112,1608,307],{"class":300},[112,1610,912],{"class":476},[112,1612,915],{"class":895},[112,1614,1616,1618,1620,1623,1625,1628,1630,1633],{"class":114,"line":1615},94,[112,1617,1211],{"class":118},[112,1619,301],{"class":300},[112,1621,1622],{"class":156},"  ⚠ ",[112,1624,605],{"class":300},[112,1626,1627],{"class":452},"SRC",[112,1629,561],{"class":300},[112,1631,1632],{"class":156}," no existe, saltando...",[112,1634,465],{"class":300},[112,1636,1638],{"class":114,"line":1637},95,[112,1639,1640],{"class":895},"        continue\n",[112,1642,1644],{"class":114,"line":1643},96,[112,1645,1048],{"class":895},[112,1647,1649],{"class":114,"line":1648},97,[112,1650,411],{"emptyLinePlaceholder":410},[112,1652,1654,1657,1659,1661,1664,1666,1668,1670,1672,1675,1677,1679,1682,1684,1687,1689,1691,1694,1696,1699,1701],{"class":114,"line":1653},98,[112,1655,1656],{"class":452},"    DEST_NAME",[112,1658,457],{"class":456},[112,1660,577],{"class":476},[112,1662,1663],{"class":417},"echo",[112,1665,301],{"class":300},[112,1667,1606],{"class":452},[112,1669,307],{"class":300},[112,1671,820],{"class":456},[112,1673,1674],{"class":118}," tr",[112,1676,802],{"class":300},[112,1678,602],{"class":156},[112,1680,1681],{"class":300},"'",[112,1683,802],{"class":300},[112,1685,1686],{"class":156},"_",[112,1688,1681],{"class":300},[112,1690,820],{"class":456},[112,1692,1693],{"class":118}," sed",[112,1695,802],{"class":300},[112,1697,1698],{"class":156},"s/^_//",[112,1700,1681],{"class":300},[112,1702,534],{"class":476},[112,1704,1706,1709,1711,1713,1715,1717,1719,1721,1724],{"class":114,"line":1705},99,[112,1707,1708],{"class":452},"    DEST",[112,1710,457],{"class":456},[112,1712,556],{"class":300},[112,1714,591],{"class":452},[112,1716,561],{"class":300},[112,1718,602],{"class":156},[112,1720,605],{"class":300},[112,1722,1723],{"class":452},"DEST_NAME",[112,1725,610],{"class":300},[112,1727,1729,1732,1734,1736,1739],{"class":114,"line":1728},100,[112,1730,1731],{"class":118},"    mkdir",[112,1733,759],{"class":122},[112,1735,301],{"class":300},[112,1737,1738],{"class":452},"$DEST",[112,1740,465],{"class":300},[112,1742,1744],{"class":114,"line":1743},101,[112,1745,411],{"emptyLinePlaceholder":410},[112,1747,1749,1751,1753,1756,1758,1760,1762,1765,1767,1769],{"class":114,"line":1748},102,[112,1750,1074],{"class":118},[112,1752,301],{"class":300},[112,1754,1755],{"class":156},"Respaldando: ",[112,1757,605],{"class":300},[112,1759,1627],{"class":452},[112,1761,561],{"class":300},[112,1763,1764],{"class":156}," → ",[112,1766,605],{"class":300},[112,1768,1723],{"class":452},[112,1770,610],{"class":300},[112,1772,1774],{"class":114,"line":1773},103,[112,1775,411],{"emptyLinePlaceholder":410},[112,1777,1779,1781,1784,1786,1788,1791],{"class":114,"line":1778},104,[112,1780,896],{"class":895},[112,1782,1783],{"class":118}," rsync",[112,1785,826],{"class":122},[112,1787,153],{"class":122},[112,1789,1790],{"class":452}," $LINK_DEST_FLAG ",[112,1792,1793],{"class":338},"\\\n",[112,1795,1797,1800,1802,1805,1807],{"class":114,"line":1796},105,[112,1798,1799],{"class":122},"        --exclude=",[112,1801,1681],{"class":300},[112,1803,1804],{"class":156},".cache",[112,1806,1681],{"class":300},[112,1808,339],{"class":338},[112,1810,1812,1814,1816,1819,1821],{"class":114,"line":1811},106,[112,1813,1799],{"class":122},[112,1815,1681],{"class":300},[112,1817,1818],{"class":156},"node_modules",[112,1820,1681],{"class":300},[112,1822,339],{"class":338},[112,1824,1826,1828,1830,1833,1835],{"class":114,"line":1825},107,[112,1827,1799],{"class":122},[112,1829,1681],{"class":300},[112,1831,1832],{"class":156},"__pycache__",[112,1834,1681],{"class":300},[112,1836,339],{"class":338},[112,1838,1840,1842,1844,1847,1849],{"class":114,"line":1839},108,[112,1841,1799],{"class":122},[112,1843,1681],{"class":300},[112,1845,1846],{"class":156},"*.log",[112,1848,1681],{"class":300},[112,1850,339],{"class":338},[112,1852,1854,1856,1858,1861,1863],{"class":114,"line":1853},109,[112,1855,1799],{"class":122},[112,1857,1681],{"class":300},[112,1859,1860],{"class":156},".git",[112,1862,1681],{"class":300},[112,1864,339],{"class":338},[112,1866,1868,1871,1873,1875,1877,1879,1881,1883,1885,1888,1890,1892,1894,1896,1898],{"class":114,"line":1867},110,[112,1869,1870],{"class":300},"        \"",[112,1872,1606],{"class":452},[112,1874,602],{"class":156},[112,1876,307],{"class":300},[112,1878,301],{"class":300},[112,1880,1738],{"class":452},[112,1882,602],{"class":156},[112,1884,307],{"class":300},[112,1886,1887],{"class":456}," >>",[112,1889,301],{"class":300},[112,1891,831],{"class":452},[112,1893,307],{"class":300},[112,1895,1036],{"class":456},[112,1897,1202],{"class":476},[112,1899,915],{"class":895},[112,1901,1903],{"class":114,"line":1902},111,[112,1904,411],{"emptyLinePlaceholder":410},[112,1906,1908,1911,1913,1915,1918,1921,1923,1925,1927,1929,1932,1935],{"class":114,"line":1907},112,[112,1909,1910],{"class":452},"        DIR_SIZE",[112,1912,457],{"class":456},[112,1914,577],{"class":476},[112,1916,1917],{"class":118},"du",[112,1919,1920],{"class":122}," -sh",[112,1922,301],{"class":300},[112,1924,1738],{"class":452},[112,1926,307],{"class":300},[112,1928,820],{"class":456},[112,1930,1931],{"class":118}," cut",[112,1933,1934],{"class":122}," -f1",[112,1936,534],{"class":476},[112,1938,1940,1942,1944,1947,1949,1951,1953,1956,1958,1961,1963,1966],{"class":114,"line":1939},113,[112,1941,1211],{"class":118},[112,1943,301],{"class":300},[112,1945,1946],{"class":156},"  ✓ ",[112,1948,605],{"class":300},[112,1950,1627],{"class":452},[112,1952,561],{"class":300},[112,1954,1955],{"class":156}," completado (",[112,1957,605],{"class":300},[112,1959,1960],{"class":452},"DIR_SIZE",[112,1962,561],{"class":300},[112,1964,1965],{"class":156},")",[112,1967,465],{"class":300},[112,1969,1971],{"class":114,"line":1970},114,[112,1972,1973],{"class":895},"    else\n",[112,1975,1977,1979,1981,1984,1986,1988],{"class":114,"line":1976},115,[112,1978,1211],{"class":118},[112,1980,301],{"class":300},[112,1982,1983],{"class":156},"  ✗ ERROR en ",[112,1985,605],{"class":300},[112,1987,1627],{"class":452},[112,1989,610],{"class":300},[112,1991,1993,1995,1997,1999,2001,2003],{"class":114,"line":1992},116,[112,1994,1250],{"class":476},[112,1996,1393],{"class":452},[112,1998,1256],{"class":456},[112,2000,1259],{"class":476},[112,2002,1039],{"class":456},[112,2004,1042],{"class":417},[112,2006,2008],{"class":114,"line":2007},117,[112,2009,1048],{"class":895},[112,2011,2013],{"class":114,"line":2012},118,[112,2014,2015],{"class":895},"done\n",[112,2017,2019],{"class":114,"line":2018},119,[112,2020,411],{"emptyLinePlaceholder":410},[112,2022,2024],{"class":114,"line":2023},120,[112,2025,2026],{"class":256},"# Actualizar symlink latest\n",[112,2028,2030,2033,2035,2037,2039],{"class":114,"line":2029},121,[112,2031,2032],{"class":118},"rm",[112,2034,1519],{"class":122},[112,2036,301],{"class":300},[112,2038,1459],{"class":452},[112,2040,465],{"class":300},[112,2042,2044,2047,2049,2051,2053,2055,2057,2059],{"class":114,"line":2043},122,[112,2045,2046],{"class":118},"ln",[112,2048,924],{"class":122},[112,2050,301],{"class":300},[112,2052,1420],{"class":452},[112,2054,307],{"class":300},[112,2056,301],{"class":300},[112,2058,1459],{"class":452},[112,2060,465],{"class":300},[112,2062,2064],{"class":114,"line":2063},123,[112,2065,411],{"emptyLinePlaceholder":410},[112,2067,2069],{"class":114,"line":2068},124,[112,2070,2071],{"class":256},"# Backup remoto (opcional)\n",[112,2073,2075,2077,2079,2081,2083,2086,2088,2090,2092,2094,2096,2098,2101,2103,2105],{"class":114,"line":2074},125,[112,2076,1449],{"class":895},[112,2078,899],{"class":476},[112,2080,902],{"class":456},[112,2082,301],{"class":300},[112,2084,2085],{"class":452},"$REMOTE_HOST",[112,2087,307],{"class":300},[112,2089,1464],{"class":476},[112,2091,1467],{"class":476},[112,2093,899],{"class":476},[112,2095,902],{"class":456},[112,2097,301],{"class":300},[112,2099,2100],{"class":452},"$REMOTE_DIR",[112,2102,307],{"class":300},[112,2104,912],{"class":476},[112,2106,915],{"class":895},[112,2108,2110,2112,2114,2117,2119,2121,2123,2125,2127,2129],{"class":114,"line":2109},126,[112,2111,1074],{"class":118},[112,2113,301],{"class":300},[112,2115,2116],{"class":156},"Sincronizando a servidor remoto: ",[112,2118,605],{"class":300},[112,2120,674],{"class":452},[112,2122,561],{"class":300},[112,2124,985],{"class":156},[112,2126,605],{"class":300},[112,2128,685],{"class":452},[112,2130,610],{"class":300},[112,2132,2134],{"class":114,"line":2133},127,[112,2135,411],{"emptyLinePlaceholder":410},[112,2137,2139,2141,2143,2146,2148],{"class":114,"line":2138},128,[112,2140,896],{"class":895},[112,2142,1783],{"class":118},[112,2144,2145],{"class":122}," -az",[112,2147,153],{"class":122},[112,2149,339],{"class":338},[112,2151,2153,2156,2158,2161,2163],{"class":114,"line":2152},129,[112,2154,2155],{"class":122},"        -e",[112,2157,301],{"class":300},[112,2159,2160],{"class":156},"ssh -o StrictHostKeyChecking=no",[112,2162,307],{"class":300},[112,2164,339],{"class":338},[112,2166,2168,2171,2173,2175,2177,2179],{"class":114,"line":2167},130,[112,2169,2170],{"class":300},"        \"${",[112,2172,591],{"class":452},[112,2174,561],{"class":300},[112,2176,602],{"class":156},[112,2178,307],{"class":300},[112,2180,339],{"class":338},[112,2182,2184,2186,2188,2190,2192,2194,2196,2198,2200,2202,2204,2206,2208,2210,2212,2214,2216,2218,2220,2222],{"class":114,"line":2183},131,[112,2185,2170],{"class":300},[112,2187,674],{"class":452},[112,2189,561],{"class":300},[112,2191,985],{"class":156},[112,2193,605],{"class":300},[112,2195,685],{"class":452},[112,2197,561],{"class":300},[112,2199,602],{"class":156},[112,2201,605],{"class":300},[112,2203,572],{"class":452},[112,2205,561],{"class":300},[112,2207,602],{"class":156},[112,2209,307],{"class":300},[112,2211,1887],{"class":456},[112,2213,301],{"class":300},[112,2215,831],{"class":452},[112,2217,307],{"class":300},[112,2219,1036],{"class":456},[112,2221,1202],{"class":476},[112,2223,915],{"class":895},[112,2225,2227,2229,2231,2234],{"class":114,"line":2226},132,[112,2228,1211],{"class":118},[112,2230,301],{"class":300},[112,2232,2233],{"class":156},"  ✓ Sincronización remota completada",[112,2235,465],{"class":300},[112,2237,2239],{"class":114,"line":2238},133,[112,2240,1973],{"class":895},[112,2242,2244,2246,2248,2251],{"class":114,"line":2243},134,[112,2245,1211],{"class":118},[112,2247,301],{"class":300},[112,2249,2250],{"class":156},"  ✗ ERROR en sincronización remota",[112,2252,465],{"class":300},[112,2254,2256,2258,2260,2262,2264,2266],{"class":114,"line":2255},135,[112,2257,1250],{"class":476},[112,2259,1393],{"class":452},[112,2261,1256],{"class":456},[112,2263,1259],{"class":476},[112,2265,1039],{"class":456},[112,2267,1042],{"class":417},[112,2269,2271],{"class":114,"line":2270},136,[112,2272,1048],{"class":895},[112,2274,2276],{"class":114,"line":2275},137,[112,2277,1549],{"class":895},[112,2279,2281],{"class":114,"line":2280},138,[112,2282,411],{"emptyLinePlaceholder":410},[112,2284,2286],{"class":114,"line":2285},139,[112,2287,2288],{"class":256},"# Limpieza\n",[112,2290,2292,2294,2296,2298],{"class":114,"line":2291},140,[112,2293,1064],{"class":118},[112,2295,301],{"class":300},[112,2297,1124],{"class":452},[112,2299,465],{"class":300},[112,2301,2303],{"class":114,"line":2302},141,[112,2304,411],{"emptyLinePlaceholder":410},[112,2306,2308],{"class":114,"line":2307},142,[112,2309,2310],{"class":256},"# Resumen\n",[112,2312,2314,2317,2319,2321,2323,2325],{"class":114,"line":2313},143,[112,2315,2316],{"class":452},"END_TIME",[112,2318,457],{"class":456},[112,2320,577],{"class":476},[112,2322,580],{"class":118},[112,2324,1375],{"class":156},[112,2326,534],{"class":476},[112,2328,2330,2333,2335,2338,2340,2343,2346],{"class":114,"line":2329},144,[112,2331,2332],{"class":452},"DURATION",[112,2334,457],{"class":456},[112,2336,2337],{"class":476},"$((",[112,2339,2316],{"class":118},[112,2341,2342],{"class":156}," -",[112,2344,2345],{"class":156}," START_TIME",[112,2347,2348],{"class":476},"))\n",[112,2350,2352,2354,2356,2358,2360,2362,2364,2366,2368,2370,2372,2374],{"class":114,"line":2351},145,[112,2353,1383],{"class":452},[112,2355,457],{"class":456},[112,2357,577],{"class":476},[112,2359,1917],{"class":118},[112,2361,1920],{"class":122},[112,2363,301],{"class":300},[112,2365,1420],{"class":452},[112,2367,307],{"class":300},[112,2369,820],{"class":456},[112,2371,1931],{"class":118},[112,2373,1934],{"class":122},[112,2375,534],{"class":476},[112,2377,2379,2382,2384,2386,2389,2392,2394,2396,2398,2400,2403,2406,2408,2411,2413,2416,2418],{"class":114,"line":2378},146,[112,2380,2381],{"class":452},"DISK_FREE",[112,2383,457],{"class":456},[112,2385,577],{"class":476},[112,2387,2388],{"class":118},"df",[112,2390,2391],{"class":122}," -h",[112,2393,301],{"class":300},[112,2395,1124],{"class":452},[112,2397,307],{"class":300},[112,2399,820],{"class":456},[112,2401,2402],{"class":118}," tail",[112,2404,2405],{"class":122}," -1",[112,2407,820],{"class":456},[112,2409,2410],{"class":118}," awk",[112,2412,802],{"class":300},[112,2414,2415],{"class":156},"{print $4}",[112,2417,1681],{"class":300},[112,2419,534],{"class":476},[112,2421,2423],{"class":114,"line":2422},147,[112,2424,411],{"emptyLinePlaceholder":410},[112,2426,2428,2430,2432,2434],{"class":114,"line":2427},148,[112,2429,778],{"class":118},[112,2431,301],{"class":300},[112,2433,1326],{"class":156},[112,2435,465],{"class":300},[112,2437,2439,2441,2443,2446],{"class":114,"line":2438},149,[112,2440,778],{"class":118},[112,2442,301],{"class":300},[112,2444,2445],{"class":156},"BACKUP COMPLETADO",[112,2447,465],{"class":300},[112,2449,2451,2453,2455,2458,2460,2462,2464,2467],{"class":114,"line":2450},150,[112,2452,778],{"class":118},[112,2454,301],{"class":300},[112,2456,2457],{"class":156},"  Duración: ",[112,2459,605],{"class":300},[112,2461,2332],{"class":452},[112,2463,561],{"class":300},[112,2465,2466],{"class":156},"s",[112,2468,465],{"class":300},[112,2470,2472,2474,2476,2479,2481,2483],{"class":114,"line":2471},151,[112,2473,778],{"class":118},[112,2475,301],{"class":300},[112,2477,2478],{"class":156},"  Tamaño: ",[112,2480,605],{"class":300},[112,2482,1383],{"class":452},[112,2484,610],{"class":300},[112,2486,2488,2490,2492,2495,2497,2499],{"class":114,"line":2487},152,[112,2489,778],{"class":118},[112,2491,301],{"class":300},[112,2493,2494],{"class":156},"  Errores: ",[112,2496,605],{"class":300},[112,2498,1393],{"class":452},[112,2500,610],{"class":300},[112,2502,2504,2506,2508,2511,2513,2515],{"class":114,"line":2503},153,[112,2505,778],{"class":118},[112,2507,301],{"class":300},[112,2509,2510],{"class":156},"  Espacio libre: ",[112,2512,605],{"class":300},[112,2514,2381],{"class":452},[112,2516,610],{"class":300},[112,2518,2520,2522,2524,2526],{"class":114,"line":2519},154,[112,2521,778],{"class":118},[112,2523,301],{"class":300},[112,2525,1326],{"class":156},[112,2527,465],{"class":300},[112,2529,2531],{"class":114,"line":2530},155,[112,2532,411],{"emptyLinePlaceholder":410},[112,2534,2536],{"class":114,"line":2535},156,[112,2537,2538],{"class":256},"# Notificación\n",[112,2540,2542,2544,2546,2549,2552,2555,2557],{"class":114,"line":2541},157,[112,2543,1449],{"class":895},[112,2545,899],{"class":476},[112,2547,2548],{"class":452}," $ERRORS ",[112,2550,2551],{"class":456},"-eq",[112,2553,2554],{"class":1103}," 0",[112,2556,912],{"class":476},[112,2558,915],{"class":895},[112,2560,2562,2565,2567,2570,2572,2574,2576,2579,2581,2583,2585,2588,2590,2593,2596,2598,2601],{"class":114,"line":2561},158,[112,2563,2564],{"class":118},"    notify_slack",[112,2566,301],{"class":300},[112,2568,2569],{"class":156},"✅ Backup completado | ",[112,2571,605],{"class":300},[112,2573,1383],{"class":452},[112,2575,561],{"class":300},[112,2577,2578],{"class":156}," | ",[112,2580,605],{"class":300},[112,2582,2332],{"class":452},[112,2584,561],{"class":300},[112,2586,2587],{"class":156},"s | ",[112,2589,577],{"class":300},[112,2591,2592],{"class":118},"hostname",[112,2594,2595],{"class":300},")\"",[112,2597,301],{"class":300},[112,2599,2600],{"class":156},"#36a64f",[112,2602,465],{"class":300},[112,2604,2606],{"class":114,"line":2605},159,[112,2607,1531],{"class":895},[112,2609,2611,2613,2615,2618,2620,2622,2624,2627,2629,2631,2633,2636,2638,2640,2643,2645,2648],{"class":114,"line":2610},160,[112,2612,2564],{"class":118},[112,2614,301],{"class":300},[112,2616,2617],{"class":156},"🚨 Backup con ",[112,2619,605],{"class":300},[112,2621,1393],{"class":452},[112,2623,561],{"class":300},[112,2625,2626],{"class":156}," error(es) | ",[112,2628,577],{"class":300},[112,2630,2592],{"class":118},[112,2632,1965],{"class":300},[112,2634,2635],{"class":156}," | Ver log: ",[112,2637,605],{"class":300},[112,2639,635],{"class":452},[112,2641,2642],{"class":300},"}\"",[112,2644,301],{"class":300},[112,2646,2647],{"class":156},"#ff0000",[112,2649,465],{"class":300},[112,2651,2653],{"class":114,"line":2652},161,[112,2654,1549],{"class":895},[112,2656,2658],{"class":114,"line":2657},162,[112,2659,411],{"emptyLinePlaceholder":410},[112,2661,2663,2666],{"class":114,"line":2662},163,[112,2664,2665],{"class":417},"exit",[112,2667,2668],{"class":452}," $ERRORS\n",[314,2670],{},[22,2672,2674],{"id":2673},"paso-4-configurar-permisos-y-probar","Paso 4: Configurar permisos y probar",[102,2676,2678],{"className":104,"code":2677,"language":106,"meta":107,"style":107},"# Hacer ejecutable\nchmod +x backup-rsync.sh\n\n# Probar manualmente\nsudo ./backup-rsync.sh\n",[109,2679,2680,2685,2696,2700,2705],{"__ignoreMap":107},[112,2681,2682],{"class":114,"line":115},[112,2683,2684],{"class":256},"# Hacer ejecutable\n",[112,2686,2687,2690,2693],{"class":114,"line":260},[112,2688,2689],{"class":118},"chmod",[112,2691,2692],{"class":156}," +x",[112,2694,2695],{"class":156}," backup-rsync.sh\n",[112,2697,2698],{"class":114,"line":349},[112,2699,411],{"emptyLinePlaceholder":410},[112,2701,2702],{"class":114,"line":357},[112,2703,2704],{"class":256},"# Probar manualmente\n",[112,2706,2707,2710],{"class":114,"line":414},[112,2708,2709],{"class":118},"sudo",[112,2711,2712],{"class":156}," ./backup-rsync.sh\n",[12,2714,2715],{},"Verifica la estructura de backups:",[102,2717,2719],{"className":104,"code":2718,"language":106,"meta":107,"style":107},"ls -la /backup/\n# Deberías ver el directorio con fecha y el symlink latest\n\n# Verificar que latest apunta al backup reciente\nreadlink -f /backup/latest\n\n# Ver tamaño real vs aparente (hard links)\ndu -sh /backup/2026-01-08/       # Tamaño aparente (completo)\ndu -sh --apparent-size /backup/   # Tamaño real en disco\n",[109,2720,2721,2732,2737,2741,2746,2755,2759,2764,2776],{"__ignoreMap":107},[112,2722,2723,2726,2729],{"class":114,"line":115},[112,2724,2725],{"class":118},"ls",[112,2727,2728],{"class":122}," -la",[112,2730,2731],{"class":156}," /backup/\n",[112,2733,2734],{"class":114,"line":260},[112,2735,2736],{"class":256},"# Deberías ver el directorio con fecha y el symlink latest\n",[112,2738,2739],{"class":114,"line":349},[112,2740,411],{"emptyLinePlaceholder":410},[112,2742,2743],{"class":114,"line":357},[112,2744,2745],{"class":256},"# Verificar que latest apunta al backup reciente\n",[112,2747,2748,2750,2752],{"class":114,"line":414},[112,2749,1516],{"class":118},[112,2751,1519],{"class":122},[112,2753,2754],{"class":156}," /backup/latest\n",[112,2756,2757],{"class":114,"line":427},[112,2758,411],{"emptyLinePlaceholder":410},[112,2760,2761],{"class":114,"line":432},[112,2762,2763],{"class":256},"# Ver tamaño real vs aparente (hard links)\n",[112,2765,2766,2768,2770,2773],{"class":114,"line":438},[112,2767,1917],{"class":118},[112,2769,1920],{"class":122},[112,2771,2772],{"class":156}," /backup/2026-01-08/",[112,2774,2775],{"class":256},"       # Tamaño aparente (completo)\n",[112,2777,2778,2780,2782,2785,2788],{"class":114,"line":444},[112,2779,1917],{"class":118},[112,2781,1920],{"class":122},[112,2783,2784],{"class":122}," --apparent-size",[112,2786,2787],{"class":156}," /backup/",[112,2789,2790],{"class":256},"   # Tamaño real en disco\n",[22,2792,2794],{"id":2793},"paso-5-automatizar-con-cron","Paso 5: Automatizar con cron",[102,2796,2798],{"className":104,"code":2797,"language":106,"meta":107,"style":107},"sudo crontab -e\n",[109,2799,2800],{"__ignoreMap":107},[112,2801,2802,2804,2807],{"class":114,"line":115},[112,2803,2709],{"class":118},[112,2805,2806],{"class":156}," crontab",[112,2808,2809],{"class":122}," -e\n",[102,2811,2815],{"className":2812,"code":2813,"language":2814,"meta":107,"style":107},"language-cron shiki shiki-themes material-theme-lighter github-light github-dark","# Backup diario a las 2:00 AM\n0 2 * * * /opt/scripts/backup-rsync.sh >> /var/log/backup-rsync-cron.log 2>&1\n","cron",[109,2816,2817,2822],{"__ignoreMap":107},[112,2818,2819],{"class":114,"line":115},[112,2820,2821],{},"# Backup diario a las 2:00 AM\n",[112,2823,2824],{"class":114,"line":260},[112,2825,2826],{},"0 2 * * * /opt/scripts/backup-rsync.sh >> /var/log/backup-rsync-cron.log 2>&1\n",[22,2828,2830],{"id":2829},"paso-6-restaurar-archivos","Paso 6: Restaurar archivos",[12,2832,2833],{},"La ventaja de rsync con hard links es que restaurar es trivial — cada backup es una carpeta navegable:",[102,2835,2837],{"className":104,"code":2836,"language":106,"meta":107,"style":107},"# Restaurar un archivo específico del backup de ayer\ncp /backup/2026-01-07/var_www/uploads/documento.pdf /var/www/uploads/\n\n# Restaurar un directorio completo\nrsync -av /backup/2026-01-07/var_www/ /var/www/\n\n# Restaurar desde el backup más reciente\nrsync -av /backup/latest/var_www/ /var/www/\n",[109,2838,2839,2844,2855,2859,2864,2877,2881,2886],{"__ignoreMap":107},[112,2840,2841],{"class":114,"line":115},[112,2842,2843],{"class":256},"# Restaurar un archivo específico del backup de ayer\n",[112,2845,2846,2849,2852],{"class":114,"line":260},[112,2847,2848],{"class":118},"cp",[112,2850,2851],{"class":156}," /backup/2026-01-07/var_www/uploads/documento.pdf",[112,2853,2854],{"class":156}," /var/www/uploads/\n",[112,2856,2857],{"class":114,"line":349},[112,2858,411],{"emptyLinePlaceholder":410},[112,2860,2861],{"class":114,"line":357},[112,2862,2863],{"class":256},"# Restaurar un directorio completo\n",[112,2865,2866,2868,2871,2874],{"class":114,"line":414},[112,2867,119],{"class":118},[112,2869,2870],{"class":122}," -av",[112,2872,2873],{"class":156}," /backup/2026-01-07/var_www/",[112,2875,2876],{"class":156}," /var/www/\n",[112,2878,2879],{"class":114,"line":427},[112,2880,411],{"emptyLinePlaceholder":410},[112,2882,2883],{"class":114,"line":432},[112,2884,2885],{"class":256},"# Restaurar desde el backup más reciente\n",[112,2887,2888,2890,2892,2895],{"class":114,"line":438},[112,2889,119],{"class":118},[112,2891,2870],{"class":122},[112,2893,2894],{"class":156}," /backup/latest/var_www/",[112,2896,2876],{"class":156},[12,2898,2899,2900,2902,2903,2905],{},"No necesitas herramientas especiales ni procesos de extracción — solo ",[109,2901,2848],{}," o ",[109,2904,119],{},".",[22,2907,2909],{"id":2908},"paso-7-backup-a-servidor-remoto","Paso 7: Backup a servidor remoto",[12,2911,2912],{},"Para cumplir con la regla 3-2-1, envía los backups a otro servidor. Modifica las variables del script:",[102,2914,2916],{"className":104,"code":2915,"language":106,"meta":107,"style":107},"REMOTE_HOST=\"backup@10.0.1.50\"\nREMOTE_DIR=\"/backups/servidor-web\"\n",[109,2917,2918,2931],{"__ignoreMap":107},[112,2919,2920,2922,2924,2926,2929],{"class":114,"line":115},[112,2921,674],{"class":452},[112,2923,457],{"class":456},[112,2925,307],{"class":300},[112,2927,2928],{"class":156},"backup@10.0.1.50",[112,2930,465],{"class":300},[112,2932,2933,2935,2937,2939,2942],{"class":114,"line":260},[112,2934,685],{"class":452},[112,2936,457],{"class":456},[112,2938,307],{"class":300},[112,2940,2941],{"class":156},"/backups/servidor-web",[112,2943,465],{"class":300},[12,2945,2946],{},"O ejecuta rsync manualmente para enviar el último backup:",[102,2948,2950],{"className":104,"code":2949,"language":106,"meta":107,"style":107},"rsync -avz -e \"ssh -p 2222\" /backup/latest/ backup@10.0.1.50:/backups/servidor-web/latest/\n",[109,2951,2952],{"__ignoreMap":107},[112,2953,2954,2956,2958,2960,2962,2964,2966,2969],{"class":114,"line":115},[112,2955,119],{"class":118},[112,2957,150],{"class":122},[112,2959,297],{"class":122},[112,2961,301],{"class":300},[112,2963,304],{"class":156},[112,2965,307],{"class":300},[112,2967,2968],{"class":156}," /backup/latest/",[112,2970,2971],{"class":156}," backup@10.0.1.50:/backups/servidor-web/latest/\n",[216,2973,2976],{"title":2974,"type":2975},"Ancho de banda","info",[12,2977,2978,2979,2981,2982,2985],{},"rsync con ",[109,2980,201],{}," comprime los datos durante la transferencia. Para backups iniciales grandes sobre internet, considera ejecutarlo con ",[109,2983,2984],{},"--bwlimit=10000"," (10 MB/s) para no saturar tu enlace. Los incrementales diarios suelen ser pequeños y no necesitan limitación.",[314,2987],{},[22,2989,2991],{"id":2990},"monitoreo-de-backups","Monitoreo de backups",[243,2993,2995],{"id":2994},"verificar-que-el-backup-se-ejecutó","Verificar que el backup se ejecutó",[102,2997,2999],{"className":104,"code":2998,"language":106,"meta":107,"style":107},"# Verificar la fecha del último backup\nstat -c %y /backup/latest\n\n# Verificar con Zabbix o Prometheus\n# Item: antigüedad del último backup en minutos\nfind /backup -maxdepth 1 -type d -name \"20*\" -mmin -1500 | wc -l\n# Si el resultado es 0, no hubo backup en las últimas 25 horas → alerta\n",[109,3000,3001,3006,3019,3023,3028,3033,3071],{"__ignoreMap":107},[112,3002,3003],{"class":114,"line":115},[112,3004,3005],{"class":256},"# Verificar la fecha del último backup\n",[112,3007,3008,3011,3014,3017],{"class":114,"line":260},[112,3009,3010],{"class":417},"stat",[112,3012,3013],{"class":122}," -c",[112,3015,3016],{"class":156}," %y",[112,3018,2754],{"class":156},[112,3020,3021],{"class":114,"line":349},[112,3022,411],{"emptyLinePlaceholder":410},[112,3024,3025],{"class":114,"line":357},[112,3026,3027],{"class":256},"# Verificar con Zabbix o Prometheus\n",[112,3029,3030],{"class":114,"line":414},[112,3031,3032],{"class":256},"# Item: antigüedad del último backup en minutos\n",[112,3034,3035,3038,3041,3043,3045,3047,3049,3051,3053,3055,3057,3060,3063,3065,3068],{"class":114,"line":427},[112,3036,3037],{"class":118},"find",[112,3039,3040],{"class":156}," /backup",[112,3042,1149],{"class":122},[112,3044,1152],{"class":1103},[112,3046,1155],{"class":122},[112,3048,1158],{"class":156},[112,3050,1161],{"class":122},[112,3052,301],{"class":300},[112,3054,1166],{"class":156},[112,3056,307],{"class":300},[112,3058,3059],{"class":122}," -mmin",[112,3061,3062],{"class":122}," -1500",[112,3064,820],{"class":456},[112,3066,3067],{"class":118}," wc",[112,3069,3070],{"class":122}," -l\n",[112,3072,3073],{"class":114,"line":432},[112,3074,3075],{"class":256},"# Si el resultado es 0, no hubo backup en las últimas 25 horas → alerta\n",[243,3077,3079],{"id":3078},"verificar-integridad","Verificar integridad",[102,3081,3083],{"className":104,"code":3082,"language":106,"meta":107,"style":107},"# Comparar el backup con el origen (dry-run, no copia nada)\nrsync -avn --delete /var/www/ /backup/latest/var_www/\n# Si la salida está vacía, el backup es idéntico al origen\n",[109,3084,3085,3090,3104],{"__ignoreMap":107},[112,3086,3087],{"class":114,"line":115},[112,3088,3089],{"class":256},"# Comparar el backup con el origen (dry-run, no copia nada)\n",[112,3091,3092,3094,3097,3099,3101],{"class":114,"line":260},[112,3093,119],{"class":118},[112,3095,3096],{"class":122}," -avn",[112,3098,153],{"class":122},[112,3100,269],{"class":156},[112,3102,3103],{"class":156}," /backup/latest/var_www/\n",[112,3105,3106],{"class":114,"line":349},[112,3107,3108],{"class":256},"# Si la salida está vacía, el backup es idéntico al origen\n",[22,3110,3112],{"id":3111},"rsync-vs-herramientas-especializadas","rsync vs herramientas especializadas",[30,3114,3115,3128],{},[33,3116,3117],{},[36,3118,3119,3122,3125],{},[39,3120,3121],{},"Herramienta",[39,3123,3124],{},"Mejor para",[39,3126,3127],{},"Limitación",[52,3129,3130,3143,3156,3169,3182],{},[36,3131,3132,3137,3140],{},[57,3133,3134],{},[3135,3136,119],"strong",{},[57,3138,3139],{},"Archivos, directorios, configuraciones",[57,3141,3142],{},"No deduplica entre archivos diferentes",[36,3144,3145,3150,3153],{},[57,3146,3147],{},[3135,3148,3149],{},"BorgBackup",[57,3151,3152],{},"Deduplicación avanzada, cifrado",[57,3154,3155],{},"Más complejo de configurar",[36,3157,3158,3163,3166],{},[57,3159,3160],{},[3135,3161,3162],{},"restic",[57,3164,3165],{},"Backup cifrado a cloud (S3, B2)",[57,3167,3168],{},"Restauración más lenta que rsync",[36,3170,3171,3176,3179],{},[57,3172,3173],{},[3135,3174,3175],{},"Veeam",[57,3177,3178],{},"VMs completas (Proxmox, VMware)",[57,3180,3181],{},"Licencia comercial",[36,3183,3184,3191,3194],{},[57,3185,3186],{},[3135,3187,3188],{},[16,3189,3190],{"href":18},"Python script",[57,3192,3193],{},"Bases de datos + lógica custom",[57,3195,3196],{},"Más código que mantener",[12,3198,3199],{},"Para archivos de servidor y directorios de datos, rsync con hard links es difícil de superar en simplicidad y eficiencia.",[22,3201,3203],{"id":3202},"siguientes-pasos","Siguientes pasos",[12,3205,3206],{},"Con backups incrementales funcionando:",[3208,3209,3210,3216,3224,3233,3242],"ul",{},[3211,3212,3213,3215],"li",{},[3135,3214,3149],{}," — deduplicación y cifrado para backups que van a destinos no confiables",[3211,3217,3218,3223],{},[3135,3219,3220],{},[16,3221,3222],{"href":18},"Backup de PostgreSQL"," — combina este script de rsync para archivos con el de Python para bases de datos",[3211,3225,3226,3232],{},[3135,3227,3228],{},[16,3229,3231],{"href":3230},"/blog/configurar-raid-software-linux","RAID"," — protección del disco de backups contra fallo de hardware",[3211,3234,3235,3241],{},[3135,3236,3237],{},[16,3238,3240],{"href":3239},"/blog/monitoreo-grafana-prometheus","Monitoreo"," — alertas si el backup no se ejecutó o si el disco de backups está lleno",[3211,3243,3244,3250],{},[3135,3245,3246],{},[16,3247,3249],{"href":3248},"/servicios/infraestructura","Infraestructura de backup"," profesional — estrategia 3-2-1 completa con Veeam, Proxmox Backup Server y pruebas de restauración",[3252,3253],"call-to-action",{"description":3254,"eyebrow":3255,"icon":3256,"label":3257,"title":3258,"to":3259},"Diseñamos tu plan de backup con rsync, Veeam o Proxmox Backup Server, con retención, cifrado y pruebas de restauración periódicas.","Respaldos empresariales","i-lucide-database-backup","Solicitar evaluación","¿Tu estrategia de backup está completa y probada?","/contacto",[3261,3262,3263],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sfi6f, html code.shiki .sfi6f{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#005CC5;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":107,"searchDepth":260,"depth":349,"links":3265},[3266,3267,3268,3272,3273,3274,3275,3276,3277,3278,3282,3283],{"id":24,"depth":260,"text":25},{"id":96,"depth":260,"text":97},{"id":134,"depth":260,"text":135,"children":3269},[3270,3271],{"id":245,"depth":349,"text":246},{"id":275,"depth":349,"text":276},{"id":318,"depth":260,"text":319},{"id":384,"depth":260,"text":385},{"id":2673,"depth":260,"text":2674},{"id":2793,"depth":260,"text":2794},{"id":2829,"depth":260,"text":2830},{"id":2908,"depth":260,"text":2909},{"id":2990,"depth":260,"text":2991,"children":3279},[3280,3281],{"id":2994,"depth":349,"text":2995},{"id":3078,"depth":349,"text":3079},{"id":3111,"depth":260,"text":3112},{"id":3202,"depth":260,"text":3203},"tutorial",{"title":3286,"description":3287,"label":3257,"to":3259,"icon":3256},"¿Necesitas una estrategia de backup profesional?","Diseñamos e implementamos tu plan de backup con rsync, Veeam o Proxmox Backup Server, con pruebas de restauración periódicas.","2026-01-08","Guía paso a paso para crear un sistema de backups incrementales con rsync y Bash que respalda archivos eficientemente, conserva versiones históricas y se automatiza con cron.",false,"md",[3293,3296,3299,3302],{"question":3294,"answer":3295},"¿Qué significa backup incremental?","Un backup incremental solo copia los archivos que cambiaron desde el último respaldo. Si tienes 100 GB de datos y solo cambiaron 500 MB, el backup incremental transfiere y almacena solo esos 500 MB. Esto reduce drásticamente el tiempo de ejecución, el uso de ancho de banda y el espacio de almacenamiento necesario.",{"question":3297,"answer":3298},"¿rsync es mejor que cp o tar para backups?","Para backups, sí. rsync compara archivos entre origen y destino y solo transfiere las diferencias. cp copia todo siempre. tar empaqueta todo siempre. Con rsync y hard links, puedes tener 30 días de backups que ocupan el espacio de una copia completa más los cambios diarios — algo que cp y tar no pueden hacer.",{"question":3300,"answer":3301},"¿Puedo usar rsync para respaldar a un servidor remoto?","Sí. rsync funciona sobre SSH de forma nativa. Solo cambias el destino de una ruta local a usuario@servidor:/ruta y rsync cifra y transfiere todo por SSH. Es la forma más común de enviar backups a un servidor remoto o a un NAS.",{"question":3303,"answer":3304},"¿Los hard links de rsync ocupan espacio doble?","No. Un hard link es una referencia al mismo archivo en disco. Si un archivo no cambió entre el backup de ayer y el de hoy, ambos apuntan al mismo bloque en disco. Solo los archivos que cambiaron ocupan espacio adicional. Por eso 30 backups diarios pueden ocupar solo 1.2x el tamaño original en lugar de 30x.","/images/blog/rsync-backup.jpg","Terminal mostrando ejecución de rsync transfiriendo archivos incrementales con estadísticas de transferencia",{},"/blog/tutorial/respaldos-incrementales-rsync-bash",{"title":5,"description":3289},"blog/tutorial/respaldos-incrementales-rsync-bash",[3312,119,106,3313,3314,3284],"backup","linux","servidores","tSq9uT-SJuHJ3H_STx-cH80RPmQwfnDcZfRI2Gyy1dE",{"path":3317,"title":3318},"/blog/tutorial/instalar-nextcloud-servidor","Instalar y configurar Nextcloud en tu propio servidor",{"path":3320,"title":3321},"/blog/tutorial/replicacion-postgresql-alta-disponibilidad","Replicación master-slave en PostgreSQL — alta disponibilidad paso a paso",[3323,3330,3337],{"path":3324,"title":3325,"description":3326,"date":3327,"category":3284,"image":3328,"imageAlt":3329,"readingTime":480},"/blog/tutorial/apis-rest-python-fastapi","Crear APIs REST con Python y FastAPI para integraciones empresariales","Guía paso a paso para construir una API REST profesional con Python y FastAPI que conecte tu ERP, CRM o cualquier sistema con validación, autenticación y documentación automática.","2026-03-04","/images/blog/fastapi-api-rest.jpg","Editor de código mostrando una API FastAPI con documentación Swagger generada automáticamente",{"path":3331,"title":3332,"description":3333,"date":3334,"category":3284,"image":3335,"imageAlt":3336,"readingTime":438},"/blog/tutorial/configurar-firewall-ufw-linux","Configurar firewall en Linux con UFW — reglas esenciales","Guía paso a paso para configurar UFW (Uncomplicated Firewall) en Ubuntu y Debian con las reglas esenciales para proteger servidores de producción.","2026-03-01","/images/blog/ufw-firewall-linux.jpg","Terminal de Linux mostrando reglas de firewall UFW activas protegiendo un servidor de producción",{"path":3338,"title":3339,"description":3340,"date":3341,"category":3284,"image":3342,"imageAlt":3343,"readingTime":449},"/blog/tutorial/traefik-reverse-proxy-docker","Configurar Traefik como reverse proxy para contenedores Docker","Guía paso a paso para instalar Traefik como reverse proxy con descubrimiento automático de contenedores Docker, SSL con Let's Encrypt y dashboard de monitoreo.","2026-02-28","/images/blog/traefik-docker.jpg","Dashboard de Traefik mostrando rutas automáticas hacia múltiples contenedores Docker con SSL activo"]