cat / dev / null> file.log não trunca arquivo grande no Darwin

15

No passado, em sistemas linux, eu era capaz de truncar arquivos de log grandes e abertos (ou seja, um arquivo que está sendo gravado ativamente por um processo) usando cat /dev/null > file.log.

No entanto, no 10.9 (Mavericks), esse não parece ser o caso. Eu tenho um arquivo de 11 GB que está sendo registrado por um aplicativo, mas quando executo o mesmo comando com esse arquivo, nada parece acontecer.

Quando eu tento isso em um arquivo de tamanho trivial, ele funciona.

Aqui está ls -l /dev/null:

crw-rw-rw- 1 root wheel 3, 2 Dec 16 12:49 /dev/null

Eu também tentei cp /dev/null file.logsem sucesso.

Pensando que eu poderia tirar proveito da função truncada ( man 2 truncateem Darwin), compilei isso e executei-o em dois arquivos, um de tamanho trivial e outro no arquivo de log real. Novamente, funcionou contra o arquivo trivial e não funcionou no log muito maior.

/*
 * Copyright (c) 2013 Thomas de Grivel <[email protected]>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 ...
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <unistd.h>

int main (int argc, const char **argv)
{
        int e = 0;
        while (--argc) {
                argv++;
                if (truncate(*argv, 0)) {
                        e = 4;
                        warn("%s", *argv);
                }
        }
        return e;
}

O processo retorna 0independentemente de qual arquivo eu uso.

chb
fonte
Como você sabe que não funcionou? O que diz duou du -hdiz? É possível que o arquivo seja um arquivo esparso?
Mikel
2
Além disso, qual é o objetivo de incluir uma licença neste post? Parece apenas adicionar ruído.
Mikel
du -h /tmp/file.logresultados em11G /tmp/file.log
chb
@ Mikel Eu incluí a licença como cortesia ... você notará que eu redigi a maior parte dela.
CHB
11
a licença é uma distração, a verdadeira jóia aqui é a resposta
Iruvar

Respostas:

12

cat /dev/nullé um pouco complicado uma maneira de escrever um comando que não produz saída. :ou truesão mais óbvias.

Em todos cat /dev/null > file, : > filee até mesmo > filena maioria das conchas, o shell abre arquivo com O_TRUNC em stdout, em seguida, executa o aplicativo que não faz nada de saída, em seguida, o arquivo é fechado e deixou truncado.

No entanto, nesse caso ou ao usar a truncatechamada do sistema, se o processo que está preenchendo esse arquivo não o abriu com o sinalizador O_APPEND, na próxima vez em que ele gravar no descritor de arquivo aberto no arquivo, ele gravará os dados no deslocamento estavam dentro do arquivo.

Como o HFS + não suporta arquivos esparsos, isso significa que o espaço antes desse deslocamento precisará ser realocado e preenchido com zeros pelo sistema.

Portanto, você precisa matar o aplicativo que está gravando nesse arquivo antes de truncá-lo. Ou você precisa garantir que o aplicativo abra o arquivo O_APPEND(como no >>caso de usar o redirecionamento de shell).

Se você quiser experimentar:

$ exec 3> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:32 x

Agora, o fd 3 do meu shell tem 100000 bytes no arquivo

$ : > x
$ ls -ls x
0 -rw-r--r--  1 me me  0 Dec 16 21:34 x

Agora o arquivo está truncado (tamanho 0, sem espaço usado no disco).

$ echo >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100001 Dec 16 21:34 x

Gravando 1 byte no arquivo no deslocamento 100000, o arquivo agora tem 100001 bytes de tamanho, os primeiros zeros, usariam mais de 100k no HFS +, mas apenas um bloco de disco na maioria dos outros sistemas de arquivos Unix

Por outro lado, com:

$ exec 3>> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:35 x
$ : > x
$ echo >&3
$ ls -ls x
8 -rw-r--r--  1 me me  1 Dec 16 21:36 x

A gravação de 1 byte no arquivo não está no deslocamento 100000, mas no final do arquivo por causa de O_APPEND. O arquivo tem 1 byte de tamanho e ocupa o espaço necessário para armazenar esse byte.

Stéphane Chazelas
fonte
11
Eu aprendi muito com essa resposta. Obrigado.
Chb