Archivo tar extraído en el lugar

14

Tengo un pequeño dilema aquí ...

Necesitaba mover aproximadamente 70 GB de archivos de uno de mis servidores al otro, así que decidí que reprimirlos y enviar el archivo sería la forma más rápida.

Sin embargo, al servidor receptor solo le quedan 5 GB de espacio después de recibir el archivo tar.

¿Hay alguna forma de extraer el alquitrán 'in situ'? No necesito guardar el archivo después de que se haya extraído, por lo que me preguntaba si es posible hacer esto.

Editar: Cabe señalar que el archivo ya ha sido enviado, y me gustaría evitar reenviarlo a través de un método diferente.

cobarde anónimo
fuente

Respuestas:

11
% tar czf - stuff_to_backup | ssh backupmachine tar xvzf -

esto se traduce en:

  • tar y comprime 'stuff_to_backup' para stdout
  • iniciar sesión en 'backupmachine' a través de ssh
  • ejecute 'tar' en la 'máquina de copia de seguridad' y descomprima las cosas que vienen de stdin

Yo personalmente usaría 'rsync over ssh' para transferir las cosas porque puedes continuar transfiriendo cosas si la conexión se rompe:

% rsync -ar --progress -e 'ssh' 'stuff_to_backup' user@backupmachine:/backup/

que transferirá todo desde 'stuff_to_backup' a la carpeta 'backup' en la 'backupmachine'. Si la conexión se interrumpe, simplemente repita el comando. si cambian algunos archivos en 'stuff_to_backup', repita el material, solo se transferirá la diferencia.

akira
fuente
Vea mi pregunta editada
cobarde anónimo el
@Charlie Somerville: sí, dejaste la parte importante en primer lugar. :)
akira
6

Si la otra máquina tiene ssh, le recomendaría rsync como otra alternativa que no utiliza un archivo tar:

rsync -avPz /some/dir/ user@machine:/some/other/dir/

Y ten cuidado con el líder /

Editar actualización

Bueno, veo cómo esto es ahora un gran problema si no puede eliminarlo y volver a comenzar con rsync. Probablemente probaría un extracto selectivo y lo eliminaría del alquitrán.

extracto selectivo:

$ tar xvf googlecl-0.9.7.tar googlecl-0.9.7/README.txt
googlecl-0.9.7/README.txt

eliminación selectiva:

$ tar --delete --file=googlecl-0.9.7.tar googlecl-0.9.7/README.txt

Sin embargo, parece que pasarás mucho tiempo codificando un script para esto ...

YuppieNetworking
fuente
Vea mi pregunta editada
cobarde anónimo el
Ver mi respuesta editada ... buena suerte: - /
YuppieNetworking
Gracias por la edición Los archivos en realidad se nombran con números, por lo que un bucle rápido para bash podría ser suficiente.
cobarde anónimo
1
@Charlie Somerville: es posible que deba comenzar con los archivos almacenados al final del alquitrán, de lo contrario podría terminar con el tar creando un nuevo archivo ... así que primero elimine los archivos del final del alquitrán.
akira
5

Básicamente, lo que necesita es la posibilidad de canalizar el archivo en alquitrán y "cortar" el frente a medida que avanza.

En StackOverflow, alguien preguntó cómo truncar un archivo al frente , pero parece que no es posible. Todavía puede completar el comienzo del archivo con ceros de una manera especial para que el archivo se convierta en un archivo disperso , pero no sé cómo hacerlo. Sin embargo, podemos truncar el final del archivo. Pero tar necesita leer el archivo hacia adelante, no hacia atrás.

Solución 1

Un nivel de indirección resuelve todos los problemas. Primero invierta el archivo en su lugar, luego léalo hacia atrás (lo que resultará en la lectura del archivo original hacia adelante) y trunca el final del archivo invertido a medida que avanza.

Tendrá que escribir un programa (c, python, lo que sea) para intercambiar el principio y el final del archivo, fragmento por fragmento, y luego canalizar estos fragmentos al alquitrán mientras trunca el archivo un fragmento a la vez. Esta es la base para la solución 2, que es quizás más simple de implementar.

Solución 2

Otro método es dividir el archivo en pequeños fragmentos en el lugar , luego eliminar esos fragmentos a medida que los extraemos. El siguiente código tiene un tamaño de fragmento de un megabyte, ajústelo según sus necesidades. Más grande es más rápido, pero ocupará más espacio intermedio al dividir y durante la extracción.

Dividir el archivo archive.tar:

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

Canalice esos archivos en tar (tenga en cuenta que necesitamos la variable chunkprefix en el segundo terminal):

mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.

Como usamos una tubería con nombre (mkfifo fifo ), no es necesario que canalice todos los fragmentos a la vez. Esto puede ser útil si tienes poco espacio. Puedes seguir los siguientes pasos:

  • Muévase, digamos los últimos fragmentos de 10 Gb a otro disco,
  • Comienza la extracción con los trozos que aún tienes,
  • Cuando el while [ -e … ]; do cat "$chunk…; doneciclo ha terminado (segundo terminal):
  • NO detenga el tarcomando, NO quite el fifo (primer terminal), pero puede ejecutarsync , por si acaso,
  • Mueva algunos archivos extraídos que sabe que están completos (el tar no se detiene esperando que los datos terminen de extraer estos archivos) a otro disco,
  • Mueve los trozos restantes hacia atrás,
  • Reanude la extracción ejecutando las while [ -e … ]; do cat "$chunk…; donelíneas nuevamente.

Por supuesto, todo esto es de alto voltaje , primero querrá verificar que todo esté bien en un archivo ficticio, porque si comete un error, adiós a los datos .

Nunca sabrá si el primer terminal ( tar) realmente ha terminado de procesar el contenido del fifo, por lo que si lo prefiere, puede ejecutar esto, pero no tendrá la posibilidad de intercambiar fragmentos sin problemas con otro disco:

chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done | tar -xf -

Descargo de responsabilidad

Tenga en cuenta que para que todo esto funcione, su shell, cola y truncamiento deben manejar enteros de 64 bits correctamente (no necesita una computadora de 64 bits ni un sistema operativo para eso). El mío sí, pero si ejecuta el script anterior en un sistema sin estos requisitos, perderá todos los datos en archive.tar .

Y en cualquier caso, algo diferente a eso va mal, perderá todos los datos en archive.tar de todos modos, así que asegúrese de tener una copia de seguridad de sus datos.

Suzanne Dupéron
fuente
0

Si tiene archivos de objeto para mover, intente quitarlos. Esto ahorrará una cantidad considerable de espacio.

$ strip `find . -name "*.bin"`
kumar
fuente