Tengo un proceso embarazosamente paralelo que crea una gran cantidad de archivos casi (pero no completamente) idénticos. ¿Hay alguna manera de archivar los archivos "sobre la marcha", para que los datos no consuman más espacio del necesario?
El proceso en sí mismo acepta parámetros de línea de comandos e imprime el nombre de cada archivo creado para stdout. Lo invoco con el parallel --gnu
que se encarga de distribuir la entrada (que proviene de otro proceso) y recopilar la salida:
arg_generating_process | parallel --gnu my_process | magic_otf_compressor
EJEMPLO SIMPLE para la primera parte de la tubería en bash
:
for ((f = 0; $f < 100000; f++)); do touch $f; echo $f; done
¿Cómo podría magic_otf_compressor
verse? Se supone que debe tratar cada línea de entrada como nombre de archivo, copiar cada archivo a un .tar
archivo comprimido (¡el mismo archivo para todos los archivos procesados!) Y luego eliminarlo. (En realidad, debería ser suficiente para imprimir el nombre de cada archivo procesado, otro | parallel --gnu rm
podría encargarse de eliminar los archivos).
¿Existe alguna herramienta de este tipo? No estoy considerando comprimir cada archivo individualmente, esto desperdiciaría demasiado espacio. He investigado archivemount
(mantendrá el sistema de archivos en la memoria -> imposible, mis archivos son demasiado grandes y demasiados) y avfs
(no pude hacer que funcione junto con FUSE). ¿Qué me he perdido?
Estoy a un paso de hackear una herramienta así, pero alguien debe haberlo hecho antes ...
EDITAR : Básicamente creo que estoy buscando un front-end stdin para libtar
(a diferencia del front-end de la línea de comandos tar
que lee argumentos de, bueno, la línea de comandos).
fuente
Respuestas:
Parece que
tar
quiere saber todos los nombres de archivo por adelantado. Entonces es menos sobre la marcha y más después de la marcha.cpio
no parece tener ese problema:fuente
tar
el código para ver que hay una función que devuelve el siguiente nombre de archivo para ser procesado, lo que me hizo leer la documentación nuevamente. - Entonces, ¿stdout
se dirige algzip
proceso a través de la sustitución del proceso ystderr
se redirige astdout
cuál se procesa en el siguiente paso en la tubería?tar
lee la lista de archivos primero, usando el ejemplo simple que agregué a mi pregunta. Sin embargo, al leertar
el código fuente nuevamente, me parece que debería leer la lista de archivos "sobre la marcha" si no se crea un archivo incremental. Desafortunadamente, tengo errores al compilartar
desde la fuente ... :-(cpio
, aparte degrep -v 'blocks$'
. (head -n -1
usa un búfer muy grande ...) Hace que esta solución sea un poco hack, pero no importa ;-)head -n -1
solo usa 16 MB cuando se ejecuta con unos pocos GB de datos. Siempre puede usar perl: perl -ne 'print $ last; $ last = $ _'Un caso clásico de RTFM (¡todo!) . La
-T
opción de GNUtar
leerá los archivos que se archivarán desde otro archivo (en mi caso,/dev/stdin
también puede usar-
), e incluso hay una--remove-files
opción:(usando la versión paralela de
xz
para la compresión, pero puede usar su compresor preferido en su lugar). Para ser utilizado como:EDITAR : Como señala Ole,
tar
parece leer la lista completa de archivos con la-T
opción por alguna razón. La siguiente prueba confirma esto:Hay un segundo retraso en mi sistema antes de que todos los archivos se impriman a la vez; en cambio, si el
tar
comando se reemplaza porcat
, todos los archivos se imprimen a medida que se crean. He presentado una solicitud de soporte con la gente de alquitrán, veamos.EDITAR ^ 2 : El más reciente
tar
de la fuente corrige esto. Todavía no está en Ubuntu 13.10, pero podría incluirse con 14.04.fuente
De alguna manera, esto no parece un buen trabajo para un compresor sólido (archivadores basados en cinta + compresión). Insertar archivos uno tras otro parece un trabajo
zip
o algún otro formato que permita el acceso aleatorio a los archivos dentro del archivo y la inserción incremental.El hecho de que los archivos sean similares no ayudará mucho en ninguno de los casos. En
zip
, los archivos se comprimen por separado, y en los compresores sólidos, generalmente hay una ventana dentro de la cual tiene lugar la compresión.Si los archivos están basados en texto, puede almacenar diferencias en comparación con un solo archivo de referencia. Para binario, es un poco más complicado pero se puede hacer.
También hay una forma formal (no solo de escritura, sino de sistemas de archivos adecuados). Por ejemplo, los sistemas de archivos ZFS y BTRFS ofrecen una compresión transparente. También puede usar este http://developer.berlios.de/projects/fusecompress
fuente
xz
parece funcionar con un tamaño de diccionario predeterminado de 8M (en el nivel de compresión predeterminado-6
), lo que parece ser suficiente para mi caso de uso. - Las diferencias en un archivo de referencia son buenas, pero primero se requiere construir un archivo de referencia. ¿Un sistema de archivos de compresión detectaría archivos con contenido casi idéntico?btrfs
tienen copia en escritura, por lo que si copia un archivo y modifica una parte del mismo, solo guarda las partes que ha cambiado. Si no está creando archivos de esta manera, supuestamente existen herramientas de deduplicación , pero aúnbtrfs
no es un sistema de archivos maduro y estable y la deduplicación se encuentra en las primeras etapas de desarrollo. Pero ahora que lo pienso, ¿qué pasa con lessfs.com/wordpressPuede que no parezca obvio, pero apuesto a
squashfs
que sería perfecto para esto, e incluso está implementado en el núcleo. Desde la versión 4.1squashfs
puede manejar pseudo archivos como se especifica en lamksquash
línea de comando o mediante un script de shell ymksquashfs
generará los archivos a medida que crea el archivo.Puede manejar tuberías , por ejemplo, puede capturar otro proceso
stdout
en un archivo de squash montable, incluso quince , es bastante genial. En su caso, si se pudiera encontrar la logística de secuencia de comandos de la tubería de salida de su proceso a través de él, se puede envolver su proceso enteramente enmksquashfs
y terminar con un único archivo. Aquí hay un poco dereadme
cómo funciona y hay más aquí :fuente
test
y un archivofile
en este directorio. ¿Podría por favor dar un breve ejemplo?