¿Cómo puedo determinar si ejecutar tar hará que el disco se llene


22

Si ejecuto tar -cvfen un directorio de tamaño 937MB para crear una copia fácilmente descargable de una estructura de carpetas profundamente anidada, ¿me arriesgo a llenar el disco dada la siguiente df -hsalida:

/dev/xvda1            7.9G  3.6G  4.3G  46% /
tmpfs                 298M     0  298M   0% /dev/shm

Preguntas relacionadas:

  • Si el disco puede llenarse, ¿por qué, por ejemplo, qué hará Linux (Amazon AMI) y / o qué estará tarhaciendo bajo el capó?
  • ¿Cómo puedo determinar esta información con precisión sin preguntar nuevamente?

No estoy seguro de si es posible sin procesar el archivo, pero puedes jugar con la --totalsopción. De cualquier manera, si llena el disco, simplemente puede eliminar el archivo, en mi humilde opinión. Para verificar todas las opciones disponibles, puede pasar tar --help.
UVV

44
Tangencialmente: no cree el archivo tar como root, un cierto porcentaje de espacio en el disco se reserva exclusivamente para root, exactamente para el tipo de "He llenado el disco y ahora no puedo iniciar sesión porque eso escribiría". bash_history o lo que sea "situación.
Ulrich Schwarz

Respuestas:


24

tar -c data_dir | wc -c sin compresión

o

tar -cz data_dir | wc -c con compresión gzip

o

tar -cj data_dir | wc -c con compresión bzip2

imprimirá el tamaño del archivo que se crearía en bytes, sin escribir en el disco. Luego puede compararlo con la cantidad de espacio libre en su dispositivo de destino.

Puede verificar el tamaño del directorio de datos en sí mismo, en caso de que se haya hecho una suposición incorrecta sobre su tamaño, con el siguiente comando:

du -h --max-depth=1 data_dir

Como ya se respondió, tar agrega un encabezado a cada registro en el archivo y también redondea el tamaño de cada registro a un múltiplo de 512 bytes (por defecto). El final de un archivo está marcado por al menos dos registros consecutivos llenos de cero. Por lo tanto, siempre tendrá un archivo tar sin comprimir más grande que los archivos, la cantidad de archivos y la forma en que se alinean con los límites de 512 bytes determina el espacio adicional utilizado.

Por supuesto, los sistemas de archivos en sí mismos usan tamaños de bloque que pueden ser más grandes que el contenido de un archivo individual, así que tenga cuidado donde lo descomprime, ¡es posible que el sistema de archivos no pueda contener muchos archivos pequeños aunque tenga espacio libre mayor que el tamaño del alquitrán!

https://en.wikipedia.org/wiki/Tar_(computing)#Format_details


Gracias Jamie! ¿Qué está haciendo '- mysql' aquí? ¿Es ese tu nombre de archivo?
codecowboy

Acabo de cambiar eso ... es la ruta a su directorio de datos.
FantasticJamieBurns

1
No es que realmente importe, pero usar la combinación de argumentos -f -para tar es redundante, ya que simplemente puede omitir el -fargumento por completo para escribir el resultado en stdout (es decir tar -c data_dir).

6

El tamaño de su archivo tar será de 937MB más el tamaño de los metadatos necesarios para cada archivo o directorio (512 bytes por objeto), y el relleno agregado para alinear los archivos a un límite de 512 bytes.

Un cálculo muy aproximado nos dice que otra copia de sus datos lo dejará con 3.4GB gratis. En 3.4GB tenemos espacio para aproximadamente 7 millones de registros de metadatos, suponiendo que no haya relleno, o menos, si supone un promedio de relleno de 256 bytes por archivo. Entonces, si tiene millones de archivos y directorios para tar, es posible que tenga problemas.

Podrías mitigar el problema al

  • comprimiendo sobre la marcha utilizando las opciones zojtar
  • haciendo esto tarcomo un usuario normal para que el espacio reservado en la /partición no se toque si se queda sin espacio.

2

taren sí mismo puede informar sobre el tamaño de sus archivos con la --testopción:

