Sistema de arquivos somente de gravação virtual para armazenar arquivos em archive

8

Eu tenho um processo embaraçosamente paralelo que cria uma enorme quantidade de quase (mas não completamente) arquivos idênticos. Existe uma maneira de arquivar os arquivos "on the fly", para que os dados não consumam mais espaço do que o necessário?

O próprio processo aceita parâmetros de linha de comando e imprime o nome de cada arquivo criado para stdout. Estou chamando-o com parallel --gnu , que cuida da distribuição de entrada (que vem de outro processo) e coleta de saída:

arg_generating_process | parallel --gnu my_process | magic_otf_compressor

EXEMPLO SIMPLES para a primeira parte do pipe em bash :

for ((f = 0; $f < 100000; f++)); do touch $f; echo $f; done

Como pode ser magic_otf_compressor ? É suposto tratar cada linha de entrada como nome de arquivo, copiar cada arquivo para um% compactado.tar archive (o mesmo arquivo para todos os arquivos processados!) E, em seguida, excluí-lo. (Na verdade, deve ser o suficiente para imprimir o nome de cada arquivo processado, outro | parallel --gnu rm pode cuidar da exclusão dos arquivos.)

Existe alguma ferramenta desse tipo? Eu não estou pensando em compactar cada arquivo individualmente, isso iria desperdiçar muito espaço. Eu olhei em archivemount (manterá o sistema de arquivos na memória - > impossível, meus arquivos são muito grandes e muitos) e avfs (não consegui fazê-lo funcionar junto com o FUSE). O que eu perdi?

Estou a apenas um passo de invadir essa ferramenta, mas alguém deve ter feito isso antes ...

EDIT : Essencialmente, acho que estou procurando um front-end de stdin para libtar (em oposição ao front-end de linha de comando tar que lê argumentos de, bem, a linha de comando).

    
por krlmlr 11.03.2014 / 15:37

4 respostas

1

Parece que tar quer saber todos os nomes dos arquivos antecipadamente. Por isso, é menos on-the-fly e mais after-the-fly. cpio parece não ter esse problema:

| cpio -vo 2>&1 > >(gzip > /tmp/arc.cpio.gz) | parallel rm
    
por 12.03.2014 / 09:22
7

Um caso clássico de RTFM (tudo isso!) . A opção -T para GNU tar lerá os arquivos a serem arquivados de outro arquivo (no meu caso, /dev/stdin , você também pode usar - ), e há até mesmo uma opção --remove-files :

alias magic_otf_compressor='tar --create -T - --remove-files -O | pixz'

(usando a versão paralela de xz para compactação, mas você pode usar o seu compressor preferido). Para ser usado como:

arg_generating_process |
  parallel --gnu my_process |
  magic_otf_compressor > file.tar.xz

EDIT : Como Ole aponta, tar parece ler toda a lista de arquivos com a opção -T por algum motivo. O teste a seguir confirma isso:

for ((f = 0; $f < 1000; f++)); do
    touch $f; echo $f;
done | tar -c -f otf.tar -T - -v

Há um atraso de um segundo no meu sistema antes que todos os arquivos sejam impressos de uma só vez; Por outro lado, se o comando tar for substituído por cat , todos os arquivos serão impressos à medida que forem criados. Eu arquivei uma solicitação de suporte com o pessoal do tar, vamos ver.

EDIT ^ 2 : O mais recente tar da origem corrige isso. Ainda não está no Ubuntu 13.10, mas pode estar incluído no 14.04.

    
por 11.03.2014 / 17:17
1

De alguma forma, isso não parece ser um bom trabalho para um compressor sólido (arquivadores baseados em fita + compactação). A inserção de arquivos um após o outro parece um trabalho para zip ou algum outro formato que permita acesso aleatório a arquivos no arquivo e inserção incremental.

O fato de os arquivos serem semelhantes não ajuda muito em nenhum dos casos. Em zip , os arquivos são compactados separadamente e, em compressores sólidos, geralmente há uma janela na qual a compactação ocorre.

Se os arquivos forem baseados em texto, você poderá armazenar os diffs em comparação com um único arquivo de referência. Para binário, é um pouco mais complicado, mas pode ser feito.

Há também uma maneira formal (não apenas de gravação, mas sistemas de arquivos apropriados). Por exemplo, os sistemas de arquivos ZFS e BTRFS oferecem compactação transparente. Você também pode usar este link

    
por 12.03.2014 / 10:35
0

Pode não parecer óbvio, mas aposto que squashfs seria perfeito para isso - e é mesmo implementado no kernel. Como a versão 4.1 squashfs pode manipular pseudo arquivos conforme especificado na linha de comando mksquash ou através de um script shell e mksquashfs gerará os arquivos conforme cria o arquivo.

Ele pode manipular pipes - por exemplo, você pode capturar stdout de outro processo em um arquivo de squash montável - até fifos - é bem legal. No seu caso, se você pudesse elaborar a logística do script de canalizar a saída do seu processo através dela, você poderia envolver completamente o seu processo em mksquashfs e acabar com um único arquivo. Aqui está um pouco do readme sobre como funciona e há mais aqui :

Mksquashfs 4.1 adds support for "dynamic pseudo files" and a modify operation. Dynamic pseudo files allow files to be dynamically created when Mksquashfs is run, their contents being the result of running a command or piece of shell script. The modifiy operation allows the mode/uid/gid of an existing file in the source filesystem to be modified.

Creating dynamic file examples

Create a file "dmesg" containing the output from dmesg.

    dmesg f 444 root root dmesg

Create a file RELEASE containing the release name, date, build host, and an incrementing version number. The incrementing version is a side-effect of executing the shell script, and ensures every time Mksquashfs is run a new version number is used without requiring any other shell scripting.

    RELEASE f 444 root root \
        if [ ! -e /tmp/ver ]; then \
        echo 0 > /tmp/ver; \
        fi; \
        ver='cat /tmp/ver'; \
            ver=$((ver +1)); \
            echo $ver > /tmp/ver; \
            echo -n "release x.x"; \
            echo "-dev #"$ver 'date' "Build host" 'hostname'

Copy 10K from the device /dev/sda1 into the file input. Ordinarily Mksquashfs given a device, fifo, or named socket will place that special file within the Squashfs filesystem, this allows input from these special files to be captured and placed in the Squashfs filesystem.

        input f 444 root root dd if=/dev/sda1 bs=1024 count=10
    
por 12.03.2014 / 13:35