cat / dev / null> file.log no trunca archivos grandes en Darwin

15

En el pasado, en los sistemas Linux, he podido truncar archivos de registro grandes y abiertos (es decir, un archivo en el que un proceso está escribiendo activamente) usando cat /dev/null > file.log.

Sin embargo, en 10.9 (Mavericks), ese no parece ser el caso. Tengo un archivo de 11GB que está siendo registrado por una aplicación, pero cuando ejecuto el mismo comando con dicho archivo, parece que no pasa nada.

Cuando intento esto en un archivo de tamaño trivial, funciona.

Aqui esta ls -l /dev/null:

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

También he tratado cp /dev/null file.logen vano.

Pensando que podría aprovechar la función truncada ( man 2 truncateen Darwin), compilé esto y lo ejecuté contra dos archivos, uno de tamaño trivial y el otro el archivo de registro real. Nuevamente, funcionó contra el archivo trivial y no funcionó en el registro mucho más grande.

/*
 * 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;
}

El proceso regresa 0independientemente del archivo que use.

chb
fuente
¿Cómo sabes que no funcionó? ¿Qué hace duo du -hdice? ¿Es posible que el archivo sea escaso?
Mikel
2
Además, ¿cuál es el propósito de incluir una licencia en esta publicación? Parece que solo agrega ruido.
Mikel
du -h /tmp/file.logresultados en11G /tmp/file.log
chb
@Mikel Incluí la licencia como cortesía ... notarás que eliminé la mayor parte.
chb
1
la licencia es una distracción, la verdadera joya aquí es la respuesta
iruvar

Respuestas:

12

cat /dev/nulles un poco complicado una forma de escribir un comando que no produce salida. :o trueson más obvios.

En todos cat /dev/null > file, : > filee incluso > fileen la mayoría de los depósitos, la cáscara se abre archivo con O_TRUNC en la salida estándar, a continuación, ejecuta la aplicación que no hace nada de salida, entonces el archivo se cierra y se deja trunca.

Sin embargo, en ese caso o al usar la truncatellamada al sistema, si el proceso que está llenando ese archivo no lo abrió con el indicador O_APPEND, la próxima vez que escriba en el descriptor de archivo que tiene abierto en el archivo, escribirá los datos en el desplazamiento estaban dentro del archivo.

Debido a que HFS + no admite archivos dispersos, eso significa que el espacio antes de ese desplazamiento tendrá que ser reasignado y llenado por ceros por el sistema.

Por lo tanto, debe eliminar la aplicación que está escribiendo en ese archivo antes de truncarlo. O debe asegurarse de que la aplicación abra el archivo con O_APPEND(como con >>si usa la redirección de shell).

Si quieres experimentar con él:

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

Ahora el fd 3 de mi shell tiene 100000 bytes dentro del archivo

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

Ahora el archivo está truncado (tamaño 0, no se utiliza espacio en el disco).

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

Al escribir 1 byte en el archivo en el desplazamiento 100000, el archivo ahora tiene un tamaño de 100001 bytes, los primeros todos ceros, usarían más de 100k en HFS +, pero solo un bloque de disco en la mayoría de los otros sistemas de archivos Unix

Por otro lado, con:

$ 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

Escribir 1 byte en el archivo no en el desplazamiento 100000, sino al final del archivo debido a O_APPEND. El archivo es de 1 byte y ocupa el espacio necesario para contener ese byte.

Stéphane Chazelas
fuente
1
Aprendí mucho de esta respuesta. Gracias.
chb