A saída do cat foi modificada ao gravar no arquivo

0

Com uma sequência de comandos canalizada como:

$ cat afile | somecommand | tee afile

afile é lido (por gato) e escrito (por tee). A questão é, supondo que afile é pelo menos vários megabytes (ou grande o suficiente para não ser totalmente armazenado em buffer pelo sistema operacional), será que os bytes posteriores no arquivo lido pelo gato serão afetados quando tee começa a gravar no arquivo?

Em outras palavras, é possível que o tee sobrescreva o arquivo antes que o gato termine com ele?

    
por adelphus 10.02.2015 / 16:49

2 respostas

1

Em um conjunto de processos em pipeline, é quase sempre um erro terrível escrever em um arquivo que também está sendo lido ao mesmo tempo.

Isso ocorre porque as operações de gravação ocorrem simultaneamente com as operações de leitura. Geralmente resultando em um arquivo prematuramente truncado. No passado, isso surpreendeu as pessoas mais acostumadas com pipelines DOS, onde o sistema operacional serializava os processos por meio de arquivos temporários ocultos (ou seu equivalente moral)

As soluções envolvem principalmente o uso de arquivos temporários e sua renomeação após a conclusão.

somecommand < infile | tee tempfile; mv tempfile infile

Obviamente, isso pode introduzir outros problemas.

Alguns utilitários (awk, perl etc) lidam com isso para você se você der a eles opções de linha de comando apropriadas.

perl -i -e 'somecommands' infile ... 

Observe que o problema que você enfrenta não tem nada a ver com cat . No meu exemplo, evitei uso desnecessário de gatos , em parte para deixar isso claro, em parte por tradição.

    
por 10.02.2015 / 18:08
0

Algumas experiências para meu próprio prazer (e para qualquer outra pessoa interessada na questão). Eu gerou umafile de 100 MB% usando / dev / urandom e tentei alguns pipelines e redirecionamentos usando o mesmo arquivo.

A maioria dos seguintes comandos não faz sentido lógico (como um resultado "bem-sucedido" deve manter o arquivo inalterado) e também deve ser notado que se arquivos diferentes forem especificados para entrada e saída, todos os comandos resultarão em uma cópia completa da entrada.

Veja alguns dos resultados:

$ cat <afile >afile

Definição: cat stdin do arquivo e redirecionamento para arquivo. Resultado: afile é truncado (0 bytes)

$ cat afile|cat >afile

Definição: cat arquivo e pipe stdout para outro gato, redirecionado para o arquivo. Resultado: afile é truncado (0 bytes)

$ tee afile <afile >/dev/null

Definição: tee stdin do afile e escreve no afile (e redireciona o stdout para / dev / null). Resultado: afile é truncado (0 bytes)

$ cat afile|tee afile >/dev/null

Definição: cat afile e pipe stdout to tee (e redireciona o tee stdout para / dev / null). Resultado: afile é reduzido para 128 KB

A última entrada mostra o problema com mais clareza: o cat só consegue fazer o buffer de 128 KB e canalizá-lo para o tee antes que o arquivo desapareça. Então, se o seu arquivo é pequeno, você pode ter sorte, mas é melhor dar atenção à resposta e sempre separar arquivos de entrada e saída.

    
por 10.02.2015 / 22:56

Tags