Transfiere archivos tar entre servidores sin almacenamiento local
Para copiar un directorio entre dos servidores, conecta mediante un pipeline un comando
tar en el origen, a través de SSH, con un comando
tar en el destino. El archivo tar pasa por tu computadora sin guardarse como
archivo local. El destino necesita espacio para los archivos extraídos, pero ninguno de los
servidores necesita espacio para un archivo tar intermedio.
La ruta es servidor de origen → tu computadora → servidor de destino. Tu computadora transporta el flujo completo y debe permanecer conectada; los servidores no necesitan acceso SSH entre sí. Si los bytes deben evitar por completo tu computadora, ejecuta la transferencia en un host con la conectividad y las credenciales necesarias para acceder a los servidores.
SSH cifra la comunicación con cada servidor. El archivo tar se descifra en la tubería local y se vuelve a cifrar para el destino, así que usa una computadora confiable. No es necesario añadir una contraseña de OpenSSL a este pipeline para cifrar el transporte.
Prepara el origen y el destino
Este ejemplo copia app-data, ubicado en el directorio personal de la cuenta de
origen, a un nuevo directorio app-data.incoming en el directorio personal de la cuenta de
destino. Sustituye source-server y
destination-server por tus alias de SSH o direcciones user@host.
Ajusta las rutas en ambos scripts si tus datos están en otra ubicación.
Necesitas Bash en la computadora que ejecuta los scripts y acceso mediante OpenSSH a dos cuentas de
Linux con GNU tar, GNU find y GNU sha256sum. La cuenta de origen debe poder leer
todos los archivos; la cuenta de destino debe poder crear el directorio de recepción y su contenido.
Configura la autenticación con claves, carga cualquier clave cifrada en tu agente SSH y verifica las
claves de host de ambos servidores antes de empezar. Los comandos usan
BatchMode=yes, por lo que fallan en lugar de solicitar
contraseñas o la confirmación de claves de host durante una transferencia.
Detén las escrituras en el directorio de origen hasta que terminen la copia y la verificación, o lee los datos desde una instantánea coherente. Para una aplicación web, esto incluye las subidas y las tareas en segundo plano. Usa el procedimiento de copia de seguridad de la base de datos para sus datos: copiar con tar los archivos de una base de datos activa no genera una copia de seguridad coherente. Estos comandos copian archivos; la configuración de la aplicación y la redirección del tráfico son pasos independientes.
Los ejemplos se probaron con Bash 5.1.16, GNU tar 1.34 y OpenSSH 8.9p1 en Linux. El paso de comprobación de sumas de verificación usa GNU find y coreutils; no es un procedimiento de comandos para macOS.
Transfiere el flujo a un directorio nuevo
Guarda lo siguiente como transfer.sh en tu computadora y ejecútalo con
bash transfer.sh:
#!/usr/bin/env bash
set -euo pipefail
ssh -T -o BatchMode=yes source-server 'test -d app-data'
ssh -T -o BatchMode=yes destination-server 'mkdir app-data.incoming'
ssh -T -o BatchMode=yes source-server 'tar -cf - -C app-data .' |
ssh -T -o BatchMode=yes destination-server 'tar -xf - -C app-data.incoming'
printf 'Transfer completed; verify app-data.incoming before using it.\n'
El comando simple mkdir falla deliberadamente si el directorio de recepción
ya existe. Elige una ruta nueva para volver a intentarlo, o inspecciona y elimina primero el
directorio de una transferencia fallida. Esto evita que el ejemplo extraiga archivos sobre un
directorio de aplicación existente.
Conceptos básicos de la transferencia de tar en flujo
En tar -cf -, c crea un archivo tar y
f - lo envía a la salida estándar. En tar -xf -,
x extrae el archivo tar leído desde la entrada estándar. Son las mismas
operaciones que suelen escribirse como tar cf - y
tar xf -.
-C app-data cambia el directorio de trabajo de tar
antes de que este archive .. Por ello, las entradas tienen nombres como
./uploads/photo.jpg, incluidos los archivos ocultos cuyo nombre empieza con un punto, en
lugar de un prefijo de directorio que debas eliminar después. Durante la extracción,
-C coloca esas entradas bajo app-data.incoming.
No crea ese directorio.
-T desactiva la asignación de una pseudoterminal de SSH para que la
conexión pueda transportar datos binarios.
pipefail hace que el pipeline falle si falla
cualquiera de los comandos SSH; entonces set -e detiene el script antes de
que muestre su mensaje de finalización. Sin pipefail, un proceso tar de origen
puede fallar después de producir un archivo tar que se pueda extraer, mientras que el destino
termina correctamente.
SSH devuelve el estado de salida del comando remoto, lo que permite
que Bash detecte ese fallo.
Una ejecución correcta muestra el mensaje de finalización y deja el árbol de directorios copiado en
app-data.incoming. Una ejecución fallida puede dejar allí archivos parciales. Ni un
estado de salida cero ni el mensaje de finalización demuestran que un origen que está cambiando se
haya copiado de forma coherente.
Verifica los archivos copiados
Mantén el origen sin cambios y guarda lo siguiente como verify.sh. Ejecuta
bash verify.sh después de la transferencia:
#!/usr/bin/env bash
set -euo pipefail
ssh -T -o BatchMode=yes source-server \
'cd app-data && find . -type f -exec sha256sum -- {} +' |
ssh -T -o BatchMode=yes destination-server \
'cd app-data.incoming && sha256sum --check --strict -'
printf 'Regular-file checksums match.\n'
Esto transmite una lista de sumas de verificación entre los servidores, de nuevo sin guardarla
localmente. GNU sha256sum --check muestra
./filename: OK por cada archivo que coincide y falla si faltan archivos o no
coinciden. GNU find -exec … {} + también devuelve un
estado de fallo si falla un comando de suma de verificación, por lo que se comprueba el lado de
origen de este pipeline. El mensaje final solo aparecerá si ambos lados terminan correctamente.
La comprobación vuelve a leer cada archivo regular en ambos servidores. Supone que existe al menos un archivo regular y verifica el contenido de los archivos, pero no los destinos de los enlaces simbólicos, los directorios vacíos, los permisos, la propiedad ni los archivos adicionales en el destino. Este es un procedimiento para copiar directorios, no una copia de seguridad completa del sistema: no solicita conservar las ACL ni los atributos extendidos. Confirma los metadatos que necesita tu aplicación antes de configurarla para usar el directorio copiado.
Ajusta la transferencia cuando sea necesario
Para visualizar el progreso, instala pv en tu computadora e insértalo en
el pipeline de transferencia: ssh … | pv | ssh …. Mantén el pipeline dentro del script
con pipefail. El
manual de pv describe el recuento de bytes,
el tiempo transcurrido y la velocidad de transferencia que muestra. Si no se conoce el tamaño total
del flujo, no puede ofrecer un porcentaje de finalización ni un tiempo estimado de finalización
útiles. Su salida mide los bytes que pasan por la tubería local, no los archivos verificados.
Si el acceso requiere un host bastión, añade -J bastion-host a cada comando SSH en
ambos scripts. Configura también la autenticación y la verificación de la clave de host para ese
host. ProxyJump se conecta al destino a través
del bastión; la tubería entre los dos comandos SSH sigue ejecutándose en tu computadora. Los ajustes
de identidad y puerto del host de salto deben estar en tu configuración de SSH, porque las opciones
de la línea de comandos generalmente se aplican al destino final.
Para datos que se puedan comprimir y una conexión limitada, cambia tar -cf - por
tar -czf - y tar -xf - por tar -xzf -.
Esto usa la opción --gzip de tar y requiere
gzip en ambos servidores. Consume tiempo de CPU y puede aportar poco en el caso de videos, imágenes
o archivos contenedores que ya estén comprimidos. Haz mediciones con tus archivos y tu conexión
antes de suponer que será más rápido.
Resuelve problemas comunes
- Permiso denegado o disco lleno: Lee stderr de ambos comandos SSH. Comprueba que se pueda leer el origen y revisa los permisos del destino, el espacio libre y los inodos disponibles. Corrige la causa y empieza con un directorio de recepción nuevo; no uses una copia parcial.
- «File changed as we read it»: Detén el proceso que escribe los datos o usa una instantánea y luego repite la transferencia y la comprobación de sumas de verificación. Suprimir la advertencia no puede hacer que una copia de datos que están cambiando sea coherente.
- Errores inesperados del archivo tar: Los archivos de inicio del shell remoto no deben mostrar
saludos en stdout para comandos no interactivos. Esa salida entraría en el flujo del archivo tar.
Mantén los mensajes de diagnóstico en stderr; no combines stderr con la tubería mediante
2>&1o|&. - Conexión interrumpida: Este flujo de tar no permite reanudar la transferencia.
tmuxoscreenpueden mantener un proceso en ejecución cuando te desconectas de su terminal, pero no pueden reparar una conexión SSH interrumpida en el pipeline de transferencia. Reinicia la transferencia a un directorio nuevo y verifica su contenido antes de usarlo.