tar -cf - ./* | tar --totals -tvf -

El comando anterior no escribe nada en el disco y tiene el beneficio adicional de enumerar los tamaños de archivo individuales de cada archivo contenido en el tarball. Agregar los diversos z/j/xzoperandos a cada lado del |pipemanejará la compresión como lo hará.

SALIDA:

...
-rwxr-xr-x mikeserv/mikeserv         8 2014-03-13 20:58 ./somefile.sh
-rwxr-xr-x mikeserv/mikeserv        62 2014-03-13 20:53 ./somefile.txt
-rw-r--r-- mikeserv/mikeserv       574 2014-02-19 16:57 ./squash.sh
-rwxr-xr-x mikeserv/mikeserv        35 2014-01-28 17:25 ./ssh.shortcut
-rw-r--r-- mikeserv/mikeserv        51 2014-01-04 08:43 ./tab1.link
-rw-r--r-- mikeserv/mikeserv         0 2014-03-16 05:40 ./tee
-rw-r--r-- mikeserv/mikeserv         0 2014-04-08 10:00 ./typescript
-rw-r--r-- mikeserv/mikeserv       159 2014-02-26 18:32 ./vlc_out.sh
Total bytes read: 4300943360 (4.1GiB, 475MiB/s)

No estoy completamente seguro de su propósito, pero si es para descargar el tarball, esto podría ser más importante:

ssh you@host 'tar -cf - ./* | cat' | cat >./path/to/saved/local/tarball.tar

O simplemente copiar con tar:

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -

La razón por la que estoy haciendo esto es porque creo que el directorio en cuestión ha causado que la salida de df -i alcance el 99%. Quiero guardar una copia del directorio para un análisis más detallado, pero quiero limpiar el espacio
Codecowboy

@codecowboy En ese caso, definitivamente deberías hacer algo como lo anterior primero. Será tarentonces copiar el árbol en el disco local en una corriente sin guardar nada en el disco remoto en absoluto, después de lo cual se puede eliminar desde el host remoto y restaurarla más tarde. Probablemente debería agregar -zpara la compresión como señala goldilocks, para ahorrar en el ancho de banda a mitad de la transferencia.
mikeserv

@ TAFKA 'goldilocks' No, porque es el 99% de los inodos, no el 99% del espacio.
Gilles 'SO- deja de ser malvado'

-ibien, lo siento!
Ricitos

@mikeserv su línea de apertura menciona la opción --test pero parece que no la usa en su comando que sigue inmediatamente (usa --totals)
codecowboy

2

He investigado mucho sobre esto. Puede hacer una prueba en el archivo con un recuento de palabras, pero no le dará el mismo número de número que a du -sb adir.

tar -tvOf afile.tar | wc -c

ducuenta cada directorio como 4096 bytes y tarcuenta los directorios como 0 bytes. Debe agregar 4096 a cada directorio:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096)))

entonces tienes que agregar todos los personajes. Para algo que se parece a esto:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096 + $(tar -xOf afile.tar | wc -c) ))

No estoy seguro de si esto es perfecto ya que no probé archivos que han sido tocados (archivos de 0 bytes) o archivos que tienen 1 carácter. Esto debería acercarte más.


1

-cvfno incluye ninguna compresión, por lo que hacerlo en una carpeta de ~ 1 GB dará como resultado un archivo tar de ~ 1 GB (la respuesta de Flub tiene más detalles sobre el tamaño adicional en el archivo tar, pero tenga en cuenta que incluso si hay 10,000 archivos esto es solo 5 MB). Como tienes más de 4 GB gratis, no, no llenarás la partición.

una copia fácilmente descargable

La mayoría de las personas consideraría "más fácil" como sinónimo de "más pequeño" en términos de descarga, por lo que debe usar algo de compresión aquí. bzip2debería estar disponible en cualquier sistema con tar, creo, por lo que incluirlos jen sus conmutadores es probablemente la mejor opción. z( gzip) es quizás aún más común, y hay otras posibilidades (menos ubicuas) con más squash.

Si quiere decir, si tarutiliza temporalmente espacio adicional en el disco para realizar la tarea, estoy bastante seguro de que no lo hace por varias razones, una de ellas se remonta a una época en que las unidades de cinta eran una forma de almacenamiento primario, y dos eran tuvo décadas para evolucionar (y estoy seguro de que no es necesario utilizar un espacio intermedio temporal, incluso si se trata de compresión).


0

Si la velocidad es importante y no se necesita compresión, puede enganchar los envoltorios de syscall que se tarusan LD_PRELOAD, para cambiarlos tary calcularlos por nosotros. Al reimplementar algunas de estas funciones para satisfacer nuestras necesidades (calcular el tamaño de los datos de alquitrán de salida potencial), podemos eliminar muchas ready writeeso se realiza en la operación normal de tar. Esto es tarmucho más rápido, ya que no es necesario cambiar de contexto de un lado a otro en el kernel ni mucho menos, y solo el stat/ los archivo / carpeta (s) de entrada solicitados debe leerse desde el disco en lugar de los datos del archivo real.

El código siguiente incluye implementaciones de las close, ready writefunciones POSIX. La macro OUT_FDcontrola qué descriptor de archivo esperamos tarusar como archivo de salida. Actualmente está configurado en stdout.

readse cambió para devolver el valor de éxito de countbytes en lugar de llenar buf con los datos, dado que los datos reales no se leyeron buf no contendrían datos válidos para pasar a compresión, y por lo tanto, si se usara compresión, calcularíamos tamaño.

writese modificó para sumar los countbytes de entrada en la variable global totaly devolver el valor de éxito de los countbytes solo si el descriptor de archivo coincide OUT_FD, de lo contrario, llama al reiniciador original adquirido a través dlsymde realizar la llamada al sistema del mismo nombre.

closetodavía realiza todas sus funciones originales, pero si el descriptor de archivo coincide con OUT_FD, sabe que tarse ha intentado escribir un archivo tar, por lo que el totalnúmero es final y lo imprime en stdout.

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>

#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
    printf("%" PRIu64 "\n", total);
}

int close(int fd)
{
    if(! original_close)
    {
        original_close = dlsym(RTLD_NEXT, "close");
    }
    if(fd == OUT_FD)
    {
        print_total();
    }
    return original_close(fd);
}

ssize_t read(int fd, void *buf, size_t count)
{
    return count;
}

ssize_t write(int fd, const void *buf, size_t count)
{
    if(!original_write)
    {
        original_write = dlsym(RTLD_NEXT, "write");
    }
    if(fd == OUT_FD)
    {
        total += count;
        return count;
    }
    return original_write(fd, buf, count);
}

Prueba comparativa que compara una solución en la que el acceso al disco de lectura y todas las llamadas al sistema de la operación normal de tar se realizan contra la LD_PRELOADsolución.

$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real    0m0.457s
user    0m0.064s
sys     0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real    0m0.016s
user    0m0.004s
sys     0m0.008s

El código anterior, un script de compilación básico para compilar lo anterior como una biblioteca compartida, y un script con la " LD_PRELOADtécnica" que lo usa se proporciona en el repositorio: https://github.com/G4Vi/tarsize

Alguna información sobre el uso de LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/


El código es bueno, si funciona, pero ¿puedes describir lo que hace? Por favor no responda en los comentarios; edite  su respuesta para que sea más clara y completa.
G-Man dice 'reinstalar a Monica' el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.