Digamos que tengo un archivo de 80GB /root/bigfile
en un sistema de 100GB y quiero poner este archivo en un archivo /root/bigarchive.tar
Obviamente necesito eliminar este archivo al mismo tiempo que se agrega al archivo. De ahí mi pregunta:
¿Cómo eliminar un archivo al mismo tiempo que se agrega a un archivo?
tar
zip
compression
gzip
usuario123456
fuente
fuente
Un archivo tar sin comprimir de un solo archivo consta de un encabezado, el archivo y un pad final. Entonces, su problema principal es cómo agregar 512 bytes de encabezado al inicio de su archivo. Puede comenzar creando el resultado deseado solo con el encabezado:
Luego copie los primeros 10G de su archivo. Por simplicidad asumimos que su dd puede leer / escribir 1Gib a la vez:
Ahora desasignamos los datos copiados del archivo original:
Esto reemplaza los datos con ceros dispersos que no ocupan espacio en el sistema de archivos. Continúe de esta manera, agregando una
skip=10
a la siguientedd
y luego incrementando elfallocate
desplazamiento inicial a-o 10GiB
. Al final, agregue algunos caracteres nul para rellenar el archivo tar final.Si su sistema de archivos no es compatible
fallocate
, puede hacer algo similar, pero comenzando al final del archivo. En primer lugar copiar los últimos 10Gibytes del archivo a un archivo intermedio llamado, por ejemplo,part8
. Luego use eltruncate
comando para reducir el tamaño del archivo original. Proceda de manera similar hasta que tenga 8 archivos de 10Gibyte cada uno. A continuación, puede concatenar la cabecera ypart1
parabigarchive.tar
, a continuación, quitarpart1
, y luego concatenarpart2
y eliminarlo, y así sucesivamente.fuente
Eliminar un archivo no necesariamente hace lo que crees que hace. Es por eso que en sistemas similares a UNIX la llamada al sistema se llama
unlink
y nodelete
. Desde la página del manual:Como consecuencia, mientras el compresor / archivador de datos lea el archivo, ese archivo permanecerá en existencia, ocupando espacio en el sistema de archivos.
fuente
Dado el contexto, interpretaré esta pregunta como:
Cómo eliminar datos del disco inmediatamente después de leerlo, antes de que se haya leído el archivo completo, de modo que haya suficiente espacio para el archivo transformado.
La transformación puede ser cualquier cosa que desee hacer con los datos: compresión, cifrado, etc.
La respuesta es esta:
En resumen: lea los datos, tírelos a gzip (o lo que quiera hacer con ellos), guarde el resultado en el búfer para asegurarnos de leer más de lo que escribimos y volver a escribirlo en el archivo. Esta es una versión más bonita y muestra resultados mientras se ejecuta:
Lo revisaré, línea por línea:
cat "$file"
lee el archivo que quieres comprimir. Es un uso inútil de cat (UUOC) ya que la siguiente parte, pv, también puede leer el archivo, pero creo que es más bonito.Lo canaliza en el
pv
que muestra información de progreso (-cN
le dice 'usa algún tipo de [c] ursor' y dale un [N] ame).Esa tubería en la
gzip
que obviamente hace la compresión (lectura de stdin, salida a stdout).Eso se canaliza a otro
pv
(vista de tubería).Eso entra
dd bs=$buffer iflag=fullblock
. La$buffer
variable es un número, algo así como 50 megabytes. Sin embargo, es la cantidad de RAM que desea dedicar al manejo seguro de su archivo (como punto de datos, el búfer de 50 MB para un archivo de 2 GB estaba bien). Leiflag=fullblock
dicedd
que lea hasta$buffer
bytes antes de pasarlo. Al principio, gzip escribirá un encabezado, por lo que la salida de gzip aterrizará en estadd
línea. Luegodd
esperará hasta que tenga suficientes datos antes de pasarlo, y así la entrada puede leer más. Además, si tiene partes no comprimibles, el archivo de salida puede ser más grande que el archivo de entrada. Este búfer se asegura de que, hasta$buffer
bytes, esto no sea un problema.Luego vamos a otra línea de vista de tubería y finalmente a nuestra
dd
línea de salida . Esta línea tieneof
(archivo de salida) yconv=notrunc
especificada, dondenotrunc
le dice add
no truncar (eliminar) el archivo de salida antes de escribir. Entonces, si tiene 500 bytesA
y escribe 3 bytesB
, el archivo seráBBBAAAAA...
(en lugar de ser reemplazado porBBB
).No cubrí las
2>/dev/null
partes, y son innecesarias. Simplemente arreglan un poco la salida suprimiendodd
el mensaje "Terminé y escribí estos bytes". Las barras invertidas al final de cada línea (\
) hacen que bash trate todo como un gran comando que se conecta entre sí.Aquí hay un script completo para un uso más fácil. Como anécdota, lo puse en una carpeta llamada 'gz-in-place'. Entonces me di cuenta del acrónimo que hice: GZIP: gnu zip in place. Por la presente les presento, GZIP.sh:
Tengo ganas de agregar otra línea de almacenamiento en búfer antes de gzip, para evitar que se escriba demasiado lejos cuando la
dd
línea de almacenamiento en búfer pasa, pero con solo 50 MiB de búfer y 1900 MB de/dev/urandom
datos, parece funcionar de todos modos (los md5sums coincidieron después de descomprimir). Buena relación para mí.Otra mejora sería la detección de la escritura demasiado lejos, pero no veo cómo hacerlo sin eliminar la belleza de la cosa y crear mucha complejidad. En ese momento, también podría convertirlo en un programa de Python completo que lo haga todo correctamente (con seguridad para evitar la destrucción de datos).
fuente