GNU/Linux >> Tutoriales Linux >  >> Linux

Truncar un archivo mientras se está utilizando (Linux)

A partir de coreutils 7.0, hay un truncate comando.


Lo interesante de esos archivos regenerados es que los primeros 128 KB serán todos ceros después de truncar el archivo copiando /dev/null encima de eso. Esto sucede porque el archivo se trunca a la longitud cero, pero el descriptor del archivo en la aplicación aún apunta inmediatamente después de su última escritura. Cuando vuelve a escribir, el sistema de archivos trata el inicio del archivo como cero bytes, sin escribir realmente los ceros en el disco.

Idealmente, debe pedirle al proveedor de la aplicación que abra el archivo de registro con el O_APPEND bandera. Esto significa que después de truncar el archivo, la siguiente escritura buscará implícitamente hasta el final del archivo (es decir, volverá al desplazamiento cero) y luego escribirá la nueva información.

Este código manipula la salida estándar para que esté en O_APPEND mode y luego invoca el comando dado por sus argumentos (más bien como nice ejecuta un comando después de ajustar su nivel agradable, o nohup ejecuta un comando después de arreglar las cosas, por lo que ignora SIGHUP).

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

static char *arg0 = "<unknown>";

static void error(const char *fmt, ...)
{
    va_list args;
    int errnum = errno;
    fprintf(stderr, "%s: ", arg0);
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
    putc('\n', stderr);
    fflush(0);
    exit(1);
}

int main(int argc, char **argv)
{
    int attr;
    arg0 = argv[0];

    if (argc < 2)
        error("Usage: %s cmd [arg ...]", arg0);
    if ((attr = fcntl(1, F_GETFL, &attr)) < 0)
        error("fcntl(F_GETFL) failed");
    attr |= O_APPEND;
    if (fcntl(1, F_SETFL, attr) != 0)
        error("fcntl(F_SETFL) failed");
    execvp(argv[1], &argv[1]);
    error("failed to exec %s", argv[1]);
    return(1);
}

Mi prueba fue algo casual, pero apenas lo suficiente para convencerme de que funcionaba.

Alternativa más sencilla

Billy anota en su respuesta que '>> ' es el operador de adición y, de hecho, en Solaris 10, bash (versión 3.00.16(1)) utiliza el O_APPEND bandera - por lo que el código anterior es innecesario, como se muestra ('Black JL:' es mi mensaje en esta máquina):

Black JL: truss -o bash.truss bash -c "echo Hi >> x3.29"
Black JL: grep open bash.truss
open("/var/ld/ld.config", O_RDONLY)             Err#2 ENOENT
open("/usr/lib/libcurses.so.1", O_RDONLY)       = 3
open("/usr/lib/libsocket.so.1", O_RDONLY)       = 3
open("/usr/lib/libnsl.so.1", O_RDONLY)          = 3
open("/usr/lib/libdl.so.1", O_RDONLY)           = 3
open("/usr/lib/libc.so.1", O_RDONLY)            = 3
open("/platform/SUNW,Ultra-4/lib/libc_psr.so.1", O_RDONLY) = 3
open64("/dev/tty", O_RDWR|O_NONBLOCK)           = 3
stat64("/usr/openssl/v0.9.8e/bin/bash", 0xFFBFF2A8) Err#2 ENOENT
open64("x3.29", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
Black JL:

Utilice la redirección de datos adjuntos en lugar del código contenedor ('cantrip') anterior. Esto solo demuestra que cuando usa una técnica en particular para otros fines (válidos), adaptarla a otra no es necesariamente el mecanismo más simple, aunque funcione.


Redirija la salida usando>> en lugar de>. Esto le permitirá truncar el archivo sin que vuelva a crecer a su tamaño original. Además, no olvide redirigir STDERR (2>&1).

Entonces el resultado final sería:myprogram >> myprogram.log 2>&1 &


Linux
  1. Cómo mover un archivo en Linux

  2. Conceptos básicos de los permisos de archivos de Linux

  3. Linux – ¿Todo es un archivo?

  4. ¿Es seguro usar Rsync mientras se actualiza la fuente?

  5. ¿Por qué se usa select en Linux?

Comando Gunzip en Linux

Comando Stat en Linux

¿Qué es umask en Linux?

Cómo vincular un archivo en Linux

Comandos de Linux utilizados con frecuencia por los administradores de sistemas de Linux - Parte 5

Extraiga el archivo tar.gz en Linux