cat / dev / null file.log não trunca arquivos grandes em Darwin

15

No passado, em sistemas Linux, eu conseguia truncar grandes arquivos de log abertos (isto é, um arquivo que estava sendo escrito ativamente por um processo) usando cat /dev/null > file.log .

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

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

Aqui está o 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.log sem sucesso.

Pensando que eu poderia tirar proveito da função truncate ( man 2 truncate em Darwin) eu compilei isso e executei-o em dois arquivos, um de tamanho trivial e o outro, o 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 0 , independentemente do arquivo que eu uso.

    
por chb 16.12.2013 / 21:22

1 resposta

12

cat /dev/null é uma maneira pouco complicada de escrever um comando que não produz saída. : ou true são mais óbvios.

Em todos os cat /dev/null > file , : > file e mesmo > file na maioria dos shells, o shell abre o arquivo com O_TRUNC no stdout, em seguida, executa o aplicativo que não produz nada, então o arquivo é fechado e deixado truncado.

No entanto, nesse caso ou ao usar a chamada de sistema truncate , se o processo que está preenchendo esse arquivo não abri-lo com o sinalizador O_APPEND, na próxima vez que ele gravar no descritor de arquivo, ele abrirá o arquivo, ele gravará os dados no deslocamento que estava 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.

Então, você precisa matar o aplicativo que está gravando no arquivo antes de truncá-lo. Ou você precisa garantir que o aplicativo abra o arquivo com O_APPEND (como com >> se estiver usando 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 é 100000 bytes dentro do 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

Escrevendo 1 byte para o arquivo no deslocamento 100000, o arquivo é agora 100001 bytes grandes, os primeiros todos os zeros, usariam mais de 100k no HFS +, mas sobre apenas um bloco de disco na maioria dos 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

Escrevendo 1 byte para o arquivo não no deslocamento 100000, mas no final do arquivo por causa de O_APPEND . O arquivo tem 1 byte e ocupa o espaço necessário para segurar aquele byte.

    
por 16.12.2013 / 22:18

Tags